- Replaced API

- Updated available currencies
 - Updated unit tests
 - Fix for failure handling
 - Android release signing
This commit is contained in:
2023-02-13 18:09:51 +00:00
parent 87d601a62c
commit afaa93fb41
14 changed files with 122 additions and 322 deletions

View File

@@ -21,6 +21,11 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0' flutterVersionName = '1.0'
} }
def relStorePassword = System.getenv("storePassword")
def relKeyPassword = System.getenv("keyPassword")
def relKeyAlias = System.getenv("keyAlias")
def relStoreFile = System.getenv("storeFile")
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
@@ -43,7 +48,6 @@ android {
} }
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
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.
@@ -53,11 +57,22 @@ android {
versionName flutterVersionName versionName flutterVersionName
} }
signingConfigs {
release {
storePassword relStorePassword
keyPassword relKeyPassword
keyAlias relKeyAlias
storeFile file(relStoreFile)
}
}
buildTypes { buildTypes {
release { release {
// TODO: Add your own signing config for the release build. signingConfig signingConfigs.release
// Signing with the debug keys for now, so `flutter run --release` works. minifyEnabled true
signingConfig signingConfigs.debug shrinkResources true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
} }
} }

View File

@@ -1,57 +1,73 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.appttude.h_mal.easycc"> package="com.appttude.h_mal.easycc">
<application
android:label="easycc" <uses-permission android:name="android.permission.INTERNET" />
<application
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/launcher_icon"> android:icon="@mipmap/launcher_icon"
android:label="easycc">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true" android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@style/LaunchTheme" android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as <!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. --> to determine the Window background behind the Flutter UI. -->
<meta-data <meta-data
android:name="io.flutter.embedding.android.NormalTheme" android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" android:resource="@style/NormalTheme" />
/>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="es.antonborri.home_widget.action.LAUNCH" />
</intent-filter>
</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>
<intent-filter>
<action android:name="es.antonborri.home_widget.action.LAUNCH" />
</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>
<!-- 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>
<!-- Don't delete the meta-data below. <service
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<!-- Home Widget -->
<!-- Home Widget --> <!-- Don't delete the meta-data below.
<receiver android:name="AppWidgetProvider" android:exported="true"> This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<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" />

View File

