mirror of
https://github.com/hmalik144/easy_cc_flutter.git
synced 2025-12-10 03:05:34 +00:00
Merge pull request #18 from hmalik144/homescreen_widget_creation
Homescreen widget creation
This commit is contained in:
@@ -47,7 +47,7 @@ android {
|
|||||||
applicationId "com.appttude.h_mal.easycc"
|
applicationId "com.appttude.h_mal.easycc"
|
||||||
// You can update the following values to match your application needs.
|
// You can update the following values to match your application needs.
|
||||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
||||||
minSdkVersion flutter.minSdkVersion
|
minSdkVersion localProperties.getProperty('flutter.minSdkVersion').toInteger()
|
||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
@@ -68,4 +68,5 @@ flutter {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,33 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity android:name="com.appttude.h_mal.easycc.CurrencyAppWidgetConfigureActivity"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
|
|
||||||
|
<!-- Home Widget -->
|
||||||
|
<receiver android:name="AppWidgetProvider" android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/currency_app_widget_info" />
|
||||||
|
</receiver>
|
||||||
|
<receiver android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver" android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="es.antonborri.home_widget.action.BACKGROUND" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
<service android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
|
||||||
|
android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true"/>
|
||||||
|
<!-- Home Widget -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package com.appttude.h_mal.easycc
|
||||||
|
|
||||||
|
import android.appwidget.AppWidgetManager
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.net.Uri
|
||||||
|
import android.widget.RemoteViews
|
||||||
|
import android.widget.Toast
|
||||||
|
import es.antonborri.home_widget.HomeWidgetBackgroundIntent
|
||||||
|
import es.antonborri.home_widget.HomeWidgetLaunchIntent
|
||||||
|
import es.antonborri.home_widget.HomeWidgetPlugin
|
||||||
|
import es.antonborri.home_widget.HomeWidgetProvider
|
||||||
|
|
||||||
|
|
||||||
|
class AppWidgetProvider : HomeWidgetProvider(){
|
||||||
|
override fun onUpdate(
|
||||||
|
context: Context,
|
||||||
|
appWidgetManager: AppWidgetManager,
|
||||||
|
appWidgetIds: IntArray,
|
||||||
|
widgetData: SharedPreferences
|
||||||
|
) {
|
||||||
|
appWidgetIds.forEach { widgetId ->
|
||||||
|
val views = RemoteViews(context.packageName, R.layout.currency_app_widget).apply {
|
||||||
|
// Data from background operation received
|
||||||
|
val from: String? = widgetData.getString("${widgetId}_from", null)
|
||||||
|
val to: String? = widgetData.getString("${widgetId}_to", null)
|
||||||
|
val rate: String? = widgetData.getString("${widgetId}_rate", null)
|
||||||
|
|
||||||
|
if (from.isNullOrBlank() or to.isNullOrBlank() or rate.isNullOrBlank()) {
|
||||||
|
Toast.makeText(context, "Unable to review data for widget", Toast.LENGTH_SHORT).show()
|
||||||
|
return@apply
|
||||||
|
}
|
||||||
|
|
||||||
|
val titleString = "${from}${to}"
|
||||||
|
setTextViewText(R.id.exchangeName, titleString)
|
||||||
|
setTextViewText(R.id.exchangeRate, rate.toString())
|
||||||
|
|
||||||
|
val uri = Uri.parse("myAppWidget://updatewidget").buildUpon()
|
||||||
|
.appendQueryParameter("id", widgetId.toString())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
setImageViewResource(R.id.refresh_icon, R.drawable.ic_refresh_white_24dp)
|
||||||
|
val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast(context, uri)
|
||||||
|
setOnClickPendingIntent(R.id.refresh_icon, backgroundIntent)
|
||||||
|
|
||||||
|
val pendingIntent = HomeWidgetLaunchIntent.getActivity(context,
|
||||||
|
MainActivity::class.java)
|
||||||
|
|
||||||
|
setOnClickPendingIntent(R.id.widget_view, pendingIntent)
|
||||||
|
}
|
||||||
|
appWidgetManager.updateAppWidget(widgetId, views)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
|
super.onReceive(context, intent)
|
||||||
|
|
||||||
|
when (intent?.action) {
|
||||||
|
|
||||||
|
}
|
||||||
|
val appWidgetManager = AppWidgetManager.getInstance(context);
|
||||||
|
val appWidgetIds = appWidgetManager.getAppWidgetIds(
|
||||||
|
context?.let { ComponentName(it, this::class.java) })
|
||||||
|
val widgetDate = context?.let { HomeWidgetPlugin.getData(it) }
|
||||||
|
|
||||||
|
appWidgetIds.forEach { widgetId ->
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDeleted(context: Context?, appWidgetIds: IntArray?) {
|
||||||
|
super.onDeleted(context, appWidgetIds)
|
||||||
|
|
||||||
|
appWidgetIds?.forEach { widgetId ->
|
||||||
|
val uri = Uri.parse("myAppWidget://deletewidget")
|
||||||
|
uri.buildUpon().appendQueryParameter("id", widgetId.toString()).build()
|
||||||
|
|
||||||
|
context?.let {
|
||||||
|
HomeWidgetBackgroundIntent
|
||||||
|
.getBroadcast(it, uri)
|
||||||
|
.send()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package com.appttude.h_mal.easycc
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.appwidget.AppWidgetManager
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
|
import es.antonborri.home_widget.HomeWidgetBackgroundIntent
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configuration screen for the [CurrencyAppWidgetKotlin] AppWidget.
|
||||||
|
*/
|
||||||
|
class CurrencyAppWidgetConfigureActivity : Activity(),
|
||||||
|
View.OnClickListener {
|
||||||
|
|
||||||
|
private var mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
|
||||||
|
|
||||||
|
private var top: String? = null
|
||||||
|
private var bottom: String? = null
|
||||||
|
|
||||||
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.currency_app_widget_configure)
|
||||||
|
|
||||||
|
// Set the result to CANCELED. This will cause the widget host to cancel
|
||||||
|
// out of the widget placement if the user presses the back button.
|
||||||
|
setResult(RESULT_CANCELED)
|
||||||
|
|
||||||
|
// Find the widget id from the intent.
|
||||||
|
val extras = intent.extras
|
||||||
|
if (extras != null) {
|
||||||
|
mAppWidgetId = extras.getInt(
|
||||||
|
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this activity was started with an intent without an app widget ID, finish with an error.
|
||||||
|
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setupClickListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupClickListener() {
|
||||||
|
findViewById<TextView>(R.id.submitWidget).setOnClickListener(this)
|
||||||
|
findViewById<TextView>(R.id.currencyOne).setOnClickListener(this)
|
||||||
|
findViewById<TextView>(R.id.currencyTwo).setOnClickListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(view: View?) {
|
||||||
|
when (view?.tag.toString()) {
|
||||||
|
"top", "bottom" -> showCustomDialog(view)
|
||||||
|
"submit" -> displaySubmitDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun displaySubmitDialog() {
|
||||||
|
if (top == null || bottom == null) {
|
||||||
|
Toast.makeText(this, "Selections incomplete", Toast.LENGTH_SHORT).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (top == bottom) {
|
||||||
|
Toast.makeText(this, "Selected rates cannot be the same", Toast.LENGTH_SHORT).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetSubmitDialog(this, getSubmitDialogMessage(), object : DialogSubmit {
|
||||||
|
override fun onSubmit() {
|
||||||
|
sendUpdateIntent(top!!, bottom!!)
|
||||||
|
finishCurrencyWidgetActivity()
|
||||||
|
}
|
||||||
|
}).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun showCustomDialog(view: View?) {
|
||||||
|
CustomDialogClass(this) {
|
||||||
|
(view as TextView).text = it
|
||||||
|
when (view.tag.toString()) {
|
||||||
|
"top" -> top = it
|
||||||
|
"bottom" -> bottom = it
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun finishCurrencyWidgetActivity() {
|
||||||
|
// Make sure we pass back the original appWidgetId
|
||||||
|
val resultValue = intent
|
||||||
|
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId)
|
||||||
|
setResult(RESULT_OK, resultValue)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendUpdateIntent(from: String, to: String) {
|
||||||
|
// It is the responsibility of the configuration activity to update the app widget
|
||||||
|
// Send update broadcast to widget app class
|
||||||
|
val uri = Uri.parse("myAppWidget://createwidget").buildUpon()
|
||||||
|
.appendQueryParameter("id", mAppWidgetId.toString())
|
||||||
|
.appendQueryParameter("from", from)
|
||||||
|
.appendQueryParameter("to", to)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast(this, uri)
|
||||||
|
backgroundIntent.send()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSubmitDialogMessage(): String {
|
||||||
|
val widgetName = getWidgetStringName()
|
||||||
|
return StringBuilder().append("Create widget for ")
|
||||||
|
.append(widgetName)
|
||||||
|
.append("?").toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getWidgetStringName() = "${top!!.substring(0, 3)}${bottom!!.substring(0, 3)}"
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package com.appttude.h_mal.easycc
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import android.view.WindowManager
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.ListView
|
||||||
|
import android.widget.TextView
|
||||||
|
import com.appttude.h_mal.easycc.R
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom dialog when selecting currencies from list with filter
|
||||||
|
*/
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
class CustomDialogClass(
|
||||||
|
context: Context,
|
||||||
|
private val onSelect: (String) -> Unit
|
||||||
|
) : Dialog(context) {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.custom_dialog)
|
||||||
|
|
||||||
|
// Transparent background
|
||||||
|
window!!.setBackgroundDrawableResource(android.R.color.transparent)
|
||||||
|
// Keyboard not to overlap dialog
|
||||||
|
window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
|
||||||
|
|
||||||
|
val arrayAdapter =
|
||||||
|
ArrayAdapter.createFromResource(
|
||||||
|
context, R.array.currency_arrays,
|
||||||
|
android.R.layout.simple_list_item_1
|
||||||
|
)
|
||||||
|
|
||||||
|
val list_view = findViewById<ListView>(R.id.list_view)
|
||||||
|
list_view.adapter = arrayAdapter
|
||||||
|
|
||||||
|
// Edit text to filter @arrayAdapter
|
||||||
|
findViewById<TextView>(R.id.search_text).addTextChangedListener(object : TextWatcher {
|
||||||
|
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||||
|
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
|
||||||
|
arrayAdapter.filter.filter(charSequence)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun afterTextChanged(editable: Editable) {}
|
||||||
|
})
|
||||||
|
|
||||||
|
// interface selection back to calling activity
|
||||||
|
list_view.setOnItemClickListener { adapterView, _, i, _ ->
|
||||||
|
onSelect.invoke(adapterView.getItemAtPosition(i).toString())
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.appttude.h_mal.easycc
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.TextView
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog created when submitting the completed selections
|
||||||
|
* in [CurrencyAppWidgetConfigureActivity]
|
||||||
|
*/
|
||||||
|
class WidgetSubmitDialog(
|
||||||
|
context: Context,
|
||||||
|
private val messageString: String,
|
||||||
|
private val dialogInterface: DialogSubmit
|
||||||
|
) : Dialog(context) {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.confirm_dialog)
|
||||||
|
// layer behind dialog to be transparent
|
||||||
|
window!!.setBackgroundDrawableResource(android.R.color.transparent)
|
||||||
|
// Dialog cannot be cancelled by clicking away
|
||||||
|
setCancelable(false)
|
||||||
|
|
||||||
|
findViewById<TextView>(R.id.confirmText).text = messageString
|
||||||
|
|
||||||
|
// handle dialog buttons
|
||||||
|
findViewById<TextView>(R.id.confirmYes).setOnClickListener { dialogInterface.onSubmit() }
|
||||||
|
findViewById<TextView>(R.id.confirmNo).setOnClickListener { dismiss() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DialogSubmit {
|
||||||
|
fun onSubmit()
|
||||||
|
}
|
||||||
BIN
android/app/src/main/res/drawable/easyycc_widget_preview.png
Normal file
BIN
android/app/src/main/res/drawable/easyycc_widget_preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
24
android/app/src/main/res/drawable/ic_background.xml
Normal file
24
android/app/src/main/res/drawable/ic_background.xml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="1080dp"
|
||||||
|
android:height="1920dp"
|
||||||
|
android:viewportWidth="1080"
|
||||||
|
android:viewportHeight="1920">
|
||||||
|
<path android:pathData="M0,0L1080,0L1080,1920L0,1920L0,0Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startY="0"
|
||||||
|
android:startX="1080"
|
||||||
|
android:endY="1920"
|
||||||
|
android:endX="0"
|
||||||
|
android:type="linear">
|
||||||
|
<item
|
||||||
|
android:offset="0"
|
||||||
|
android:color="#FF315659" />
|
||||||
|
<item
|
||||||
|
android:offset="1"
|
||||||
|
android:color="#FF2978A0" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_refresh_white_24dp.xml
Normal file
10
android/app/src/main/res/drawable/ic_refresh_white_24dp.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector android:height="24dp"
|
||||||
|
android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24.0"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:width="24dp"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z" />
|
||||||
|
</vector>
|
||||||
64
android/app/src/main/res/layout/confirm_dialog.xml
Normal file
64
android/app/src/main/res/layout/confirm_dialog.xml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:backgroundTint="@android:color/transparent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
card_view:cardBackgroundColor="@color/colour_three"
|
||||||
|
card_view:cardCornerRadius="22dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="12dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/confirmText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:layout_marginLeft="12dp"
|
||||||
|
android:layout_marginRight="36dp"
|
||||||
|
android:layout_marginBottom="24dp"
|
||||||
|
android:text="Create widget for AUDGBP?"
|
||||||
|
android:textColor="@color/colour_five" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/confirmYes"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:paddingLeft="12dp"
|
||||||
|
android:paddingRight="12dp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:text="@android:string/yes"
|
||||||
|
android:textColor="@color/colour_five" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/confirmNo"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:text="@android:string/no"
|
||||||
|
android:textColor="@color/colour_five" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
65
android/app/src/main/res/layout/currency_app_widget.xml
Normal file
65
android/app/src/main/res/layout/currency_app_widget.xml
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/widget_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
tools:layout_width="110dp"
|
||||||
|
android:layout_height="72dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="#4D000000">
|
||||||
|
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/exchangeName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:autoSizeMaxTextSize="20sp"
|
||||||
|
android:autoSizeMinTextSize="6sp"
|
||||||
|
android:autoSizeStepGranularity="2sp"
|
||||||
|
android:autoSizeTextType="uniform"
|
||||||
|
android:textColor="#ffffff"
|
||||||
|
android:text="Rate not set"
|
||||||
|
tools:text="AUDGBP" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/refresh_icon"
|
||||||
|
android:layout_width="18dp"
|
||||||
|
android:layout_height="18dp"
|
||||||
|
tools:src="@drawable/ic_refresh_white_24dp"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_alignBottom="@id/exchangeName"
|
||||||
|
android:adjustViewBounds="true" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/exchangeRate"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginLeft="6dp"
|
||||||
|
android:layout_marginRight="6dp"
|
||||||
|
android:autoSizeMaxTextSize="100sp"
|
||||||
|
android:autoSizeMinTextSize="6sp"
|
||||||
|
android:autoSizeStepGranularity="2sp"
|
||||||
|
android:autoSizeTextType="uniform"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="#ffffff"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="0.52646215" />
|
||||||
|
|
||||||
|
<!-- <TextView-->
|
||||||
|
<!-- android:id="@+id/lastUpdated"-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- android:gravity="center"-->
|
||||||
|
<!-- android:textSize="8sp"-->
|
||||||
|
<!-- android:textColor="#ffffff"-->
|
||||||
|
<!-- android:text=" "-->
|
||||||
|
<!-- tools:text="Last updated: 03:18 Wed" />-->
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:focusable="false"
|
||||||
|
android:focusableInTouchMode="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="@drawable/ic_background"
|
||||||
|
tools:context=".CurrencyAppWidgetConfigureActivity">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:layout_margin="12dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/whole_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
style="@style/cardview_theme"
|
||||||
|
android:layout_margin="11dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/currencyOne"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="12dp"
|
||||||
|
android:tag="top"
|
||||||
|
android:textColor="@color/colour_five"
|
||||||
|
android:textSize="18sp"
|
||||||
|
tools:text="Currency One" />
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
style="@style/cardview_theme"
|
||||||
|
android:layout_margin="11dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/currencyTwo"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="12dp"
|
||||||
|
android:tag="bottom"
|
||||||
|
android:textColor="@color/colour_five"
|
||||||
|
android:textSize="18sp"
|
||||||
|
tools:text="Currency Two" />
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/submitWidget"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/whole_view"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginEnd="22dp"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:tag="submit"
|
||||||
|
android:text="Submit"
|
||||||
|
android:textColor="@color/colour_five" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</RelativeLayout>
|
||||||
39
android/app/src/main/res/layout/custom_dialog.xml
Normal file
39
android/app/src/main/res/layout/custom_dialog.xml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:backgroundTint="@android:color/transparent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
card_view:cardCornerRadius="22dp"
|
||||||
|
card_view:cardBackgroundColor="@color/colour_three"
|
||||||
|
android:layout_marginTop="45dp">
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/list_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"></ListView>
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="45dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
card_view:cardBackgroundColor="@color/colour_three"
|
||||||
|
card_view:cardCornerRadius="22dp">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/search_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:hint="Search Currency" />
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
8
android/app/src/main/res/values-night/colors.xml
Normal file
8
android/app/src/main/res/values-night/colors.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="colour_one">#253031</color>
|
||||||
|
<color name="colour_two">#315659</color>
|
||||||
|
<color name="colour_three">#2978A0</color>
|
||||||
|
<color name="colour_four">#8549ff</color>
|
||||||
|
<color name="colour_five">#C6E0FF</color>
|
||||||
|
</resources>
|
||||||
8
android/app/src/main/res/values/colors.xml
Normal file
8
android/app/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="colour_one">#253031</color>
|
||||||
|
<color name="colour_two">#315659</color>
|
||||||
|
<color name="colour_three">#2978A0</color>
|
||||||
|
<color name="colour_four">#8549ff</color>
|
||||||
|
<color name="colour_five">#C6E0FF</color>
|
||||||
|
</resources>
|
||||||
161
android/app/src/main/res/values/strings.xml
Normal file
161
android/app/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string-array name="currency_arrays">
|
||||||
|
<item>ALL - Albanian Lek</item>
|
||||||
|
<item>AFN - Afghan Afghani</item>
|
||||||
|
<item>DZD - Algerian Dinar</item>
|
||||||
|
<item>AOA - Angolan Kwanza</item>
|
||||||
|
<item>ARS - Argentine Peso</item>
|
||||||
|
<item>AMD - Armenian Dram</item>
|
||||||
|
<item>AWG - Aruban Florin</item>
|
||||||
|
<item>AUD - Australian Dollar</item>
|
||||||
|
<item>AZN - Azerbaijani Manat</item>
|
||||||
|
<item>BSD - Bahamian Dollar</item>
|
||||||
|
<item>BHD - Bahraini Dinar</item>
|
||||||
|
<item>BDT - Bangladeshi Taka</item>
|
||||||
|
<item>BBD - Barbadian Dollar</item>
|
||||||
|
<item>BYR - Belarusian Ruble</item>
|
||||||
|
<item>BZD - Belize Dollar</item>
|
||||||
|
<item>BTN - Bhutanese Ngultrum</item>
|
||||||
|
<item>BTC - Bitcoin</item>
|
||||||
|
<item>BOB - Bolivian Boliviano</item>
|
||||||
|
<item>BAM - Bosnia And Herzegovina Konvertibilna Marka</item>
|
||||||
|
<item>BWP - Botswana Pula</item>
|
||||||
|
<item>BRL - Brazilian Real</item>
|
||||||
|
<item>GBP - British Pound</item>
|
||||||
|
<item>BND - Brunei Dollar</item>
|
||||||
|
<item>BGN - Bulgarian Lev</item>
|
||||||
|
<item>BIF - Burundi Franc</item>
|
||||||
|
<item>KHR - Cambodian Riel</item>
|
||||||
|
<item>CAD - Canadian Dollar</item>
|
||||||
|
<item>CVE - Cape Verdean Escudo</item>
|
||||||
|
<item>KYD - Cayman Islands Dollar</item>
|
||||||
|
<item>XAF - Central African CFA Franc</item>
|
||||||
|
<item>XPF - CFP Franc</item>
|
||||||
|
<item>CLP - Chilean Peso</item>
|
||||||
|
<item>CNY - Chinese Yuan</item>
|
||||||
|
<item>COP - Colombian Peso</item>
|
||||||
|
<item>KMF - Comorian Franc</item>
|
||||||
|
<item>CDF - Congolese Franc</item>
|
||||||
|
<item>CRC - Costa Rican Colon</item>
|
||||||
|
<item>HRK - Croatian Kuna</item>
|
||||||
|
<item>CUP - Cuban Peso</item>
|
||||||
|
<item>CZK - Czech Koruna</item>
|
||||||
|
<item>DKK - Danish Krone</item>
|
||||||
|
<item>DJF - Djiboutian Franc</item>
|
||||||
|
<item>DOP - Dominican Peso</item>
|
||||||
|
<item>XCD - East Caribbean Dollar</item>
|
||||||
|
<item>EGP - Egyptian Pound</item>
|
||||||
|
<item>ERN - Eritrean Nakfa</item>
|
||||||
|
<item>ETB - Ethiopian Birr</item>
|
||||||
|
<item>EUR - Euro</item>
|
||||||
|
<item>FKP - Falkland Islands Pound</item>
|
||||||
|
<item>FJD - Fijian Dollar</item>
|
||||||
|
<item>GMD - Gambian Dalasi</item>
|
||||||
|
<item>GEL - Georgian Lari</item>
|
||||||
|
<item>GHS - Ghanaian Cedi</item>
|
||||||
|
<item>GIP - Gibraltar Pound</item>
|
||||||
|
<item>GTQ - Guatemalan Quetzal</item>
|
||||||
|
<item>GNF - Guinean Franc</item>
|
||||||
|
<item>GYD - Guyanese Dollar</item>
|
||||||
|
<item>HTG - Haitian Gourde</item>
|
||||||
|
<item>HNL - Honduran Lempira</item>
|
||||||
|
<item>HKD - Hong Kong Dollar</item>
|
||||||
|
<item>HUF - Hungarian Forint</item>
|
||||||
|
<item>ISK - Icelandic Kr\u00f3na</item>
|
||||||
|
<item>INR - Indian Rupee</item>
|
||||||
|
<item>IDR - Indonesian Rupiah</item>
|
||||||
|
<item>IRR - Iranian Rial</item>
|
||||||
|
<item>IQD - Iraqi Dinar</item>
|
||||||
|
<item>ILS - Israeli New Sheqel</item>
|
||||||
|
<item>JMD - Jamaican Dollar</item>
|
||||||
|
<item>JPY - Japanese Yen</item>
|
||||||
|
<item>JOD - Jordanian Dinar</item>
|
||||||
|
<item>KZT - Kazakhstani Tenge</item>
|
||||||
|
<item>KES - Kenyan Shilling</item>
|
||||||
|
<item>KWD - Kuwaiti Dinar</item>
|
||||||
|
<item>KGS - Kyrgyzstani Som</item>
|
||||||
|
<item>LAK - Lao Kip</item>
|
||||||
|
<item>LVL - Latvian Lats</item>
|
||||||
|
<item>LBP - Lebanese Lira</item>
|
||||||
|
<item>LSL - Lesotho Loti</item>
|
||||||
|
<item>LRD - Liberian Dollar</item>
|
||||||
|
<item>LYD - Libyan Dinar</item>
|
||||||
|
<item>MOP - Macanese Pataca</item>
|
||||||
|
<item>MKD - Macedonian Denar</item>
|
||||||
|
<item>MGA - Malagasy Ariary</item>
|
||||||
|
<item>MWK - Malawian Kwacha</item>
|
||||||
|
<item>MYR - Malaysian Ringgit</item>
|
||||||
|
<item>MVR - Maldivian Rufiyaa</item>
|
||||||
|
<item>MRO - Mauritanian Ouguiya</item>
|
||||||
|
<item>MUR - Mauritian Rupee</item>
|
||||||
|
<item>MXN - Mexican Peso</item>
|
||||||
|
<item>MDL - Moldovan Leu</item>
|
||||||
|
<item>MNT - Mongolian Tugrik</item>
|
||||||
|
<item>MAD - Moroccan Dirham</item>
|
||||||
|
<item>MZN - Mozambican Metical</item>
|
||||||
|
<item>MMK - Myanma Kyat</item>
|
||||||
|
<item>NAD - Namibian Dollar</item>
|
||||||
|
<item>NPR - Nepalese Rupee</item>
|
||||||
|
<item>ANG - Netherlands Antillean Gulden</item>
|
||||||
|
<item>TWD - New Taiwan Dollar</item>
|
||||||
|
<item>NZD - New Zealand Dollar</item>
|
||||||
|
<item>NIO - Nicaraguan Cordoba</item>
|
||||||
|
<item>NGN - Nigerian Naira</item>
|
||||||
|
<item>KPW - North Korean Won</item>
|
||||||
|
<item>NOK - Norwegian Krone</item>
|
||||||
|
<item>OMR - Omani Rial</item>
|
||||||
|
<item>TOP - Paanga</item>
|
||||||
|
<item>PKR - Pakistani Rupee</item>
|
||||||
|
<item>PAB - Panamanian Balboa</item>
|
||||||
|
<item>PGK - Papua New Guinean Kina</item>
|
||||||
|
<item>PYG - Paraguayan Guarani</item>
|
||||||
|
<item>PEN - Peruvian Nuevo Sol</item>
|
||||||
|
<item>PHP - Philippine Peso</item>
|
||||||
|
<item>PLN - Polish Zloty</item>
|
||||||
|
<item>QAR - Qatari Riyal</item>
|
||||||
|
<item>RON - Romanian Leu</item>
|
||||||
|
<item>RUB - Russian Ruble</item>
|
||||||
|
<item>RWF - Rwandan Franc</item>
|
||||||
|
<item>SHP - Saint Helena Pound</item>
|
||||||
|
<item>WST - Samoan Tala</item>
|
||||||
|
<item>STD - Sao Tome And Principe Dobra</item>
|
||||||
|
<item>SAR - Saudi Riyal</item>
|
||||||
|
<item>RSD - Serbian Dinar</item>
|
||||||
|
<item>SCR - Seychellois Rupee</item>
|
||||||
|
<item>SLL - Sierra Leonean Leone</item>
|
||||||
|
<item>SGD - Singapore Dollar</item>
|
||||||
|
<item>SBD - Solomon Islands Dollar</item>
|
||||||
|
<item>SOS - Somali Shilling</item>
|
||||||
|
<item>ZAR - South African Rand</item>
|
||||||
|
<item>KRW - South Korean Won</item>
|
||||||
|
<item>XDR - Special Drawing Rights</item>
|
||||||
|
<item>LKR - Sri Lankan Rupee</item>
|
||||||
|
<item>SDG - Sudanese Pound</item>
|
||||||
|
<item>SRD - Surinamese Dollar</item>
|
||||||
|
<item>SZL - Swazi Lilangeni</item>
|
||||||
|
<item>SEK - Swedish Krona</item>
|
||||||
|
<item>CHF - Swiss Franc</item>
|
||||||
|
<item>SYP - Syrian Pound</item>
|
||||||
|
<item>TJS - Tajikistani Somoni</item>
|
||||||
|
<item>TZS - Tanzanian Shilling</item>
|
||||||
|
<item>THB - Thai Baht</item>
|
||||||
|
<item>TTD - Trinidad and Tobago Dollar</item>
|
||||||
|
<item>TND - Tunisian Dinar</item>
|
||||||
|
<item>TRY - Turkish New Lira</item>
|
||||||
|
<item>TMT - Turkmenistan Manat</item>
|
||||||
|
<item>AED - UAE Dirham</item>
|
||||||
|
<item>UGX - Ugandan Shilling</item>
|
||||||
|
<item>UAH - Ukrainian Hryvnia</item>
|
||||||
|
<item>USD - United States Dollar</item>
|
||||||
|
<item>UYU - Uruguayan Peso</item>
|
||||||
|
<item>UZS - Uzbekistani Som</item>
|
||||||
|
<item>VUV - Vanuatu Vatu</item>
|
||||||
|
<item>VEF - Venezuelan Bolivar</item>
|
||||||
|
<item>VND - Vietnamese Dong</item>
|
||||||
|
<item>XOF - West African CFA Franc</item>
|
||||||
|
<item>YER - Yemeni Rial</item>
|
||||||
|
<item>ZMW - Zambian Kwacha</item>
|
||||||
|
</string-array>
|
||||||
|
</resources>
|
||||||
@@ -15,4 +15,12 @@
|
|||||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
<item name="android:windowBackground">?android:colorBackground</item>
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="cardview_theme" parent="CardView">
|
||||||
|
<item name="android:layout_width">match_parent</item>
|
||||||
|
<item name="android:layout_height">match_parent</item>
|
||||||
|
<item name="cardBackgroundColor">@color/colour_three</item>
|
||||||
|
<item name="cardCornerRadius">22dp</item>
|
||||||
|
<!--<item name="cardElevation">0dp</item>-->
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
11
android/app/src/main/res/xml/currency_app_widget_info.xml
Normal file
11
android/app/src/main/res/xml/currency_app_widget_info.xml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:configure="com.appttude.h_mal.easycc.CurrencyAppWidgetConfigureActivity"
|
||||||
|
android:initialKeyguardLayout="@layout/currency_app_widget"
|
||||||
|
android:initialLayout="@layout/currency_app_widget"
|
||||||
|
android:minWidth="110dp"
|
||||||
|
android:minHeight="40dp"
|
||||||
|
android:previewImage="@drawable/easyycc_widget_preview"
|
||||||
|
android:resizeMode="horizontal|vertical"
|
||||||
|
android:updatePeriodMillis="3600000"
|
||||||
|
android:widgetCategory="home_screen|keyguard" />
|
||||||
@@ -6,7 +6,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.2.0'
|
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ extension CurrencyExtension on String {
|
|||||||
/// Convert currency string into currency code
|
/// Convert currency string into currency code
|
||||||
/// eg. "AUD - Australian Dollar" to "AUD"
|
/// eg. "AUD - Australian Dollar" to "AUD"
|
||||||
String getCurrencyCode(){
|
String getCurrencyCode(){
|
||||||
|
if (length == 3) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
return substring(0,3);
|
return substring(0,3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:toast/toast.dart';
|
import 'package:toast/toast.dart';
|
||||||
|
|
||||||
import 'base_viewmodel.dart';
|
|
||||||
import 'Utils/constants.dart';
|
import 'Utils/constants.dart';
|
||||||
import 'Utils/view_state.dart';
|
import 'Utils/view_state.dart';
|
||||||
import 'Utils/view_utils.dart';
|
import 'Utils/view_utils.dart';
|
||||||
|
import 'base_viewmodel.dart';
|
||||||
|
|
||||||
abstract class BaseStatelessWidget<T extends BaseViewmodel>
|
abstract class BaseStatelessWidget<T extends BaseViewmodel>
|
||||||
extends StatelessWidget {
|
extends StatelessWidget {
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ class AppDio {
|
|||||||
static Dio createDio() {
|
static Dio createDio() {
|
||||||
Dio dio = Dio(
|
Dio dio = Dio(
|
||||||
BaseOptions(
|
BaseOptions(
|
||||||
receiveTimeout: 60000,
|
receiveTimeout: 30000,
|
||||||
connectTimeout: 120000,
|
connectTimeout: 30000,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
dio.interceptors.add(LogInterceptor());
|
dio.interceptors.add(LogInterceptor());
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import 'package:easy_cc_flutter/Utils/currency_utils.dart';
|
|||||||
import 'package:easy_cc_flutter/data/model/currency.dart';
|
import 'package:easy_cc_flutter/data/model/currency.dart';
|
||||||
import 'package:easy_cc_flutter/data/prefs/currency_pair.dart';
|
import 'package:easy_cc_flutter/data/prefs/currency_pair.dart';
|
||||||
|
|
||||||
import '../../locator.dart';
|
|
||||||
import '../../main.dart';
|
import '../../main.dart';
|
||||||
import '../network/backup_currency_api.dart';
|
import '../network/backup_currency_api.dart';
|
||||||
import '../network/currency_api.dart';
|
import '../network/currency_api.dart';
|
||||||
@@ -13,9 +12,11 @@ import '../prefs/preference_provider.dart';
|
|||||||
import 'repository.dart';
|
import 'repository.dart';
|
||||||
|
|
||||||
class RepositoryImpl extends Repository with SafeApiCall {
|
class RepositoryImpl extends Repository with SafeApiCall {
|
||||||
final PreferenceProvider _prefs = locator<PreferenceProvider>();
|
final PreferenceProvider _prefs;
|
||||||
final CurrencyApi _api = locator<CurrencyApi>();
|
final CurrencyApi _api;
|
||||||
final BackupCurrencyApi _backupApi = locator<BackupCurrencyApi>();
|
final BackupCurrencyApi _backupApi;
|
||||||
|
|
||||||
|
RepositoryImpl(this._prefs, this._api, this._backupApi);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
CurrencyPair getConversionPair() {
|
CurrencyPair getConversionPair() {
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
import 'package:easy_cc_flutter/main_view_model.dart';
|
|
||||||
import 'package:easy_cc_flutter/Utils/selection_type.dart';
|
import 'package:easy_cc_flutter/Utils/selection_type.dart';
|
||||||
import 'package:easy_cc_flutter/views/drop_down_box.dart';
|
import 'package:easy_cc_flutter/locator.dart';
|
||||||
|
import 'package:easy_cc_flutter/main_view_model.dart';
|
||||||
import 'package:easy_cc_flutter/views/converter_edit_text.dart';
|
import 'package:easy_cc_flutter/views/converter_edit_text.dart';
|
||||||
|
import 'package:easy_cc_flutter/views/drop_down_box.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'base_widget.dart';
|
|
||||||
import 'Utils/constants.dart';
|
import 'Utils/constants.dart';
|
||||||
|
import 'base_widget.dart';
|
||||||
|
|
||||||
class HomePage extends BaseStatelessWidget<MainViewModel> {
|
class HomePage extends BaseStatelessWidget<MainViewModel> {
|
||||||
const HomePage({super.key});
|
const HomePage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MainViewModel createViewModel() {
|
MainViewModel createViewModel() {
|
||||||
return MainViewModel();
|
return locator<MainViewModel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'package:easy_cc_flutter/main_view_model.dart';
|
|
||||||
import 'package:easy_cc_flutter/data/network/backup_currency_api.dart';
|
import 'package:easy_cc_flutter/data/network/backup_currency_api.dart';
|
||||||
import 'package:easy_cc_flutter/data/network/currency_api.dart';
|
import 'package:easy_cc_flutter/data/network/currency_api.dart';
|
||||||
import 'package:easy_cc_flutter/data/repository/repository_impl.dart';
|
import 'package:easy_cc_flutter/data/repository/repository_impl.dart';
|
||||||
|
import 'package:easy_cc_flutter/main_view_model.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
|
|
||||||
import 'data/prefs/preference_provider.dart';
|
import 'data/prefs/preference_provider.dart';
|
||||||
|
import 'data/repository/repository.dart';
|
||||||
|
|
||||||
GetIt locator = GetIt.instance;
|
GetIt locator = GetIt.instance;
|
||||||
|
|
||||||
@@ -12,6 +12,6 @@ void setupLocator() {
|
|||||||
locator.registerLazySingleton(() => PreferenceProvider());
|
locator.registerLazySingleton(() => PreferenceProvider());
|
||||||
locator.registerLazySingleton(() => CurrencyApi.create());
|
locator.registerLazySingleton(() => CurrencyApi.create());
|
||||||
locator.registerLazySingleton(() => BackupCurrencyApi.create());
|
locator.registerLazySingleton(() => BackupCurrencyApi.create());
|
||||||
locator.registerLazySingleton(() => RepositoryImpl());
|
locator.registerLazySingleton<Repository>(() => RepositoryImpl(locator<PreferenceProvider>(), locator<CurrencyApi>(),locator<BackupCurrencyApi>()));
|
||||||
locator.registerFactory(() => MainViewModel());
|
locator.registerFactory(() => MainViewModel(locator<Repository>()));
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,14 @@
|
|||||||
|
import 'package:easy_cc_flutter/Utils/currency_utils.dart';
|
||||||
|
import 'package:easy_cc_flutter/data/network/backup_currency_api.dart';
|
||||||
|
import 'package:easy_cc_flutter/data/network/currency_api.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:home_widget/home_widget.dart';
|
||||||
import 'package:logger/logger.dart';
|
import 'package:logger/logger.dart';
|
||||||
|
|
||||||
|
import 'data/model/currency.dart';
|
||||||
import 'data/prefs/preference_provider.dart';
|
import 'data/prefs/preference_provider.dart';
|
||||||
|
import 'data/repository/repository.dart';
|
||||||
|
import 'data/repository/repository_impl.dart';
|
||||||
import 'home.dart';
|
import 'home.dart';
|
||||||
import 'locator.dart';
|
import 'locator.dart';
|
||||||
|
|
||||||
@@ -9,13 +16,56 @@ var logger = Logger(
|
|||||||
printer: PrettyPrinter(),
|
printer: PrettyPrinter(),
|
||||||
);
|
);
|
||||||
|
|
||||||
void main() async {
|
Future<void> main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
setupLocator();
|
setupLocator();
|
||||||
await locator<PreferenceProvider>().init();
|
await locator<PreferenceProvider>().init();
|
||||||
|
await HomeWidget.registerBackgroundCallback(backgroundCallback);
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> backgroundCallback(Uri? uri) async {
|
||||||
|
PreferenceProvider prefs = PreferenceProvider();
|
||||||
|
await prefs.init();
|
||||||
|
CurrencyApi api = CurrencyApi.create();
|
||||||
|
BackupCurrencyApi backupApi = BackupCurrencyApi.create();
|
||||||
|
RepositoryImpl repository = RepositoryImpl(prefs, api, backupApi);
|
||||||
|
|
||||||
|
if (uri?.host == 'updatewidget') {
|
||||||
|
Map<String, String>? querys = uri?.queryParameters;
|
||||||
|
String? widgetId = querys?["id"];
|
||||||
|
|
||||||
|
await updateWidget(widgetId, repository);
|
||||||
|
} else if (uri?.host == 'createwidget') {
|
||||||
|
Map<String, String>? querys = uri?.queryParameters;
|
||||||
|
String? widgetId = querys?["id"];
|
||||||
|
String? from = querys?["from"]?.getCurrencyCode();
|
||||||
|
String? to = querys?["to"]?.getCurrencyCode();
|
||||||
|
|
||||||
|
await HomeWidget.saveWidgetData<String>("${widgetId}_from", from);
|
||||||
|
await HomeWidget.saveWidgetData<String>("${widgetId}_to", to);
|
||||||
|
|
||||||
|
await updateWidget(widgetId, repository);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateWidget(String? widgetId, Repository repository) async {
|
||||||
|
String? from = await HomeWidget.getWidgetData<String>("${widgetId}_from");
|
||||||
|
String? to = await HomeWidget.getWidgetData<String>("${widgetId}_to");
|
||||||
|
|
||||||
|
if (from == null || to == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Currency currency = await repository.getConversationRateFromApi(from, to);
|
||||||
|
|
||||||
|
await HomeWidget.saveWidgetData<String>("${widgetId}_from", from);
|
||||||
|
await HomeWidget.saveWidgetData<String>("${widgetId}_to", to);
|
||||||
|
await HomeWidget.saveWidgetData<String>("${widgetId}_rate", currency.rate.toString());
|
||||||
|
|
||||||
|
await HomeWidget.updateWidget(name: 'AppWidgetProvider', iOSName: 'AppWidgetProvider');
|
||||||
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
const MyApp({super.key});
|
const MyApp({super.key});
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import 'package:easy_cc_flutter/base_viewmodel.dart';
|
|
||||||
import 'package:easy_cc_flutter/Utils/selection_type.dart';
|
import 'package:easy_cc_flutter/Utils/selection_type.dart';
|
||||||
|
import 'package:easy_cc_flutter/base_viewmodel.dart';
|
||||||
|
|
||||||
import 'Utils/constants.dart';
|
import 'Utils/constants.dart';
|
||||||
import 'data/prefs/currency_pair.dart';
|
import 'data/prefs/currency_pair.dart';
|
||||||
import 'data/repository/repository.dart';
|
import 'data/repository/repository.dart';
|
||||||
import 'data/repository/repository_impl.dart';
|
|
||||||
import 'locator.dart';
|
|
||||||
|
|
||||||
class MainViewModel extends BaseViewmodel {
|
class MainViewModel extends BaseViewmodel {
|
||||||
final Repository _repository = locator<RepositoryImpl>();
|
final Repository _repository;
|
||||||
|
|
||||||
|
MainViewModel(this._repository);
|
||||||
|
|
||||||
double conversionRate = 1.0;
|
double conversionRate = 1.0;
|
||||||
|
|
||||||
|
|||||||
@@ -282,6 +282,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.0"
|
||||||
|
home_widget:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: home_widget
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.6"
|
||||||
http_multi_server:
|
http_multi_server:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ dependencies:
|
|||||||
mockito: ^5.3.2
|
mockito: ^5.3.2
|
||||||
json_annotation: ^4.7.0
|
json_annotation: ^4.7.0
|
||||||
flutter_launcher_icons: ^0.10.0
|
flutter_launcher_icons: ^0.10.0
|
||||||
|
home_widget: ^0.1.6
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import 'package:easy_cc_flutter/data/network/currency_api.dart';
|
|||||||
import 'package:easy_cc_flutter/data/prefs/currency_pair.dart';
|
import 'package:easy_cc_flutter/data/prefs/currency_pair.dart';
|
||||||
import 'package:easy_cc_flutter/data/prefs/preference_provider.dart';
|
import 'package:easy_cc_flutter/data/prefs/preference_provider.dart';
|
||||||
import 'package:easy_cc_flutter/data/repository/repository_impl.dart';
|
import 'package:easy_cc_flutter/data/repository/repository_impl.dart';
|
||||||
import 'package:easy_cc_flutter/locator.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:mockito/annotations.dart';
|
import 'package:mockito/annotations.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mockito/mockito.dart';
|
||||||
@@ -29,7 +28,8 @@ import 'repository_test.mocks.dart';
|
|||||||
MockSpec<DioError>(onMissingStub: OnMissingStub.returnDefault)
|
MockSpec<DioError>(onMissingStub: OnMissingStub.returnDefault)
|
||||||
])
|
])
|
||||||
void main() {
|
void main() {
|
||||||
late RepositoryImpl repository;
|
late RepositoryImpl sut;
|
||||||
|
|
||||||
late PreferenceProvider preferenceProvider;
|
late PreferenceProvider preferenceProvider;
|
||||||
late CurrencyApi currencyApi;
|
late CurrencyApi currencyApi;
|
||||||
late BackupCurrencyApi backupCurrencyApi;
|
late BackupCurrencyApi backupCurrencyApi;
|
||||||
@@ -44,11 +44,7 @@ void main() {
|
|||||||
currencyApi = MockCurrencyApi();
|
currencyApi = MockCurrencyApi();
|
||||||
backupCurrencyApi = MockBackupCurrencyApi();
|
backupCurrencyApi = MockBackupCurrencyApi();
|
||||||
|
|
||||||
locator.registerLazySingleton(() => preferenceProvider);
|
sut = RepositoryImpl(preferenceProvider, currencyApi, backupCurrencyApi);
|
||||||
locator.registerLazySingleton(() => currencyApi);
|
|
||||||
locator.registerLazySingleton(() => backupCurrencyApi);
|
|
||||||
|
|
||||||
repository = RepositoryImpl();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('get currency pair from prefs', () {
|
test('get currency pair from prefs', () {
|
||||||
@@ -59,7 +55,7 @@ void main() {
|
|||||||
when(preferenceProvider.getConversionPair()).thenReturn(pair);
|
when(preferenceProvider.getConversionPair()).thenReturn(pair);
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(repository.getConversionPair(), pair);
|
expect(sut.getConversionPair(), pair);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('get currency rate from API', () async {
|
test('get currency rate from API', () async {
|
||||||
@@ -77,7 +73,7 @@ void main() {
|
|||||||
|
|
||||||
// Then
|
// Then
|
||||||
Currency retrieved =
|
Currency retrieved =
|
||||||
await repository.getConversationRateFromApi(fromCurrency, toCurrency);
|
await sut.getConversationRateFromApi(fromCurrency, toCurrency);
|
||||||
expect(retrieved.toString(), currencyObject.toString());
|
expect(retrieved.toString(), currencyObject.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -98,7 +94,7 @@ void main() {
|
|||||||
|
|
||||||
// Then
|
// Then
|
||||||
Currency retrieved =
|
Currency retrieved =
|
||||||
await repository.getConversationRateFromApi(fromCurrency, toCurrency);
|
await sut.getConversationRateFromApi(fromCurrency, toCurrency);
|
||||||
expect(retrieved.toString(), currencyObject.toString());
|
expect(retrieved.toString(), currencyObject.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -115,7 +111,7 @@ void main() {
|
|||||||
.thenAnswer((_) async => Future.error(backUpError));
|
.thenAnswer((_) async => Future.error(backUpError));
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(() async => await repository.getConversationRateFromApi(fromCurrency, toCurrency),
|
expect(() async => await sut.getConversationRateFromApi(fromCurrency, toCurrency),
|
||||||
throwsA(predicate((e) =>
|
throwsA(predicate((e) =>
|
||||||
e is HttpException &&
|
e is HttpException &&
|
||||||
e.message == 'Error message')));
|
e.message == 'Error message')));
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:easy_cc_flutter/main_view_model.dart';
|
|
||||||
import 'package:easy_cc_flutter/Utils/selection_type.dart';
|
import 'package:easy_cc_flutter/Utils/selection_type.dart';
|
||||||
|
import 'package:easy_cc_flutter/Utils/view_state.dart';
|
||||||
import 'package:easy_cc_flutter/data/model/currency.dart';
|
import 'package:easy_cc_flutter/data/model/currency.dart';
|
||||||
import 'package:easy_cc_flutter/data/prefs/currency_pair.dart';
|
import 'package:easy_cc_flutter/data/prefs/currency_pair.dart';
|
||||||
import 'package:easy_cc_flutter/data/repository/repository_impl.dart';
|
import 'package:easy_cc_flutter/data/repository/repository_impl.dart';
|
||||||
import 'package:easy_cc_flutter/locator.dart';
|
import 'package:easy_cc_flutter/main_view_model.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:mockito/annotations.dart';
|
import 'package:mockito/annotations.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mockito/mockito.dart';
|
||||||
import 'package:easy_cc_flutter/Utils/view_state.dart';
|
|
||||||
|
|
||||||
import 'viewmodel_test.mocks.dart';
|
import 'viewmodel_test.mocks.dart';
|
||||||
|
|
||||||
@@ -29,9 +28,7 @@ void main() {
|
|||||||
// Create mock object.
|
// Create mock object.
|
||||||
repository = MockRepositoryImpl();
|
repository = MockRepositoryImpl();
|
||||||
|
|
||||||
locator.registerLazySingleton(() => repository);
|
mainViewModel = MainViewModel(repository);
|
||||||
|
|
||||||
mainViewModel = MainViewModel();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('get currency pair from prefs', () {
|
test('get currency pair from prefs', () {
|
||||||
|
|||||||
Reference in New Issue
Block a user