@@ -1,20 +1,17 @@
package com.appttude.h_mal.easycc package com.appttude.h_mal.easycc
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.widget.RemoteViews import android.widget.RemoteViews
import android.widget.Toast import android.widget.Toast
import es.antonborri.home_widget.HomeWidgetBackgroundIntent import es.antonborri.home_widget.HomeWidgetBackgroundIntent
import es.antonborri.home_widget.HomeWidgetLaunchIntent import es.antonborri.home_widget.HomeWidgetLaunchIntent
import es.antonborri.home_widget.HomeWidgetPlugin
import es.antonborri.home_widget.HomeWidgetProvider import es.antonborri.home_widget.HomeWidgetProvider
class AppWidgetProvider : HomeWidgetProvider(){ class AppWidgetProvider : HomeWidgetProvider() {
override fun onUpdate( override fun onUpdate(
context: Context, context: Context,
appWidgetManager: AppWidgetManager, appWidgetManager: AppWidgetManager,
@@ -23,54 +20,46 @@ class AppWidgetProvider : HomeWidgetProvider(){
) { ) {
appWidgetIds.forEach { widgetId -> appWidgetIds.forEach { widgetId ->
val views = RemoteViews(context.packageName, R.layout.currency_app_widget).apply { val views = RemoteViews(context.packageName, R.layout.currency_app_widget).apply {
// Data from background operation received val uri = createUpdateUri(widgetId)
val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast(context, uri)
// checks if forced update or period update
val forcedUpdate: Boolean =
widgetData.getBoolean("${widgetId}_forced_update", false)
if (!forcedUpdate) {
widgetData.edit().putBoolean("${widgetId}_forced_update", true).apply()
backgroundIntent.send()
return@apply
}
val from: String? = widgetData.getString("${widgetId}_from", null) val from: String? = widgetData.getString("${widgetId}_from", null)
val to: String? = widgetData.getString("${widgetId}_to", null) val to: String? = widgetData.getString("${widgetId}_to", null)
val rate: String? = widgetData.getString("${widgetId}_rate", null) val rate: String? = widgetData.getString("${widgetId}_rate", null)
if (from.isNullOrBlank() or to.isNullOrBlank() or rate.isNullOrBlank()) { if (from.isNullOrBlank() or to.isNullOrBlank() or rate.isNullOrBlank()) {
Toast.makeText(context, "Unable to review data for widget", Toast.LENGTH_SHORT).show() Toast.makeText(context, "Unable to review data for widget", Toast.LENGTH_SHORT)
.show()
return@apply return@apply
} }
val titleString = "${from}${to}" val titleString = "${from}${to}"
setTextViewText(R.id.exchangeName, titleString) setTextViewText(R.id.exchangeName, titleString)
setTextViewText(R.id.exchangeRate, rate.toString()) 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) setImageViewResource(R.id.refresh_icon, R.drawable.ic_refresh_white_24dp)
val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast(context, uri)
setOnClickPendingIntent(R.id.refresh_icon, backgroundIntent) setOnClickPendingIntent(R.id.refresh_icon, backgroundIntent)
val pendingIntent = HomeWidgetLaunchIntent.getActivity(context, val pendingIntent = HomeWidgetLaunchIntent.getActivity(
MainActivity::class.java) context,
MainActivity::class.java
)
widgetData.edit().putBoolean("${widgetId}_forced_update", false).apply()
setOnClickPendingIntent(R.id.widget_view, pendingIntent) setOnClickPendingIntent(R.id.widget_view, pendingIntent)
} }
appWidgetManager.updateAppWidget(widgetId, views) 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?) { override fun onDeleted(context: Context?, appWidgetIds: IntArray?) {
super.onDeleted(context, appWidgetIds) super.onDeleted(context, appWidgetIds)
@@ -85,4 +74,11 @@ class AppWidgetProvider : HomeWidgetProvider(){
} }
} }
} }
// Send update broadcast to widget app class
private fun createUpdateUri(widgetId: Int): Uri? {
return Uri.parse("myAppWidget://updatewidget").buildUpon()
.appendQueryParameter("id", widgetId.toString())
.build()
}
} }

View File

@@ -2,160 +2,43 @@
<resources> <resources>
<string-array name="currency_arrays"> <string-array name="currency_arrays">
<item>ALL - Albanian Lek</item>
<item>AFN - Afghan Afghani</item>
<item>DZD - Algerian Dinar</item> <item>DZD - Algerian Dinar</item>
<item>AOA - Angolan Kwanza</item>
<item>ARS - Argentine Peso</item> <item>ARS - Argentine Peso</item>
<item>AMD - Armenian Dram</item>
<item>AWG - Aruban Florin</item>
<item>AUD - Australian Dollar</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>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>BRL - Brazilian Real</item>
<item>GBP - British Pound</item> <item>GBP - British Pound</item>
<item>BND - Brunei Dollar</item>
<item>BGN - Bulgarian Lev</item> <item>BGN - Bulgarian Lev</item>
<item>BIF - Burundi Franc</item>
<item>KHR - Cambodian Riel</item>
<item>CAD - Canadian Dollar</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>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>HRK - Croatian Kuna</item>
<item>CUP - Cuban Peso</item>
<item>CZK - Czech Koruna</item> <item>CZK - Czech Koruna</item>
<item>DKK - Danish Krone</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>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>HKD - Hong Kong Dollar</item>
<item>HUF - Hungarian Forint</item> <item>HUF - Hungarian Forint</item>
<item>ISK - Icelandic Kr\u00f3na</item> <item>ISK - Icelandic Kr\u00f3na</item>
<item>INR - Indian Rupee</item> <item>INR - Indian Rupee</item>
<item>IDR - Indonesian Rupiah</item> <item>IDR - Indonesian Rupiah</item>
<item>IRR - Iranian Rial</item>
<item>IQD - Iraqi Dinar</item>
<item>ILS - Israeli New Sheqel</item> <item>ILS - Israeli New Sheqel</item>
<item>JMD - Jamaican Dollar</item>
<item>JPY - Japanese Yen</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>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>MXN - Mexican Peso</item>
<item>MDL - Moldovan Leu</item>
<item>MNT - Mongolian Tugrik</item>
<item>MAD - Moroccan Dirham</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>TWD - New Taiwan Dollar</item>
<item>NZD - New Zealand 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>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>PHP - Philippine Peso</item>
<item>PLN - Polish Zloty</item> <item>PLN - Polish Zloty</item>
<item>QAR - Qatari Riyal</item>
<item>RON - Romanian Leu</item> <item>RON - Romanian Leu</item>
<item>RUB - Russian Ruble</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>SGD - Singapore Dollar</item>
<item>SBD - Solomon Islands Dollar</item>
<item>SOS - Somali Shilling</item>
<item>ZAR - South African Rand</item> <item>ZAR - South African Rand</item>
<item>KRW - South Korean Won</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>SEK - Swedish Krona</item>
<item>CHF - Swiss Franc</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>THB - Thai Baht</item>
<item>TTD - Trinidad and Tobago Dollar</item>
<item>TND - Tunisian Dinar</item>
<item>TRY - Turkish New Lira</item> <item>TRY - Turkish New Lira</item>
<item>TMT - Turkmenistan Manat</item> <item>USD - US Dollar</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> </string-array>
</resources> </resources>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:configure="com.appttude.h_mal.easycc.CurrencyAppWidgetConfigureActivity" android:configure="com.appttude.h_mal.easycc.CurrencyAppWidgetConfigureActivity"
android:initialKeyguardLayout="@layout/currency_app_widget" android:initialKeyguardLayout="@layout/currency_app_widget"
android:initialLayout="@layout/currency_app_widget" android:initialLayout="@layout/currency_app_widget"
@@ -7,5 +8,6 @@
android:minHeight="40dp" android:minHeight="40dp"
android:previewImage="@drawable/easyycc_widget_preview" android:previewImage="@drawable/easyycc_widget_preview"
android:resizeMode="horizontal|vertical" android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="3600000" android:updatePeriodMillis="14400000"
android:widgetCategory="home_screen|keyguard" /> android:widgetCategory="home_screen|keyguard"
tools:targetApi="jelly_bean_mr1" />

View File

@@ -9,159 +9,42 @@ const Color colourFive = Color(0xFFC6E0FF);
const double paddingGlobal = 12; const double paddingGlobal = 12;
final List<String> listOfCurrencies = <String>[ final List<String> listOfCurrencies = <String>[
'ALL - Albanian Lek',
'AFN - Afghan Afghani',
'DZD - Algerian Dinar', 'DZD - Algerian Dinar',
'AOA - Angolan Kwanza',
'ARS - Argentine Peso', 'ARS - Argentine Peso',
'AMD - Armenian Dram',
'AWG - Aruban Florin',
'AUD - Australian Dollar', 'AUD - Australian Dollar',
'AZN - Azerbaijani Manat',
'BSD - Bahamian Dollar',
'BHD - Bahraini Dinar',
'BDT - Bangladeshi Taka',
'BBD - Barbadian Dollar',
'BYR - Belarusian Ruble',
'BZD - Belize Dollar',
'BTN - Bhutanese Ngultrum',
'BTC - Bitcoin', 'BTC - Bitcoin',
'BOB - Bolivian Boliviano',
'BAM - Bosnia And Herzegovina Konvertibilna Marka',
'BWP - Botswana Pula',
'BRL - Brazilian Real', 'BRL - Brazilian Real',
'GBP - British Pound', 'GBP - British Pound',
'BND - Brunei Dollar',
'BGN - Bulgarian Lev', 'BGN - Bulgarian Lev',
'BIF - Burundi Franc',
'KHR - Cambodian Riel',
'CAD - Canadian Dollar', 'CAD - Canadian Dollar',
'CVE - Cape Verdean Escudo',
'KYD - Cayman Islands Dollar',
'XAF - Central African CFA Franc',
'XPF - CFP Franc',
'CLP - Chilean Peso',
'CNY - Chinese Yuan', 'CNY - Chinese Yuan',
'COP - Colombian Peso',
'KMF - Comorian Franc',
'CDF - Congolese Franc',
'CRC - Costa Rican Colon',
'HRK - Croatian Kuna', 'HRK - Croatian Kuna',
'CUP - Cuban Peso',
'CZK - Czech Koruna', 'CZK - Czech Koruna',
'DKK - Danish Krone', 'DKK - Danish Krone',
'DJF - Djiboutian Franc',
'DOP - Dominican Peso',
'XCD - East Caribbean Dollar',
'EGP - Egyptian Pound',
'ERN - Eritrean Nakfa',
'ETB - Ethiopian Birr',
'EUR - Euro', 'EUR - Euro',
'FKP - Falkland Islands Pound',
'FJD - Fijian Dollar',
'GMD - Gambian Dalasi',
'GEL - Georgian Lari',
'GHS - Ghanaian Cedi',
'GIP - Gibraltar Pound',
'GTQ - Guatemalan Quetzal',
'GNF - Guinean Franc',
'GYD - Guyanese Dollar',
'HTG - Haitian Gourde',
'HNL - Honduran Lempira',
'HKD - Hong Kong Dollar', 'HKD - Hong Kong Dollar',
'HUF - Hungarian Forint', 'HUF - Hungarian Forint',
'ISK - Icelandic Kr\u00f3na', 'ISK - Icelandic Kr\u00f3na',
'INR - Indian Rupee', 'INR - Indian Rupee',
'IDR - Indonesian Rupiah', 'IDR - Indonesian Rupiah',
'IRR - Iranian Rial',
'IQD - Iraqi Dinar',
'ILS - Israeli New Sheqel', 'ILS - Israeli New Sheqel',
'JMD - Jamaican Dollar',
'JPY - Japanese Yen', 'JPY - Japanese Yen',
'JOD - Jordanian Dinar',
'KZT - Kazakhstani Tenge',
'KES - Kenyan Shilling',
'KWD - Kuwaiti Dinar',
'KGS - Kyrgyzstani Som',
'LAK - Lao Kip',
'LVL - Latvian Lats',
'LBP - Lebanese Lira',
'LSL - Lesotho Loti',
'LRD - Liberian Dollar',
'LYD - Libyan Dinar',
'MOP - Macanese Pataca',
'MKD - Macedonian Denar',
'MGA - Malagasy Ariary',
'MWK - Malawian Kwacha',
'MYR - Malaysian Ringgit', 'MYR - Malaysian Ringgit',
'MVR - Maldivian Rufiyaa',
'MRO - Mauritanian Ouguiya',
'MUR - Mauritian Rupee',
'MXN - Mexican Peso', 'MXN - Mexican Peso',
'MDL - Moldovan Leu',
'MNT - Mongolian Tugrik',
'MAD - Moroccan Dirham', 'MAD - Moroccan Dirham',
'MZN - Mozambican Metical',
'MMK - Myanma Kyat',
'NAD - Namibian Dollar',
'NPR - Nepalese Rupee',
'ANG - Netherlands Antillean Gulden',
'TWD - New Taiwan Dollar', 'TWD - New Taiwan Dollar',
'NZD - New Zealand Dollar', 'NZD - New Zealand Dollar',
'NIO - Nicaraguan Cordoba',
'NGN - Nigerian Naira',
'KPW - North Korean Won',
'NOK - Norwegian Krone', 'NOK - Norwegian Krone',
'OMR - Omani Rial',
'TOP - Paanga',
'PKR - Pakistani Rupee',
'PAB - Panamanian Balboa',
'PGK - Papua New Guinean Kina',
'PYG - Paraguayan Guarani',
'PEN - Peruvian Nuevo Sol',
'PHP - Philippine Peso', 'PHP - Philippine Peso',
'PLN - Polish Zloty', 'PLN - Polish Zloty',
'QAR - Qatari Riyal',
'RON - Romanian Leu', 'RON - Romanian Leu',
'RUB - Russian Ruble', 'RUB - Russian Ruble',
'RWF - Rwandan Franc',
'SHP - Saint Helena Pound',
'WST - Samoan Tala',
'STD - Sao Tome And Principe Dobra',
'SAR - Saudi Riyal',
'RSD - Serbian Dinar',
'SCR - Seychellois Rupee',
'SLL - Sierra Leonean Leone',
'SGD - Singapore Dollar', 'SGD - Singapore Dollar',
'SBD - Solomon Islands Dollar',
'SOS - Somali Shilling',
'ZAR - South African Rand', 'ZAR - South African Rand',
'KRW - South Korean Won', 'KRW - South Korean Won',
'XDR - Special Drawing Rights',
'LKR - Sri Lankan Rupee',
'SDG - Sudanese Pound',
'SRD - Surinamese Dollar',
'SZL - Swazi Lilangeni',
'SEK - Swedish Krona', 'SEK - Swedish Krona',
'CHF - Swiss Franc', 'CHF - Swiss Franc',
'SYP - Syrian Pound',
'TJS - Tajikistani Somoni',
'TZS - Tanzanian Shilling',
'THB - Thai Baht', 'THB - Thai Baht',
'TTD - Trinidad and Tobago Dollar',
'TND - Tunisian Dinar',
'TRY - Turkish New Lira', 'TRY - Turkish New Lira',
'TMT - Turkmenistan Manat', 'USD - US Dollar'
'AED - UAE Dirham',
'UGX - Ugandan Shilling',
'UAH - Ukrainian Hryvnia',
'USD - United States Dollar',
'UYU - Uruguayan Peso',
'UZS - Uzbekistani Som',
'VUV - Vanuatu Vatu',
'VEF - Venezuelan Bolivar',
'VND - Vietnamese Dong',
'XOF - West African CFA Franc',
'YER - Yemeni Rial',
'ZMW - Zambian Kwacha'
]; ];

View File

@@ -17,8 +17,8 @@ mixin SafeApiCall {
if (errorResponse?["message"] != null){ if (errorResponse?["message"] != null){
error = errorResponse!["message"]; error = errorResponse!["message"];
} else if (dioError.error != null){ } else if (dioError.message.isNotEmpty){
error = dioError.error; error = dioError.message;
} else { } else {
error = "Failed to retrieve data from api"; error = "Failed to retrieve data from api";
} }

View File

@@ -3,6 +3,7 @@ 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: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'; import 'data/repository/repository.dart';

View File

@@ -62,6 +62,7 @@ Future<void> updateWidget(String? widgetId, Repository repository) async {
await HomeWidget.saveWidgetData<String>("${widgetId}_from", from); await HomeWidget.saveWidgetData<String>("${widgetId}_from", from);
await HomeWidget.saveWidgetData<String>("${widgetId}_to", to); await HomeWidget.saveWidgetData<String>("${widgetId}_to", to);
await HomeWidget.saveWidgetData<String>("${widgetId}_rate", currency.rate.toString()); await HomeWidget.saveWidgetData<String>("${widgetId}_rate", currency.rate.toString());
await HomeWidget.saveWidgetData<bool>("${widgetId}_forced_update", true);
await HomeWidget.updateWidget(name: 'AppWidgetProvider', iOSName: 'AppWidgetProvider'); await HomeWidget.updateWidget(name: 'AppWidgetProvider', iOSName: 'AppWidgetProvider');
} }
@@ -74,6 +75,7 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
title: 'Flutter Demo', title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData( theme: ThemeData(
// This is the theme of your application. // This is the theme of your application.
// //

View File

@@ -40,8 +40,8 @@ class MainViewModel extends BaseViewmodel {
(value) { (value) {
conversionRate = value.rate != null ? value.rate! : 0.00; conversionRate = value.rate != null ? value.rate! : 0.00;
onSuccess(value); onSuccess(value);
}, onError: (exception, _) { }).catchError((e) {
onError(exception.message); onError(e.message);
}); });
} }

View File

@@ -379,7 +379,7 @@ packages:
name: material_color_utilities name: material_color_utilities
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.5" version: "0.2.0"
meta: meta:
dependency: transitive dependency: transitive
description: description:
@@ -622,7 +622,7 @@ packages:
name: source_span name: source_span
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.9.0" version: "1.9.1"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@@ -685,7 +685,7 @@ packages:
name: test_api name: test_api
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.12" version: "0.4.13"
timing: timing:
dependency: transitive dependency: transitive
description: description:
@@ -734,7 +734,7 @@ packages:
name: vector_math name: vector_math
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.2" version: "2.1.3"
watcher: watcher:
dependency: transitive dependency: transitive
description: description:

View File

@@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1 version: 6.1.1+8
environment: environment:
sdk: '>=2.18.0-190.0.dev <3.0.0' sdk: '>=2.18.0-190.0.dev <3.0.0'

View File

@@ -25,6 +25,7 @@ import 'repository_test.mocks.dart';
onMissingStub: OnMissingStub.returnDefault), onMissingStub: OnMissingStub.returnDefault),
MockSpec<http.HttpResponse<CurrencyResponse>>( MockSpec<http.HttpResponse<CurrencyResponse>>(
as: #MockCurrencyResponse, onMissingStub: OnMissingStub.returnDefault), as: #MockCurrencyResponse, onMissingStub: OnMissingStub.returnDefault),
MockSpec<HttpException>(onMissingStub: OnMissingStub.returnDefault),
MockSpec<DioError>(onMissingStub: OnMissingStub.returnDefault) MockSpec<DioError>(onMissingStub: OnMissingStub.returnDefault)
]) ])
void main() { void main() {
@@ -85,7 +86,7 @@ void main() {
// When // When
when(currencyApi.getConversion("AUD", "GBP")) when(currencyApi.getConversion("AUD", "GBP"))
.thenAnswer((_) async => Future.error(MockDioError())); .thenAnswer((_) async => Future.error(MockHttpException()));
when(mockResponse.data).thenReturn(currencyResponse); when(mockResponse.data).thenReturn(currencyResponse);
when(backupCurrencyApi.getCurrencyRate("AUD", "GBP")) when(backupCurrencyApi.getCurrencyRate("AUD", "GBP"))
.thenAnswer((_) async => mockResponse); .thenAnswer((_) async => mockResponse);
@@ -98,17 +99,18 @@ void main() {
test('unable to retrieve rate from both APIs', () async { test('unable to retrieve rate from both APIs', () async {
// Given // Given
DioError backUpError = MockDioError(); MockDioError backUpError = MockDioError();
// When // When
when(backUpError.error).thenReturn("Error message"); when(backUpError.message).thenReturn("Error message");
when(currencyApi.getConversion("AUD", "GBP")) when(currencyApi.getConversion("AUD", "GBP"))
.thenAnswer((_) async => Future.error(MockDioError())); .thenAnswer((_) async => Future.error(MockDioError()));
when(backupCurrencyApi.getCurrencyRate("AUD", "GBP")) when(backupCurrencyApi.getCurrencyRate("AUD", "GBP"))
.thenAnswer((_) async => Future.error(backUpError)); .thenAnswer((_) async => Future.error(backUpError));
// Then // Then
expect(() async => expect(
() async =>
await sut.getConversationRateFromApi(fromCurrency, toCurrency), await sut.getConversationRateFromApi(fromCurrency, toCurrency),
throwsA(predicate( throwsA(predicate(
(e) => e is HttpException && e.message == 'Error message'))); (e) => e is HttpException && e.message == 'Error message')));

View File

@@ -55,8 +55,8 @@ void main() {
// Then // Then
String fromSelection = mainViewModel.getConversionPair(SelectionType.conversionFrom); String fromSelection = mainViewModel.getConversionPair(SelectionType.conversionFrom);
String toSelection = mainViewModel.getConversionPair(SelectionType.conversionTo); String toSelection = mainViewModel.getConversionPair(SelectionType.conversionTo);
expect(fromSelection, "ALL - Albanian Lek"); expect(fromSelection, "DZD - Algerian Dinar");
expect(toSelection, "ALL - Albanian Lek"); expect(toSelection, "DZD - Algerian Dinar");
}); });
test('set the currency rate from API', () async{ test('set the currency rate from API', () async{