From 01adf863d06a179332136a3fd80210a38b146265 Mon Sep 17 00:00:00 2001 From: OmarHatem28 Date: Tue, 9 Aug 2022 13:34:40 +0200 Subject: [PATCH 001/203] Add the ability to launch app from Crypto QR codes --- android/app/src/main/AndroidManifestBase.xml | 9 +++++ lib/main.dart | 37 ++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index f43b0369b..f4023f532 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -38,6 +38,15 @@ android:scheme="cakewallet" android:host="y.at" /> + + + + + + + + + with SingleTickerProviderStateMixin { super.initState(); //_handleIncomingLinks(); //_handleInitialUri(); + + initUniLinks(); } @override @@ -210,6 +212,41 @@ class AppState extends State with SingleTickerProviderStateMixin { super.dispose(); } + /// handle app links while the app is already started - be it in + /// the foreground or in the background. + Future initUniLinks() async { + try { + stream = getLinksStream().listen((String link) { + handleDeepLinking(link); + }); + + final String initialLink = await getInitialLink(); + + handleDeepLinking(initialLink); + } catch (e) { + print(e); + } + } + + void handleDeepLinking(String link) async { + if (link == null || !mounted) return; + + final List urlComponents = link.split(":"); + + switch (urlComponents.first) { + case "bitcoin": + print("@@@@@@@@@@@@@@@@@@@@@@@@@@"); + print("Bitcoin QR Code: \n${link}"); + break; + case "litecoin": + case "haven": + case "monero": + default: + print("@@@@@@@@@@@@@@@@@@@@@@@@@@"); + print(link); + } + } + Future _handleInitialUri() async { try { final uri = await getInitialUri(); From 7bccf468323fe40f8cde19a86d436669f68c81d1 Mon Sep 17 00:00:00 2001 From: OmarHatem28 Date: Tue, 9 Aug 2022 15:47:41 +0200 Subject: [PATCH 002/203] Send data from URI to send screen --- lib/di.dart | 10 ++++-- lib/main.dart | 27 ++++++++------- lib/router.dart | 7 +++- lib/src/screens/send/send_page.dart | 11 ++++-- lib/src/screens/send/widgets/send_card.dart | 37 ++++++++++++++++----- 5 files changed, 64 insertions(+), 28 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index bd911335d..bc02b3466 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/ionia/ionia_anypay.dart'; import 'package:cake_wallet/ionia/ionia_category.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; +import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_filter_view_model.dart'; @@ -372,9 +373,12 @@ Future setup( getIt.get(), _transactionDescriptionBox)); - getIt.registerFactory( - () => SendPage(sendViewModel: getIt.get(), - settingsViewModel: getIt.get())); + getIt.registerFactoryParam( + (PaymentRequest initialPaymentRequest, _) => SendPage( + sendViewModel: getIt.get(), + settingsViewModel: getIt.get(), + initialPaymentRequest: initialPaymentRequest, + )); getIt.registerFactory(() => SendTemplatePage( sendTemplateViewModel: getIt.get())); diff --git a/lib/main.dart b/lib/main.dart index 901773072..cfd242dbf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/ionia/ionia_category.dart'; import 'package:cake_wallet/ionia/ionia_merchant.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; +import 'package:cake_wallet/utils/payment_request.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -216,34 +217,32 @@ class AppState extends State with SingleTickerProviderStateMixin { /// the foreground or in the background. Future initUniLinks() async { try { - stream = getLinksStream().listen((String link) { - handleDeepLinking(link); + stream = getUriLinksStream().listen((Uri uri) { + handleDeepLinking(uri); }); - final String initialLink = await getInitialLink(); + final Uri initialUri = await getInitialUri(); - handleDeepLinking(initialLink); + handleDeepLinking(initialUri); } catch (e) { print(e); } } - void handleDeepLinking(String link) async { - if (link == null || !mounted) return; + void handleDeepLinking(Uri uri) { + if (uri == null || !mounted) return; - final List urlComponents = link.split(":"); - - switch (urlComponents.first) { + switch (uri.scheme) { case "bitcoin": - print("@@@@@@@@@@@@@@@@@@@@@@@@@@"); - print("Bitcoin QR Code: \n${link}"); - break; case "litecoin": case "haven": case "monero": default: - print("@@@@@@@@@@@@@@@@@@@@@@@@@@"); - print(link); + Navigator.pushNamed( + navigatorKey.currentContext, + Routes.send, + arguments: PaymentRequest.fromUri(uri), + ); } } diff --git a/lib/router.dart b/lib/router.dart index 1a9c3c2d5..c5079f078 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -16,6 +16,7 @@ import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; import 'package:cake_wallet/src/screens/support/support_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; +import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -207,8 +208,12 @@ Route createRoute(RouteSettings settings) { builder: (_) => getIt.get()); case Routes.send: + final initialPaymentRequest = settings.arguments as PaymentRequest; + return CupertinoPageRoute( - fullscreenDialog: true, builder: (_) => getIt.get()); + fullscreenDialog: true, builder: (_) => getIt.get( + param1: initialPaymentRequest, + )); case Routes.sendTemplate: return CupertinoPageRoute( diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 791548f3d..64e564501 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/src/screens/send/widgets/send_card.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:cake_wallet/src/widgets/template_tile.dart'; +import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:flutter/cupertino.dart'; @@ -28,13 +29,18 @@ import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'package:cw_core/crypto_currency.dart'; class SendPage extends BasePage { - SendPage({@required this.sendViewModel,@required this.settingsViewModel }) : _formKey = GlobalKey(),fiatFromSettings = settingsViewModel.fiatCurrency; + SendPage({ + @required this.sendViewModel, + @required this.settingsViewModel, + this.initialPaymentRequest, + }) : _formKey = GlobalKey(),fiatFromSettings = settingsViewModel.fiatCurrency; final SendViewModel sendViewModel; final SettingsViewModel settingsViewModel; final GlobalKey _formKey; final controller = PageController(initialPage: 0); - final FiatCurrency fiatFromSettings ; + final FiatCurrency fiatFromSettings; + final PaymentRequest initialPaymentRequest; bool _effectsInstalled = false; @@ -116,6 +122,7 @@ class SendPage extends BasePage { key: output.key, output: output, sendViewModel: sendViewModel, + initialPaymentRequest: initialPaymentRequest, ); }); }, diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 69858a3ac..27b3f49dc 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -19,23 +19,35 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; class SendCard extends StatefulWidget { - SendCard({Key key, @required this.output, @required this.sendViewModel}) : super(key: key); + SendCard({ + Key key, + @required this.output, + @required this.sendViewModel, + this.initialPaymentRequest, + }) : super(key: key); final Output output; final SendViewModel sendViewModel; + final PaymentRequest initialPaymentRequest; @override - SendCardState createState() => SendCardState( + SendCardState createState() { + return SendCardState( output: output, - sendViewModel: sendViewModel + sendViewModel: sendViewModel, + initialPaymentRequest: initialPaymentRequest, ); + } } class SendCardState extends State with AutomaticKeepAliveClientMixin { - SendCardState({@required this.output, @required this.sendViewModel}) - : addressController = TextEditingController(), - cryptoAmountController = TextEditingController(), + SendCardState({ + @required this.output, + @required this.sendViewModel, + PaymentRequest initialPaymentRequest}) + : addressController = TextEditingController(text: initialPaymentRequest?.address), + cryptoAmountController = TextEditingController(text: initialPaymentRequest?.amount), fiatAmountController = TextEditingController(), noteController = TextEditingController(), extractedAddressController = TextEditingController(), @@ -111,6 +123,11 @@ class SendCardState extends State ? sendViewModel.textValidator : sendViewModel.addressValidator; + print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + print("444444444444444444444444444444"); + print(addressController.text); + print(cryptoAmountController.text); + return AddressTextField( focusNode: addressFocusNode, controller: addressController, @@ -509,8 +526,12 @@ class SendCardState extends State } void _setEffects(BuildContext context) { - addressController.text = output.address; - cryptoAmountController.text = output.cryptoAmount; + if (output.address.isNotEmpty) { + addressController.text = output.address; + } + if (output.cryptoAmount.isNotEmpty) { + cryptoAmountController.text = output.cryptoAmount; + } fiatAmountController.text = output.fiatAmount; noteController.text = output.note; extractedAddressController.text = output.extractedAddress; From e5fac16ef77ec032b768762913dfcae62802267d Mon Sep 17 00:00:00 2001 From: OmarHatem28 Date: Tue, 9 Aug 2022 17:06:21 +0200 Subject: [PATCH 003/203] Notify user when a different currency is scanned --- lib/main.dart | 17 +++------- lib/src/screens/send/widgets/send_card.dart | 35 ++++++++++++++++----- lib/utils/payment_request.dart | 7 +++-- lib/view_model/send/send_view_model.dart | 2 ++ res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_zh.arb | 3 +- 19 files changed, 69 insertions(+), 37 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index cfd242dbf..120871fbd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -232,18 +232,11 @@ class AppState extends State with SingleTickerProviderStateMixin { void handleDeepLinking(Uri uri) { if (uri == null || !mounted) return; - switch (uri.scheme) { - case "bitcoin": - case "litecoin": - case "haven": - case "monero": - default: - Navigator.pushNamed( - navigatorKey.currentContext, - Routes.send, - arguments: PaymentRequest.fromUri(uri), - ); - } + Navigator.pushNamed( + navigatorKey.currentContext, + Routes.send, + arguments: PaymentRequest.fromUri(uri), + ); } Future _handleInitialUri() async { diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 27b3f49dc..063b9d57a 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -1,4 +1,5 @@ import 'dart:ui'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/routes.dart'; @@ -45,8 +46,8 @@ class SendCardState extends State SendCardState({ @required this.output, @required this.sendViewModel, - PaymentRequest initialPaymentRequest}) - : addressController = TextEditingController(text: initialPaymentRequest?.address), + this.initialPaymentRequest}) + : addressController = TextEditingController(text: initialPaymentRequest?.address?.toLowerCase()), cryptoAmountController = TextEditingController(text: initialPaymentRequest?.amount), fiatAmountController = TextEditingController(), noteController = TextEditingController(), @@ -60,6 +61,7 @@ class SendCardState extends State final Output output; final SendViewModel sendViewModel; + final PaymentRequest initialPaymentRequest; final TextEditingController addressController; final TextEditingController cryptoAmountController; @@ -72,6 +74,27 @@ class SendCardState extends State bool _effectsInstalled = false; + @override + void initState() { + super.initState(); + + /// if the current wallet doesn't match the one in the qr code + if (initialPaymentRequest != null && + sendViewModel.walletCurrencyName != initialPaymentRequest.scheme?.toLowerCase()) { + WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { + showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.of(context).error, + alertContent: S.of(context).unmatched_currencies, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); + }); + } + } + @override Widget build(BuildContext context) { super.build(context); @@ -123,11 +146,6 @@ class SendCardState extends State ? sendViewModel.textValidator : sendViewModel.addressValidator; - print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - print("444444444444444444444444444444"); - print(addressController.text); - print(cryptoAmountController.text); - return AddressTextField( focusNode: addressFocusNode, controller: addressController, @@ -529,7 +547,8 @@ class SendCardState extends State if (output.address.isNotEmpty) { addressController.text = output.address; } - if (output.cryptoAmount.isNotEmpty) { + if (output.cryptoAmount.isNotEmpty || + sendViewModel.walletCurrencyName != initialPaymentRequest?.scheme?.toLowerCase()) { cryptoAmountController.text = output.cryptoAmount; } fiatAmountController.text = output.fiatAmount; diff --git a/lib/utils/payment_request.dart b/lib/utils/payment_request.dart index d4338a39a..3830c69cb 100644 --- a/lib/utils/payment_request.dart +++ b/lib/utils/payment_request.dart @@ -1,18 +1,21 @@ class PaymentRequest { - PaymentRequest(this.address, this.amount); + PaymentRequest(this.address, this.amount, {this.scheme}); factory PaymentRequest.fromUri(Uri uri) { var address = ""; var amount = ""; + var scheme = ""; if (uri != null) { address = uri.path; amount = uri.queryParameters['tx_amount'] ?? uri.queryParameters['amount'] ?? ""; + scheme = uri.scheme; } - return PaymentRequest(address, amount); + return PaymentRequest(address, amount, scheme: scheme); } final String address; final String amount; + final String scheme; } \ No newline at end of file diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index b615c00c4..1b06d2421 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -157,6 +157,8 @@ abstract class SendViewModelBase with Store { WalletType get walletType => _wallet.type; + String get walletCurrencyName => _wallet.currency.name.toLowerCase(); + bool get hasCurrecyChanger => walletType == WalletType.haven; final WalletBase _wallet; diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index d9687bc36..7791563f9 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -632,5 +632,6 @@ "gift_card_is_generated": "Geschenkkarte wird generiert", "open_gift_card": "Geschenkkarte öffnen", "contact_support": "Support kontaktieren", - "gift_cards_unavailable": "Geschenkkarten können derzeit nur über Monero, Bitcoin und Litecoin erworben werden" + "gift_cards_unavailable": "Geschenkkarten können derzeit nur über Monero, Bitcoin und Litecoin erworben werden", + "unmatched_currencies": "Die Währung Ihres aktuellen Wallets stimmt nicht mit der des gescannten QR überein" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 9fc0b743e..ff88286ac 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -632,5 +632,6 @@ "gift_card_is_generated": "Gift Card is generated", "open_gift_card": "Open Gift Card", "contact_support": "Contact Support", - "gift_cards_unavailable": "Gift cards are available for purchase only with Monero, Bitcoin, and Litecoin at this time" + "gift_cards_unavailable": "Gift cards are available for purchase only with Monero, Bitcoin, and Litecoin at this time", + "unmatched_currencies": "Your current wallet's currency does not match that of the scanned QR" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 084658081..685770f13 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -632,5 +632,6 @@ "gift_card_is_generated": "Se genera la tarjeta de regalo", "open_gift_card": "Abrir tarjeta de regalo", "contact_support": "Contactar con Soporte", - "gift_cards_unavailable": "Las tarjetas de regalo están disponibles para comprar solo a través de Monero, Bitcoin y Litecoin en este momento" + "gift_cards_unavailable": "Las tarjetas de regalo están disponibles para comprar solo a través de Monero, Bitcoin y Litecoin en este momento", + "unmatched_currencies": "La moneda de su billetera actual no coincide con la del QR escaneado" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 9817e7bef..e348912df 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -630,5 +630,6 @@ "gift_card_is_generated": "La carte-cadeau est générée", "open_gift_card": "Ouvrir la carte-cadeau", "contact_support": "Contacter l'assistance", - "gift_cards_unavailable": "Les cartes-cadeaux ne sont disponibles à l'achat que via Monero, Bitcoin et Litecoin pour le moment" + "gift_cards_unavailable": "Les cartes-cadeaux ne sont disponibles à l'achat que via Monero, Bitcoin et Litecoin pour le moment", + "unmatched_currencies": "La devise de votre portefeuille actuel ne correspond pas à celle du QR scanné" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 03a891169..22e429b7e 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -632,5 +632,6 @@ "gift_card_is_generated": "गिफ्ट कार्ड जनरेट हुआ", "open_gift_card": "गिफ्ट कार्ड खोलें", "contact_support": "सहायता से संपर्क करें", - "gift_cards_unavailable": "उपहार कार्ड इस समय केवल मोनेरो, बिटकॉइन और लिटकोइन के माध्यम से खरीदने के लिए उपलब्ध हैं" + "gift_cards_unavailable": "उपहार कार्ड इस समय केवल मोनेरो, बिटकॉइन और लिटकोइन के माध्यम से खरीदने के लिए उपलब्ध हैं", + "unmatched_currencies": "आपके वर्तमान वॉलेट की मुद्रा स्कैन किए गए क्यूआर से मेल नहीं खाती" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index c25b54eb8..ea29a7491 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -632,5 +632,6 @@ "gift_card_is_generated": "Poklon kartica je generirana", "open_gift_card": "Otvori darovnu karticu", "contact_support": "Kontaktirajte podršku", - "gift_cards_unavailable": "Poklon kartice trenutno su dostupne za kupnju samo putem Monera, Bitcoina i Litecoina" + "gift_cards_unavailable": "Poklon kartice trenutno su dostupne za kupnju samo putem Monera, Bitcoina i Litecoina", + "unmatched_currencies": "Valuta vašeg trenutnog novčanika ne odgovara onoj na skeniranom QR-u" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 8383c9ad9..2e0793283 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -632,5 +632,6 @@ "gift_card_is_generated": "Il buono regalo è stato generato", "open_gift_card": "Apri carta regalo", "contact_support": "Contatta l'assistenza", - "gift_cards_unavailable": "Le carte regalo sono disponibili per l'acquisto solo tramite Monero, Bitcoin e Litecoin in questo momento" + "gift_cards_unavailable": "Le carte regalo sono disponibili per l'acquisto solo tramite Monero, Bitcoin e Litecoin in questo momento", + "unmatched_currencies": "La valuta del tuo portafoglio attuale non corrisponde a quella del QR scansionato" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 0ee7b5f29..e0bd967e9 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -632,5 +632,6 @@ "gift_card_is_generated": "ギフトカードが生成されます", "open_gift_card": "オープンギフトカード", "contact_support": "サポートに連絡する", - "gift_cards_unavailable": "現時点では、ギフトカードはMonero、Bitcoin、Litecoinからのみ購入できます。" + "gift_cards_unavailable": "現時点では、ギフトカードはMonero、Bitcoin、Litecoinからのみ購入できます。", + "unmatched_currencies": "現在のウォレットの通貨がスキャンされたQRの通貨と一致しません" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index d7ee849aa..5f60de560 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -632,5 +632,6 @@ "gift_card_is_generated": "기프트 카드가 생성되었습니다", "open_gift_card": "기프트 카드 열기", "contact_support": "지원팀에 문의", - "gift_cards_unavailable": "기프트 카드는 현재 Monero, Bitcoin 및 Litecoin을 통해서만 구매할 수 있습니다." + "gift_cards_unavailable": "기프트 카드는 현재 Monero, Bitcoin 및 Litecoin을 통해서만 구매할 수 있습니다.", + "unmatched_currencies": "현재 지갑의 통화가 스캔한 QR의 통화와 일치하지 않습니다." } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 967cf1e38..e9c43fc01 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -632,5 +632,6 @@ "gift_card_is_generated": "Cadeaukaart is gegenereerd", "open_gift_card": "Geschenkkaart openen", "contact_support": "Contact opnemen met ondersteuning", - "gift_cards_unavailable": "Cadeaubonnen kunnen momenteel alleen worden gekocht via Monero, Bitcoin en Litecoin" + "gift_cards_unavailable": "Cadeaubonnen kunnen momenteel alleen worden gekocht via Monero, Bitcoin en Litecoin", + "unmatched_currencies": "De valuta van uw huidige portemonnee komt niet overeen met die van de gescande QR" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index be58b6a17..42bdcde86 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -632,5 +632,6 @@ "gift_card_is_generated": "Karta podarunkowa jest generowana", "open_gift_card": "Otwórz kartę podarunkową", "contact_support": "Skontaktuj się z pomocą techniczną", - "gift_cards_unavailable": "Karty podarunkowe można obecnie kupić tylko za pośrednictwem Monero, Bitcoin i Litecoin" + "gift_cards_unavailable": "Karty podarunkowe można obecnie kupić tylko za pośrednictwem Monero, Bitcoin i Litecoin", + "unmatched_currencies": "Waluta Twojego obecnego portfela nie odpowiada walucie zeskanowanego kodu QR" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 50aa25100..8d2d52ded 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -632,5 +632,6 @@ "gift_card_is_generated": "Cartão presente é gerado", "open_gift_card": "Abrir vale-presente", "contact_support": "Contatar Suporte", - "gift_cards_unavailable": "Os cartões-presente estão disponíveis para compra apenas através do Monero, Bitcoin e Litecoin no momento" + "gift_cards_unavailable": "Os cartões-presente estão disponíveis para compra apenas através do Monero, Bitcoin e Litecoin no momento", + "unmatched_currencies": "A moeda da sua carteira atual não corresponde à do QR digitalizado" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index ce8109512..0cd899be4 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -632,5 +632,6 @@ "gift_card_is_generated": "Подарочная карта сгенерирована", "open_gift_card": "Открыть подарочную карту", "contact_support": "Связаться со службой поддержки", - "gift_cards_unavailable": "В настоящее время подарочные карты можно приобрести только через Monero, Bitcoin и Litecoin." + "gift_cards_unavailable": "В настоящее время подарочные карты можно приобрести только через Monero, Bitcoin и Litecoin.", + "unmatched_currencies": "Валюта вашего текущего кошелька не соответствует валюте отсканированного QR-кода." } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 04e270d57..8ca95cae4 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -631,5 +631,6 @@ "gift_card_is_generated": "Подарункова картка створена", "open_gift_card": "Відкрити подарункову картку", "contact_support": "Звернутися до служби підтримки", - "gift_cards_unavailable": "Наразі подарункові картки можна придбати лише через Monero, Bitcoin і Litecoin" + "gift_cards_unavailable": "Наразі подарункові картки можна придбати лише через Monero, Bitcoin і Litecoin", + "unmatched_currencies": "Валюта вашого гаманця не збігається з валютою сканованого QR-коду" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 14af48137..2c5eb6dfc 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -630,5 +630,6 @@ "gift_card_is_generated": "礼品卡生成", "open_gift_card": "打开礼品卡", "contact_support": "联系支持", - "gift_cards_unavailable": "目前只能通过门罗币、比特币和莱特币购买礼品卡" + "gift_cards_unavailable": "目前只能通过门罗币、比特币和莱特币购买礼品卡", + "unmatched_currencies": "您当前钱包的货币与扫描的 QR 的货币不匹配" } From 13a95ab11f6205f312d101e47f6e4d4aa6c1aee6 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Tue, 6 Sep 2022 09:09:44 +0300 Subject: [PATCH 004/203] fix color for login back button --- lib/src/screens/ionia/auth/ionia_login_page.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/src/screens/ionia/auth/ionia_login_page.dart b/lib/src/screens/ionia/auth/ionia_login_page.dart index bcbc0fee3..44df933b5 100644 --- a/lib/src/screens/ionia/auth/ionia_login_page.dart +++ b/lib/src/screens/ionia/auth/ionia_login_page.dart @@ -26,9 +26,6 @@ class IoniaLoginPage extends BasePage { final IoniaAuthViewModel _authViewModel; - @override - Color get titleColor => Colors.black; - final TextEditingController _emailController; @override From 406707fa5862cdb5de832ccd5378ad9b1c283fd1 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Tue, 13 Sep 2022 08:13:20 +0300 Subject: [PATCH 005/203] fix partial redemption --- lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart b/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart index 4bb76848f..c85108be4 100644 --- a/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart +++ b/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart @@ -149,7 +149,7 @@ class IoniaCustomRedeemPage extends BasePage { padding: EdgeInsets.only(bottom: 12), child: PrimaryButton( onPressed: () { - Navigator.of(context).pop(_amountController.text); + Navigator.of(context).pop(ioniaCustomRedeemViewModel.remaining.toString()); }, isDisabled: ioniaCustomRedeemViewModel.disableRedeem, text: S.of(context).add_custom_redemption, From d748f12e4441a7383c0a86c169c94053a4815314 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 4 Oct 2022 14:54:39 +0200 Subject: [PATCH 006/203] Allow marking Monero Nodes as trusted --- cw_core/lib/node.dart | 11 +++++++++-- .../screens/nodes/node_create_or_edit_page.dart | 17 ++++++++++++++++- .../node_create_or_edit_view_model.dart | 9 +++++++-- res/values/strings_de.arb | 1 + res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 2 +- res/values/strings_ru.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_zh.arb | 1 + 18 files changed, 47 insertions(+), 6 deletions(-) diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 7de2e84b6..dd5969b99 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -20,7 +20,8 @@ class Node extends HiveObject with Keyable { @required WalletType type, this.login, this.password, - this.useSSL}) { + this.useSSL, + this.trusted}) { uriRaw = uri; this.type = type; } @@ -30,7 +31,8 @@ class Node extends HiveObject with Keyable { login = map['login'] as String, password = map['password'] as String, typeRaw = map['typeRaw'] as int, - useSSL = map['useSSL'] as bool; + useSSL = map['useSSL'] as bool, + trusted = map['trusted'] as bool ?? false; static const typeId = 1; static const boxName = 'Nodes'; @@ -50,8 +52,13 @@ class Node extends HiveObject with Keyable { @HiveField(4) bool useSSL; + @HiveField(5) + bool trusted; + bool get isSSL => useSSL ?? false; + bool get isTrusted => trusted ?? false; + Uri get uri { switch (type) { case WalletType.monero: diff --git a/lib/src/screens/nodes/node_create_or_edit_page.dart b/lib/src/screens/nodes/node_create_or_edit_page.dart index 6cfa67285..857bde023 100644 --- a/lib/src/screens/nodes/node_create_or_edit_page.dart +++ b/lib/src/screens/nodes/node_create_or_edit_page.dart @@ -174,7 +174,22 @@ class NodeCreateOrEditPage extends BasePage { caption: S.of(context).use_ssl, )) ], - )) + )), + Padding( + padding: EdgeInsets.only(top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Observer( + builder: (_) => StandardCheckbox( + value: nodeCreateOrEditViewModel.trusted, + onChanged: (value) => + nodeCreateOrEditViewModel.trusted = value, + caption: S.of(context).trusted, + )) + ], + )), ] ], )), diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index ef7e03189..c14bdda5e 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -14,7 +14,8 @@ abstract class NodeCreateOrEditViewModelBase with Store { NodeCreateOrEditViewModelBase(this._nodeSource, this._wallet) : state = InitialExecutionState(), connectionState = InitialExecutionState(), - useSSL = false; + useSSL = false, + trusted = false; @observable ExecutionState state; @@ -37,6 +38,9 @@ abstract class NodeCreateOrEditViewModelBase with Store { @observable bool useSSL; + @observable + bool trusted; + @computed bool get isReady => (address?.isNotEmpty ?? false) && (port?.isNotEmpty ?? false); @@ -64,6 +68,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { login = ''; password = ''; useSSL = false; + trusted = false; } @action @@ -72,7 +77,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { state = IsExecutingState(); final node = Node(uri: uri, type: _wallet.type, login: login, password: password, - useSSL: useSSL); + useSSL: useSSL, trusted: trusted); await _nodeSource.add(node); state = ExecutedSuccessfullyState(); } catch (e) { diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 3457f8ab2..fa04a6a8e 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -436,6 +436,7 @@ "provider_error" : "${provider}-Fehler", "use_ssl" : "SSL verwenden", + "trusted" : "Vertrauenswürdige", "color_theme" : "Farbthema", "light_theme" : "Hell", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index ef8e6e495..4a46d36c8 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -436,6 +436,7 @@ "provider_error" : "${provider} error", "use_ssl" : "Use SSL", + "trusted" : "Trusted", "color_theme" : "Color theme", "light_theme" : "Light", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 7c996134e..756ac3e11 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -436,6 +436,7 @@ "provider_error" : "${provider} error", "use_ssl" : "Utilice SSL", + "trusted" : "de confianza", "color_theme" : "Tema de color", "light_theme" : "Ligera", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index b347086ae..04462943e 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -434,6 +434,7 @@ "provider_error" : "Erreur de ${provider}", "use_ssl" : "Utiliser SSL", + "trusted" : "de confiance", "color_theme" : "Thème", "light_theme" : "Clair", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 83c0808c4..f8bad76e2 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -436,6 +436,7 @@ "provider_error" : "${provider} त्रुटि", "use_ssl" : "उपयोग SSL", + "trusted" : "भरोसा", "color_theme" : "रंग विषय", "light_theme" : "रोशनी", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 97d4d335c..0e27e3a2c 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -436,6 +436,7 @@ "provider_error" : "${provider} greška", "use_ssl" : "Koristi SSL", + "trusted" : "vjerovao", "color_theme" : "Shema boja", "light_theme" : "Svijetla", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index cd779471f..ea9bbd5be 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -436,6 +436,7 @@ "provider_error" : "${provider} errore", "use_ssl" : "Usa SSL", + "trusted" : "di fiducia", "color_theme" : "Colore tema", "light_theme" : "Bianco", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 2b3920862..5ae3a5a1a 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -436,6 +436,7 @@ "provider_error" : "${provider} エラー", "use_ssl" : "SSLを使用する", + "trusted" : "信頼できる", "color_theme" : "カラーテーマ", "light_theme" : "光", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 85ece0603..f934784ba 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -436,6 +436,7 @@ "provider_error" : "${provider} 오류", "use_ssl" : "SSL 사용", + "trusted" : "신뢰할 수 있는", "color_theme" : "색상 테마", "light_theme" : "빛", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 15da6fd7b..428da3d76 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -436,6 +436,7 @@ "provider_error" : "${provider} fout", "use_ssl" : "Gebruik SSL", + "trusted" : "vertrouwd", "color_theme" : "Kleur thema", "light_theme" : "Licht", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 26d8a38d4..fda0ea721 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -436,6 +436,7 @@ "provider_error" : "${provider} pomyłka", "use_ssl" : "Użyj SSL", + "trusted" : "zaufany", "color_theme" : "Motyw kolorystyczny", "light_theme" : "Lekki", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index bfb4a2d0a..6a55cf534 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -436,6 +436,7 @@ "provider_error" : "${provider} erro", "use_ssl" : "Use SSL", + "trusted" : "confiável", "color_theme" : "Tema de cor", "light_theme" : "Luz", @@ -544,7 +545,6 @@ "create_account": "Criar conta", "privacy_policy": "Política de privacidade", "welcome_to_cakepay": "Bem-vindo ao Cake Pay!", - "create_account": "Registar-se", "forgot_password": "Esqueci a senha", "reset_password": "Redefinir senha", "gift_cards": "Cartões de presente", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 94a5b3c0b..ebc4a615c 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -436,6 +436,7 @@ "provider_error" : "${provider} ошибка", "use_ssl" : "Использовать SSL", + "trusted" : "доверенный", "color_theme" : "Цветовая тема", "light_theme" : "Светлая", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index b139750be..efbd5a3b8 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -435,6 +435,7 @@ "provider_error" : "${provider} помилка", "use_ssl" : "Використати SSL", + "trusted" : "довіряють", "color_theme" : "Кольорова тема", "light_theme" : "Світла", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 487c6be52..83990cf2e 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -435,6 +435,7 @@ "provider_error" : "${provider} 错误", "use_ssl" : "使用SSL", + "trusted" : "值得信赖", "color_theme" : "主题", "light_theme" : "艳丽", From c37bfb2e83d2fe2ff48d911256b689dd8b53a03d Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 5 Oct 2022 15:57:17 +0200 Subject: [PATCH 007/203] Add Advanced privacy settings page and initial view model --- .../advanced_privacy_settings_page.dart | 173 ++++++++++++++++++ .../privacy_settings_view_model.dart | 54 ++++++ 2 files changed, 227 insertions(+) create mode 100644 lib/src/screens/new_wallet/advanced_privacy_settings_page.dart create mode 100644 lib/view_model/privacy_settings_view_model.dart diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart new file mode 100644 index 000000000..149b65d2e --- /dev/null +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -0,0 +1,173 @@ +import 'package:cake_wallet/entities/generate_name.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/view_model/privacy_settings_view_model.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/core/wallet_name_validator.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; + +class AdvancedPrivacySettingsPage extends BasePage { + AdvancedPrivacySettingsPage(this.privacySettingsViewModel); + + final PrivacySettingsViewModel privacySettingsViewModel; + + @override + String get title => S.current.privacy_settings; + + @override + Widget body(BuildContext context) => + AdvancedPrivacySettingsBody(privacySettingsViewModel); +} + +class AdvancedPrivacySettingsBody extends StatefulWidget { + const AdvancedPrivacySettingsBody(this.privacySettingsViewModel, {Key key}) + : super(key: key); + + final PrivacySettingsViewModel privacySettingsViewModel; + + @override + _AdvancedPrivacySettingsBodyState createState() => + _AdvancedPrivacySettingsBodyState(privacySettingsViewModel); +} + +class _AdvancedPrivacySettingsBodyState + extends State { + _AdvancedPrivacySettingsBodyState(this.privacySettingsViewModel); + + final PrivacySettingsViewModel privacySettingsViewModel; + + final _formKey = GlobalKey(); + + final TextEditingController _controller = TextEditingController(); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 24), + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), + content: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ...privacySettingsViewModel.settings.map( + (item) => Observer( + builder: (_) => SettingsSwitcherCell( + title: item.title, + value: item.value(), + onValueChange: item.onValueChange, + ), + ), + ), + Observer( + builder: (_) { + if (privacySettingsViewModel.addCustomNode) { + return Padding( + padding: EdgeInsets.only(top: 24), + child: Form( + key: _formKey, + child: TextFormField( + onChanged: (value) {}, + controller: _controller, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 20.0, + fontWeight: FontWeight.w600, + color: + Theme.of(context).primaryTextTheme.title.color), + decoration: InputDecoration( + hintStyle: TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .accentTextTheme + .display3 + .color), + hintText: S.of(context).wallet_name, + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: Theme.of(context) + .accentTextTheme + .display3 + .decorationColor, + width: 1.0), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: Theme.of(context) + .accentTextTheme + .display3 + .decorationColor, + width: 1.0), + ), + suffixIcon: IconButton( + onPressed: () async { + final rName = await generateName(); + FocusManager.instance.primaryFocus?.unfocus(); + + setState(() { + _controller.text = rName; + _controller.selection = + TextSelection.fromPosition( + TextPosition(offset: _controller.text.length), + ); + }); + }, + icon: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6.0), + color: Theme.of(context).hintColor, + ), + width: 34, + height: 34, + child: Image.asset( + 'assets/images/refresh_icon.png', + color: Theme.of(context) + .primaryTextTheme + .display1 + .decorationColor, + ), + ), + ), + ), + validator: WalletNameValidator(), + ), + ), + ); + } + return const SizedBox(); + }, + ), + ], + ), + bottomSectionPadding: EdgeInsets.all(24), + bottomSection: Column( + children: [ + LoadingPrimaryButton( + onPressed: () {}, + text: S.of(context).continue_text, + color: Theme.of(context).accentTextTheme.body2.color, + textColor: Colors.white, + ), + const SizedBox(height: 25), + Padding( + padding: EdgeInsets.symmetric( + horizontal: MediaQuery.of(context).size.width * 0.15), + child: Text( + S.of(context).settings_can_be_changed_later, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).accentTextTheme.display3.color, + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/view_model/privacy_settings_view_model.dart b/lib/view_model/privacy_settings_view_model.dart new file mode 100644 index 000000000..ce5a3f7a6 --- /dev/null +++ b/lib/view_model/privacy_settings_view_model.dart @@ -0,0 +1,54 @@ +import 'package:cake_wallet/view_model/settings/switcher_list_item.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/generated/i18n.dart'; + +part 'privacy_settings_view_model.g.dart'; + +class PrivacySettingsViewModel = PrivacySettingsViewModelBase + with _$PrivacySettingsViewModel; + +abstract class PrivacySettingsViewModelBase with Store { + PrivacySettingsViewModelBase(this.type) { + _disableFiat = false; + _disableExchange = false; + _addCustomNode = false; + + settings = [ + SwitcherListItem( + title: "Disable Fiat API", + // title: S.current.disable_fiat, + value: () => _disableFiat, + onValueChange: (_, bool value) => _disableFiat = value, + ), + SwitcherListItem( + title: "Disable Exchange", + // title: S.current.disable_exchange, + value: () => _disableExchange, + onValueChange: (_, bool value) => _disableExchange = value, + ), + SwitcherListItem( + title: "Add New Custom Node", + // title: S.current.add_custom_node, + value: () => _addCustomNode, + onValueChange: (_, bool value) => _addCustomNode = value, + ), + ]; + } + + List settings; + + @observable + bool _disableFiat; + + @observable + bool _disableExchange; + + @observable + bool _addCustomNode; + + final WalletType type; + + @computed + bool get addCustomNode => _addCustomNode; +} From 6bbedde9b7920ec090037a4ed16a89bf5f7a9b64 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 5 Oct 2022 15:58:25 +0200 Subject: [PATCH 008/203] Add privacy settings route Add text translation --- lib/di.dart | 4 +++ lib/router.dart | 9 +++++ lib/routes.dart | 1 + .../screens/new_wallet/new_wallet_page.dart | 35 ++++++++++++------- res/values/strings_de.arb | 5 ++- res/values/strings_en.arb | 5 ++- res/values/strings_es.arb | 5 ++- res/values/strings_fr.arb | 5 ++- res/values/strings_hi.arb | 5 ++- res/values/strings_hr.arb | 5 ++- res/values/strings_it.arb | 5 ++- res/values/strings_ja.arb | 5 ++- res/values/strings_ko.arb | 5 ++- res/values/strings_nl.arb | 5 ++- res/values/strings_pl.arb | 5 ++- res/values/strings_pt.arb | 5 ++- res/values/strings_ru.arb | 5 ++- res/values/strings_uk.arb | 5 ++- res/values/strings_zh.arb | 5 ++- 19 files changed, 97 insertions(+), 27 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index 5cc698d27..8dfbfd788 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -25,6 +25,7 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart'; import 'package:cake_wallet/view_model/ionia/ionia_account_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart'; +import 'package:cake_wallet/view_model/privacy_settings_view_model.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cake_wallet/core/backup_service.dart'; import 'package:cw_core/wallet_service.dart'; @@ -786,5 +787,8 @@ Future setup( (IoniaAnyPayPaymentInfo paymentInfo, AnyPayPaymentCommittedInfo committedInfo) => IoniaPaymentStatusPage(getIt.get(param1: paymentInfo, param2: committedInfo))); + getIt.registerFactoryParam((type, _) => + PrivacySettingsViewModel(type)); + _isSetupFinished = true; } diff --git a/lib/router.dart b/lib/router.dart index 051e07cb0..b19fb198e 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -10,6 +10,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dar import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_tip_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; +import 'package:cake_wallet/src/screens/new_wallet/advanced_privacy_settings_page.dart'; import 'package:cake_wallet/src/screens/order_details/order_details_page.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; @@ -19,6 +20,7 @@ import 'package:cake_wallet/src/screens/support/support_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; +import 'package:cake_wallet/view_model/privacy_settings_view_model.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; @@ -471,6 +473,13 @@ Route createRoute(RouteSettings settings) { param1: paymentInfo, param2: commitedInfo)); + case Routes.privacySettings: + final type = settings.arguments as WalletType; + final privacySettingsViewModel = getIt.get(param1: type); + + return CupertinoPageRoute( + builder: (_) => AdvancedPrivacySettingsPage(privacySettingsViewModel)); + default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/routes.dart b/lib/routes.dart index 7431d71df..8b0a6ca03 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -76,4 +76,5 @@ class Routes { static const ioniaPaymentStatusPage = '/ionia_payment_status_page'; static const ioniaMoreOptionsPage = '/ionia_more_options_page'; static const ioniaCustomRedeemPage = '/ionia_custom_redeem_page'; + static const privacySettings = '/privacy_settings'; } diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 2ea1eca94..8aef74445 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -198,18 +198,29 @@ class _WalletNameFormState extends State { ] ]), bottomSectionPadding: - EdgeInsets.only(left: 24, right: 24, bottom: 24), - bottomSection: Observer( - builder: (context) { - return LoadingPrimaryButton( - onPressed: _confirmForm, - text: S.of(context).seed_language_next, - color: Colors.green, - textColor: Colors.white, - isLoading: _walletNewVM.state is IsExecutingState, - isDisabled: _walletNewVM.name.isEmpty, - ); - }, + EdgeInsets.all(24), + bottomSection: Column( + children: [ + Observer( + builder: (context) { + return LoadingPrimaryButton( + onPressed: _confirmForm, + text: S.of(context).seed_language_next, + color: Colors.green, + textColor: Colors.white, + isLoading: _walletNewVM.state is IsExecutingState, + isDisabled: _walletNewVM.name.isEmpty, + ); + }, + ), + const SizedBox(height: 25), + GestureDetector( + onTap: () { + Navigator.of(context).pushNamed(Routes.privacySettings); + }, + child: Text(S.of(context).advanced_privacy_settings), + ), + ], )), ); } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index fa04a6a8e..fa896eb97 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -644,5 +644,8 @@ "choose_from_available_options": "Wähle aus verfügbaren Optionen:", "custom_redeem_amount": "Benutzerdefinierter Einlösungsbetrag", "add_custom_redemption": "Benutzerdefinierte Einlösung hinzufügen", - "remaining": "Rest" + "remaining": "Rest", + "advanced_privacy_settings": "Erweiterte Datenschutzeinstellungen", + "privacy_settings": "Datenschutzeinstellungen", + "settings_can_be_changed_later": "Diese Einstellungen können später in den App-Einstellungen geändert werden" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 4a46d36c8..a79f66cc2 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -644,5 +644,8 @@ "choose_from_available_options": "Choose from the available options:", "custom_redeem_amount": "Custom Redeem Amount", "add_custom_redemption": "Add Custom Redemption", - "remaining": "remaining" + "remaining": "remaining", + "advanced_privacy_settings": "Advanced Privacy Settings", + "privacy_settings": "Privacy Settings", + "settings_can_be_changed_later": "These settings can be changed later in the app settings" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 756ac3e11..b953ccd45 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -644,5 +644,8 @@ "choose_from_available_options": "Elija entre las opciones disponibles:", "custom_redeem_amount": "Cantidad de canje personalizada", "add_custom_redemption": "Agregar redención personalizada", - "remaining": "restante" + "remaining": "restante", + "advanced_privacy_settings": "Configuración avanzada de privacidad", + "privacy_settings": "La configuración de privacidad", + "settings_can_be_changed_later": "Estas configuraciones se pueden cambiar más tarde en la configuración de la aplicación" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 04462943e..b62ae92a4 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -642,5 +642,8 @@ "choose_from_available_options": "Choisissez parmi les options disponibles :", "custom_redeem_amount": "Montant d'échange personnalisé", "add_custom_redemption": "Ajouter un remboursement personnalisé", - "remaining": "restant" + "remaining": "restant", + "advanced_privacy_settings": "Paramètres de confidentialité avancés", + "privacy_settings": "Paramètres de confidentialité", + "settings_can_be_changed_later": "Ces paramètres peuvent être modifiés ultérieurement dans les paramètres de l'application" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index f8bad76e2..932118e9a 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -644,5 +644,8 @@ "choose_from_available_options": "उपलब्ध विकल्पों में से चुनें:", "custom_redeem_amount": "कस्टम रिडीम राशि", "add_custom_redemption": "कस्टम रिडेम्पशन जोड़ें", - "remaining": "शेष" + "remaining": "शेष", + "advanced_privacy_settings": "उन्नत गोपनीयता सेटिंग्स", + "privacy_settings": "गोपनीय सेटिंग", + "settings_can_be_changed_later": "इन सेटिंग्स को बाद में ऐप सेटिंग में बदला जा सकता है" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 0e27e3a2c..7eebebdc9 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -644,5 +644,8 @@ "choose_from_available_options": "Odaberite neku od dostupnih opcija:", "custom_redeem_amount": "Prilagođeni iznos otkupa", "add_custom_redemption": "Dodaj prilagođeni otkup", - "remaining": "preostalo" + "remaining": "preostalo", + "advanced_privacy_settings": "Napredne postavke privatnosti", + "privacy_settings": "Postavke privatnosti", + "settings_can_be_changed_later": "Te se postavke mogu promijeniti kasnije u postavkama aplikacije" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index ea9bbd5be..a1333dae4 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -644,5 +644,8 @@ "choose_from_available_options": "Scegli tra le opzioni disponibili:", "custom_redeem_amount": "Importo di riscatto personalizzato", "add_custom_redemption": "Aggiungi riscatto personalizzato", - "remaining": "rimanente" + "remaining": "rimanente", + "advanced_privacy_settings": "Impostazioni avanzate sulla privacy", + "privacy_settings": "Impostazioni della privacy", + "settings_can_be_changed_later": "Queste impostazioni possono essere modificate in seguito nelle impostazioni dell'app" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 5ae3a5a1a..733dc4a00 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -644,5 +644,8 @@ "choose_from_available_options": "利用可能なオプションから選択してください:", "custom_redeem_amount": "カスタム交換金額", "add_custom_redemption": "カスタム引き換えを追加", - "remaining": "残り" + "remaining": "残り", + "advanced_privacy_settings": "高度なプライバシー設定", + "privacy_settings": "プライバシー設定", + "settings_can_be_changed_later": "これらの設定は、後でアプリの設定で変更できます" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index f934784ba..c1069c003 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -644,5 +644,8 @@ "choose_from_available_options": "사용 가능한 옵션에서 선택:", "custom_redeem_amount": "사용자 지정 상환 금액", "add_custom_redemption": "사용자 지정 상환 추가", - "remaining": "남은" + "remaining": "남은", + "advanced_privacy_settings": "고급 개인 정보 설정", + "privacy_settings": "개인 정보 설정", + "settings_can_be_changed_later": "이 설정은 나중에 앱 설정에서 변경할 수 있습니다." } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 428da3d76..fc3ab96cd 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -644,5 +644,8 @@ "choose_from_available_options": "Kies uit de beschikbare opties:", "custom_redeem_amount": "Aangepast inwisselbedrag", "add_custom_redemption": "Voeg aangepaste inwisseling toe", - "remaining": "resterende" + "remaining": "resterende", + "advanced_privacy_settings": "Geavanceerde privacy-instellingen", + "privacy_settings": "Privacy instellingen", + "settings_can_be_changed_later": "Deze instellingen kunnen later worden gewijzigd in de app-instellingen" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index fda0ea721..eb5f9d06c 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -644,5 +644,8 @@ "choose_from_available_options": "Wybierz z dostępnych opcji:", "custom_redeem_amount": "Niestandardowa kwota wykorzystania", "add_custom_redemption": "Dodaj niestandardowe wykorzystanie", - "remaining": "pozostałe" + "remaining": "pozostałe", + "advanced_privacy_settings": "Zaawansowane ustawienia prywatności", + "privacy_settings": "Ustawienia prywatności", + "settings_can_be_changed_later": "Te ustawienia można później zmienić w ustawieniach aplikacji" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 6a55cf534..a33bbb060 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -643,5 +643,8 @@ "choose_from_available_options": "Escolha entre as opções disponíveis:", "custom_redeem_amount": "Valor de resgate personalizado", "add_custom_redemption": "Adicionar resgate personalizado", - "remaining": "restante" + "remaining": "restante", + "advanced_privacy_settings": "Configurações de privacidade avançadas", + "privacy_settings": "Configurações de privacidade", + "settings_can_be_changed_later": "Essas configurações podem ser alteradas posteriormente nas configurações do aplicativo" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index ebc4a615c..efa90deec 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -644,5 +644,8 @@ "choose_from_available_options": "Выберите из доступных вариантов:", "custom_redeem_amount": "Пользовательская сумма погашения", "add_custom_redemption": "Добавить пользовательское погашение", - "remaining": "осталось" + "remaining": "осталось", + "advanced_privacy_settings": "Расширенные настройки конфиденциальности", + "privacy_settings": "Настройки конфиденциальности", + "settings_can_be_changed_later": "Эти настройки можно изменить позже в настройках приложения." } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index efbd5a3b8..fbc47a619 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -643,5 +643,8 @@ "choose_from_available_options": "Виберіть із доступних варіантів:", "custom_redeem_amount": "Власна сума викупу", "add_custom_redemption": "Додати спеціальне погашення", - "remaining": "залишилося" + "remaining": "залишилося", + "advanced_privacy_settings": "Розширені налаштування конфіденційності", + "privacy_settings": "Параметри конфіденційності", + "settings_can_be_changed_later": "Ці параметри можна змінити пізніше в налаштуваннях програми" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 83990cf2e..ae2acd73a 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -642,5 +642,8 @@ "choose_from_available_options": "从可用选项中选择:", "custom_redeem_amount": "自定义兑换金额", "add_custom_redemption": "添加自定义兑换", - "remaining": "剩余" + "remaining": "剩余", + "advanced_privacy_settings": "高级隐私设置", + "privacy_settings": "隐私设置", + "settings_can_be_changed_later": "稍后可以在应用设置中更改这些设置" } From 299df3c087ace7f188d204db8c1623222cbd2f20 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 5 Oct 2022 19:28:11 +0200 Subject: [PATCH 009/203] Separate node form to be more reusable Add node form to privacy settings --- lib/di.dart | 25 +-- lib/router.dart | 4 +- .../advanced_privacy_settings_page.dart | 91 ++--------- .../nodes/node_create_or_edit_page.dart | 94 +---------- lib/src/screens/nodes/widgets/node_form.dart | 151 ++++++++++++++++++ .../node_create_or_edit_view_model.dart | 13 +- 6 files changed, 191 insertions(+), 187 deletions(-) create mode 100644 lib/src/screens/nodes/widgets/node_form.dart diff --git a/lib/di.dart b/lib/di.dart index 8dfbfd788..b7f8ce949 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -343,7 +343,7 @@ Future setup( onAuthenticationFinished: onAuthFinished, closable: closable ?? false)); - getIt.registerFactory(() => + getIt.registerFactory(() => BalancePage(dashboardViewModel: getIt.get(), settingsStore: getIt.get())); getIt.registerFactory(() => DashboardPage( balancePage: getIt.get(), walletViewModel: getIt.get(), addressListViewModel: getIt.get())); @@ -478,8 +478,9 @@ Future setup( getIt.registerFactory(() => NodeListPage(getIt.get())); - getIt.registerFactory(() => - NodeCreateOrEditViewModel(_nodeSource, getIt.get().wallet)); + getIt.registerFactoryParam( + (WalletType type, _) => + NodeCreateOrEditViewModel(_nodeSource, type ?? getIt.get().wallet.type)); getIt.registerFactory( () => NodeCreateOrEditPage(getIt.get())); @@ -672,7 +673,7 @@ Future setup( getIt.registerFactoryParam( (String qrData, bool isLight) => FullscreenQRPage(qrData: qrData, isLight: isLight,)); - + getIt.registerFactory(() => IoniaApi()); getIt.registerFactory(() => AnyPayApi()); @@ -692,7 +693,7 @@ Future setup( getIt.registerFactoryParam((double amount, merchant) { return IoniaMerchPurchaseViewModel( - ioniaAnyPayService: getIt.get(), + ioniaAnyPayService: getIt.get(), amount: amount, ioniaMerchant: merchant, ); @@ -734,31 +735,31 @@ Future setup( ioniaService: getIt.get(), giftCard: giftCard); }); - + getIt.registerFactoryParam((List args, _) { final amount = args[0] as double; final merchant = args[1] as IoniaMerchant; final tip = args[2] as IoniaTip; - + return IoniaCustomTipViewModel(amount: amount, tip: tip, ioniaMerchant: merchant); }); - + getIt.registerFactoryParam((IoniaGiftCard giftCard, _) { return IoniaGiftCardDetailPage(getIt.get(param1: giftCard)); }); getIt.registerFactoryParam((List args, _){ final giftCard = args.first as IoniaGiftCard; - - return IoniaMoreOptionsPage(giftCard); + + return IoniaMoreOptionsPage(giftCard); }); getIt.registerFactoryParam((IoniaGiftCard giftCard, _) => IoniaCustomRedeemViewModel(giftCard)); getIt.registerFactoryParam((List args, _){ final giftCard = args.first as IoniaGiftCard; - - return IoniaCustomRedeemPage(getIt.get(param1: giftCard) ); + + return IoniaCustomRedeemPage(getIt.get(param1: giftCard) ); }); diff --git a/lib/router.dart b/lib/router.dart index b19fb198e..fd820b764 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -20,6 +20,7 @@ import 'package:cake_wallet/src/screens/support/support_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; +import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cake_wallet/view_model/privacy_settings_view_model.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -476,9 +477,10 @@ Route createRoute(RouteSettings settings) { case Routes.privacySettings: final type = settings.arguments as WalletType; final privacySettingsViewModel = getIt.get(param1: type); + final nodeCreateViewModel = getIt.get(param1: type); return CupertinoPageRoute( - builder: (_) => AdvancedPrivacySettingsPage(privacySettingsViewModel)); + builder: (_) => AdvancedPrivacySettingsPage(privacySettingsViewModel, nodeCreateViewModel)); default: return MaterialPageRoute( diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index 149b65d2e..e22afeb92 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -1,49 +1,50 @@ -import 'package:cake_wallet/entities/generate_name.dart'; +import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cake_wallet/view_model/privacy_settings_view_model.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/core/wallet_name_validator.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; class AdvancedPrivacySettingsPage extends BasePage { - AdvancedPrivacySettingsPage(this.privacySettingsViewModel); + AdvancedPrivacySettingsPage(this.privacySettingsViewModel, this.nodeViewModel); final PrivacySettingsViewModel privacySettingsViewModel; + final NodeCreateOrEditViewModel nodeViewModel; @override String get title => S.current.privacy_settings; @override Widget body(BuildContext context) => - AdvancedPrivacySettingsBody(privacySettingsViewModel); + AdvancedPrivacySettingsBody(privacySettingsViewModel, nodeViewModel); } class AdvancedPrivacySettingsBody extends StatefulWidget { - const AdvancedPrivacySettingsBody(this.privacySettingsViewModel, {Key key}) + const AdvancedPrivacySettingsBody(this.privacySettingsViewModel, this.nodeViewModel, {Key key}) : super(key: key); final PrivacySettingsViewModel privacySettingsViewModel; + final NodeCreateOrEditViewModel nodeViewModel; @override _AdvancedPrivacySettingsBodyState createState() => - _AdvancedPrivacySettingsBodyState(privacySettingsViewModel); + _AdvancedPrivacySettingsBodyState(privacySettingsViewModel, nodeViewModel); } class _AdvancedPrivacySettingsBodyState extends State { - _AdvancedPrivacySettingsBodyState(this.privacySettingsViewModel); + _AdvancedPrivacySettingsBodyState(this.privacySettingsViewModel, this.nodeViewModel); final PrivacySettingsViewModel privacySettingsViewModel; + final NodeCreateOrEditViewModel nodeViewModel; final _formKey = GlobalKey(); - final TextEditingController _controller = TextEditingController(); - @override Widget build(BuildContext context) { return Container( @@ -67,75 +68,9 @@ class _AdvancedPrivacySettingsBodyState if (privacySettingsViewModel.addCustomNode) { return Padding( padding: EdgeInsets.only(top: 24), - child: Form( - key: _formKey, - child: TextFormField( - onChanged: (value) {}, - controller: _controller, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 20.0, - fontWeight: FontWeight.w600, - color: - Theme.of(context).primaryTextTheme.title.color), - decoration: InputDecoration( - hintStyle: TextStyle( - fontSize: 18.0, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme - .display3 - .color), - hintText: S.of(context).wallet_name, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context) - .accentTextTheme - .display3 - .decorationColor, - width: 1.0), - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context) - .accentTextTheme - .display3 - .decorationColor, - width: 1.0), - ), - suffixIcon: IconButton( - onPressed: () async { - final rName = await generateName(); - FocusManager.instance.primaryFocus?.unfocus(); - - setState(() { - _controller.text = rName; - _controller.selection = - TextSelection.fromPosition( - TextPosition(offset: _controller.text.length), - ); - }); - }, - icon: Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(6.0), - color: Theme.of(context).hintColor, - ), - width: 34, - height: 34, - child: Image.asset( - 'assets/images/refresh_icon.png', - color: Theme.of(context) - .primaryTextTheme - .display1 - .decorationColor, - ), - ), - ), - ), - validator: WalletNameValidator(), - ), + child: NodeForm( + formKey: _formKey, + nodeViewModel: nodeViewModel, ), ); } diff --git a/lib/src/screens/nodes/node_create_or_edit_page.dart b/lib/src/screens/nodes/node_create_or_edit_page.dart index 857bde023..e4864cc91 100644 --- a/lib/src/screens/nodes/node_create_or_edit_page.dart +++ b/lib/src/screens/nodes/node_create_or_edit_page.dart @@ -1,16 +1,13 @@ import 'package:cake_wallet/core/execution_state.dart'; +import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/core/node_address_validator.dart'; -import 'package:cake_wallet/core/node_port_validator.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; -import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; @@ -108,91 +105,10 @@ class NodeCreateOrEditPage extends BasePage { padding: EdgeInsets.only(left: 24, right: 24), child: ScrollableWithBottomSection( contentPadding: EdgeInsets.only(bottom: 24.0), - content: Form( - key: _formKey, - child: Column( - children: [ - Row( - children: [ - Expanded( - child: BaseTextFormField( - controller: _addressController, - hintText: S.of(context).node_address, - validator: NodeAddressValidator(), - ) - ) - ], - ), - SizedBox(height: 10.0), - Row( - children: [ - Expanded( - child: BaseTextFormField( - controller: _portController, - hintText: S.of(context).node_port, - keyboardType: TextInputType.numberWithOptions( - signed: false, decimal: false), - validator: NodePortValidator(), - ) - ) - ], - ), - SizedBox(height: 10.0), - if (nodeCreateOrEditViewModel.hasAuthCredentials) ...[ - Row( - children: [ - Expanded( - child: BaseTextFormField( - controller: _loginController, - hintText: S.of(context).login, - ) - ) - ], - ), - SizedBox(height: 10.0), - Row( - children: [ - Expanded( - child: BaseTextFormField( - controller: _passwordController, - hintText: S.of(context).password, - ) - ) - ], - ), - Padding( - padding: EdgeInsets.only(top: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Observer( - builder: (_) => StandardCheckbox( - value: nodeCreateOrEditViewModel.useSSL, - onChanged: (value) => - nodeCreateOrEditViewModel.useSSL = value, - caption: S.of(context).use_ssl, - )) - ], - )), - Padding( - padding: EdgeInsets.only(top: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Observer( - builder: (_) => StandardCheckbox( - value: nodeCreateOrEditViewModel.trusted, - onChanged: (value) => - nodeCreateOrEditViewModel.trusted = value, - caption: S.of(context).trusted, - )) - ], - )), - ] - ], - )), + content: NodeForm( + formKey: _formKey, + nodeViewModel: nodeCreateOrEditViewModel, + ), bottomSectionPadding: EdgeInsets.only(bottom: 24), bottomSection: Observer( builder: (_) => Row( diff --git a/lib/src/screens/nodes/widgets/node_form.dart b/lib/src/screens/nodes/widgets/node_form.dart new file mode 100644 index 000000000..757032a2a --- /dev/null +++ b/lib/src/screens/nodes/widgets/node_form.dart @@ -0,0 +1,151 @@ +import 'package:cake_wallet/core/node_address_validator.dart'; +import 'package:cake_wallet/core/node_port_validator.dart'; +import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; +import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:mobx/mobx.dart'; + +class NodeForm extends StatelessWidget { + NodeForm({ + @required this.nodeViewModel, + @required this.formKey, + }) : _addressController = TextEditingController(), + _portController = TextEditingController(), + _loginController = TextEditingController(), + _passwordController = TextEditingController() { + reaction((_) => nodeViewModel.address, (String address) { + if (address != _addressController.text) { + _addressController.text = address; + } + }); + + reaction((_) => nodeViewModel.port, (String port) { + if (port != _portController.text) { + _portController.text = port; + } + }); + + if (nodeViewModel.hasAuthCredentials) { + reaction((_) => nodeViewModel.login, (String login) { + if (login != _loginController.text) { + _loginController.text = login; + } + }); + + reaction((_) => nodeViewModel.password, (String password) { + if (password != _passwordController.text) { + _passwordController.text = password; + } + }); + } + + _addressController + .addListener(() => nodeViewModel.address = _addressController.text); + _portController + .addListener(() => nodeViewModel.port = _portController.text); + _loginController + .addListener(() => nodeViewModel.login = _loginController.text); + _passwordController + .addListener(() => nodeViewModel.password = _passwordController.text); + } + + final NodeCreateOrEditViewModel nodeViewModel; + final GlobalKey formKey; + + final TextEditingController _addressController; + final TextEditingController _portController; + final TextEditingController _loginController; + final TextEditingController _passwordController; + + @override + Widget build(BuildContext context) { + return Form( + key: formKey, + child: Column( + children: [ + Row( + children: [ + Expanded( + child: BaseTextFormField( + controller: _addressController, + hintText: S.of(context).node_address, + validator: NodeAddressValidator(), + ), + ) + ], + ), + SizedBox(height: 10.0), + Row( + children: [ + Expanded( + child: BaseTextFormField( + controller: _portController, + hintText: S.of(context).node_port, + keyboardType: TextInputType.numberWithOptions( + signed: false, decimal: false), + validator: NodePortValidator(), + )) + ], + ), + SizedBox(height: 10.0), + if (nodeViewModel.hasAuthCredentials) ...[ + Row( + children: [ + Expanded( + child: BaseTextFormField( + controller: _loginController, + hintText: S.of(context).login, + )) + ], + ), + SizedBox(height: 10.0), + Row( + children: [ + Expanded( + child: BaseTextFormField( + controller: _passwordController, + hintText: S.of(context).password, + )) + ], + ), + Padding( + padding: EdgeInsets.only(top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Observer( + builder: (_) => StandardCheckbox( + value: nodeViewModel.useSSL, + onChanged: (value) => nodeViewModel.useSSL = value, + caption: S.of(context).use_ssl, + ), + ) + ], + ), + ), + Padding( + padding: EdgeInsets.only(top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Observer( + builder: (_) => StandardCheckbox( + value: nodeViewModel.trusted, + onChanged: (value) => nodeViewModel.trusted = value, + caption: S.of(context).trusted, + ), + ), + ], + ), + ), + ] + ], + ), + ); + } +} diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index c14bdda5e..be6e3e316 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -1,7 +1,6 @@ import 'package:cake_wallet/core/execution_state.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; -import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/node.dart'; import 'package:cw_core/wallet_type.dart'; @@ -11,7 +10,7 @@ class NodeCreateOrEditViewModel = NodeCreateOrEditViewModelBase with _$NodeCreateOrEditViewModel; abstract class NodeCreateOrEditViewModelBase with Store { - NodeCreateOrEditViewModelBase(this._nodeSource, this._wallet) + NodeCreateOrEditViewModelBase(this._nodeSource, this._walletType) : state = InitialExecutionState(), connectionState = InitialExecutionState(), useSSL = false, @@ -45,8 +44,8 @@ abstract class NodeCreateOrEditViewModelBase with Store { bool get isReady => (address?.isNotEmpty ?? false) && (port?.isNotEmpty ?? false); - bool get hasAuthCredentials => _wallet.type == WalletType.monero || - _wallet.type == WalletType.haven; + bool get hasAuthCredentials => _walletType == WalletType.monero || + _walletType == WalletType.haven; String get uri { var uri = address; @@ -58,7 +57,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { return uri; } - final WalletBase _wallet; + final WalletType _walletType; final Box _nodeSource; @action @@ -76,7 +75,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { try { state = IsExecutingState(); final node = - Node(uri: uri, type: _wallet.type, login: login, password: password, + Node(uri: uri, type: _walletType, login: login, password: password, useSSL: useSSL, trusted: trusted); await _nodeSource.add(node); state = ExecutedSuccessfullyState(); @@ -90,7 +89,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { try { connectionState = IsExecutingState(); final node = - Node(uri: uri, type: _wallet.type, login: login, password: password); + Node(uri: uri, type: _walletType, login: login, password: password); final isAlive = await node.requestNode(); connectionState = ExecutedSuccessfullyState(payload: isAlive); } catch (e) { From 3c04bd9aa5899f3e626876af28adc4c270ab6546 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 5 Oct 2022 20:07:16 +0200 Subject: [PATCH 010/203] Pass wallet type when navigating Fix UI padding --- .../screens/new_wallet/advanced_privacy_settings_page.dart | 4 ++-- lib/src/screens/new_wallet/new_wallet_page.dart | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index e22afeb92..cb3e4e8dc 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -50,7 +50,7 @@ class _AdvancedPrivacySettingsBodyState return Container( padding: EdgeInsets.only(top: 24), child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), + contentPadding: EdgeInsets.only(bottom: 24), content: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -67,7 +67,7 @@ class _AdvancedPrivacySettingsBodyState builder: (_) { if (privacySettingsViewModel.addCustomNode) { return Padding( - padding: EdgeInsets.only(top: 24), + padding: EdgeInsets.only(left: 24, right: 24, top: 24), child: NodeForm( formKey: _formKey, nodeViewModel: nodeViewModel, diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 8aef74445..6bbd9e72d 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -216,7 +216,8 @@ class _WalletNameFormState extends State { const SizedBox(height: 25), GestureDetector( onTap: () { - Navigator.of(context).pushNamed(Routes.privacySettings); + Navigator.of(context) + .pushNamed(Routes.privacySettings, arguments: _walletNewVM.type); }, child: Text(S.of(context).advanced_privacy_settings), ), From cb9f69074563e0e81199413f54ab9f279dc16033 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 7 Oct 2022 15:25:20 +0200 Subject: [PATCH 011/203] Add Native setTrustedDaemon and trustedDaemon functions and integrate them with their wallets --- cw_haven/ios/Classes/haven_api.cpp | 10 ++++++++++ cw_haven/lib/api/signatures.dart | 6 +++++- cw_haven/lib/api/types.dart | 6 +++++- cw_haven/lib/api/wallet.dart | 12 ++++++++++++ cw_haven/lib/haven_wallet.dart | 4 ++++ cw_monero/ios/Classes/monero_api.cpp | 10 ++++++++++ cw_monero/ios/Classes/monero_api.h | 3 +++ cw_monero/lib/api/signatures.dart | 6 +++++- cw_monero/lib/api/types.dart | 6 +++++- cw_monero/lib/api/wallet.dart | 14 +++++++++++++- cw_monero/lib/monero_wallet.dart | 4 ++++ .../node_list/node_create_or_edit_view_model.dart | 7 +++++++ 12 files changed, 83 insertions(+), 5 deletions(-) diff --git a/cw_haven/ios/Classes/haven_api.cpp b/cw_haven/ios/Classes/haven_api.cpp index c1013bf87..aecaf0016 100644 --- a/cw_haven/ios/Classes/haven_api.cpp +++ b/cw_haven/ios/Classes/haven_api.cpp @@ -927,6 +927,16 @@ extern "C" return static_cast(rates.size()); } + void set_trusted_daemon(bool arg) + { + m_wallet->setTrustedDaemon(arg); + } + + bool trusted_daemon() + { + return m_wallet->trustedDaemon(); + } + #ifdef __cplusplus } #endif diff --git a/cw_haven/lib/api/signatures.dart b/cw_haven/lib/api/signatures.dart index 9dd1c8dac..c98926c51 100644 --- a/cw_haven/lib/api/signatures.dart +++ b/cw_haven/lib/api/signatures.dart @@ -137,4 +137,8 @@ typedef get_rate = Pointer Function(); typedef size_of_rate = Int32 Function(); -typedef update_rate = Void Function(); \ No newline at end of file +typedef update_rate = Void Function(); + +typedef set_trusted_daemon = Void Function(Int8 trusted); + +typedef trusted_daemon = Int8 Function(); \ No newline at end of file diff --git a/cw_haven/lib/api/types.dart b/cw_haven/lib/api/types.dart index 878297501..81661afc2 100644 --- a/cw_haven/lib/api/types.dart +++ b/cw_haven/lib/api/types.dart @@ -135,4 +135,8 @@ typedef GetRate = Pointer Function(); typedef SizeOfRate = int Function(); -typedef UpdateRate = void Function(); \ No newline at end of file +typedef UpdateRate = void Function(); + +typedef SetTrustedDaemon = void Function(int); + +typedef TrustedDaemon = int Function(); \ No newline at end of file diff --git a/cw_haven/lib/api/wallet.dart b/cw_haven/lib/api/wallet.dart index 3370fd3e0..96e6e80a6 100644 --- a/cw_haven/lib/api/wallet.dart +++ b/cw_haven/lib/api/wallet.dart @@ -116,6 +116,14 @@ final rescanBlockchainAsyncNative = havenApi .lookup>('rescan_blockchain') .asFunction(); +final setTrustedDaemonNative = havenApi + .lookup>('set_trusted_daemon') + .asFunction(); + +final trustedDaemonNative = havenApi + .lookup>('trusted_daemon') + .asFunction(); + int getSyncingHeight() => getSyncingHeightNative(); bool isNeededToRefresh() => isNeededToRefreshNative() != 0; @@ -346,3 +354,7 @@ Future isConnected() => compute(_isConnected, 0); Future getNodeHeight() => compute(_getNodeHeight, 0); void rescanBlockchainAsync() => rescanBlockchainAsyncNative(); + +Future setTrustedDaemon(bool trusted) async => setTrustedDaemonNative(_boolToInt(trusted)); + +Future trustedDaemon() async => trustedDaemonNative() != 0; diff --git a/cw_haven/lib/haven_wallet.dart b/cw_haven/lib/haven_wallet.dart index c107d2f52..4a08a183a 100644 --- a/cw_haven/lib/haven_wallet.dart +++ b/cw_haven/lib/haven_wallet.dart @@ -390,4 +390,8 @@ abstract class HavenWalletBase extends WalletBase haven_wallet.setTrustedDaemon(arg); + + Future trustedDaemon() async => haven_wallet.trustedDaemon(); } diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index 6bb251dcf..117214295 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -783,6 +783,16 @@ extern "C" return strdup(get_current_wallet()->getSubaddressLabel(accountIndex, addressIndex).c_str()); } + void set_trusted_daemon(bool arg) + { + m_wallet->setTrustedDaemon(arg); + } + + bool trusted_daemon() + { + return m_wallet->trustedDaemon(); + } + #ifdef __cplusplus } #endif diff --git a/cw_monero/ios/Classes/monero_api.h b/cw_monero/ios/Classes/monero_api.h index 3e2ebcff2..74258ba4c 100644 --- a/cw_monero/ios/Classes/monero_api.h +++ b/cw_monero/ios/Classes/monero_api.h @@ -30,6 +30,9 @@ void set_refresh_from_block_height(uint64_t height); void set_recovering_from_seed(bool is_recovery); void store(char *path); +void set_trusted_daemon(bool arg); +bool trusted_daemon(); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/cw_monero/lib/api/signatures.dart b/cw_monero/lib/api/signatures.dart index 16f983480..3de4fd1a5 100644 --- a/cw_monero/lib/api/signatures.dart +++ b/cw_monero/lib/api/signatures.dart @@ -125,4 +125,8 @@ typedef rescan_blockchain = Void Function(); typedef get_subaddress_label = Pointer Function( Int32 accountIndex, - Int32 addressIndex); \ No newline at end of file + Int32 addressIndex); + +typedef set_trusted_daemon = Void Function(Int8 trusted); + +typedef trusted_daemon = Int8 Function(); \ No newline at end of file diff --git a/cw_monero/lib/api/types.dart b/cw_monero/lib/api/types.dart index 3438b89fc..e328b776a 100644 --- a/cw_monero/lib/api/types.dart +++ b/cw_monero/lib/api/types.dart @@ -123,4 +123,8 @@ typedef RescanBlockchainAsync = void Function(); typedef GetSubaddressLabel = Pointer Function( int accountIndex, - int addressIndex); \ No newline at end of file + int addressIndex); + +typedef SetTrustedDaemon = void Function(int); + +typedef TrustedDaemon = int Function(); \ No newline at end of file diff --git a/cw_monero/lib/api/wallet.dart b/cw_monero/lib/api/wallet.dart index 9e84d7865..aeda971d8 100644 --- a/cw_monero/lib/api/wallet.dart +++ b/cw_monero/lib/api/wallet.dart @@ -120,6 +120,14 @@ final getSubaddressLabelNative = moneroApi .lookup>('get_subaddress_label') .asFunction(); +final setTrustedDaemonNative = moneroApi + .lookup>('set_trusted_daemon') + .asFunction(); + +final trustedDaemonNative = moneroApi + .lookup>('trusted_daemon') + .asFunction(); + int getSyncingHeight() => getSyncingHeightNative(); bool isNeededToRefresh() => isNeededToRefreshNative() != 0; @@ -353,4 +361,8 @@ void rescanBlockchainAsync() => rescanBlockchainAsyncNative(); String getSubaddressLabel(int accountIndex, int addressIndex) { return convertUTF8ToString(pointer: getSubaddressLabelNative(accountIndex, addressIndex)); -} \ No newline at end of file +} + +Future setTrustedDaemon(bool trusted) async => setTrustedDaemonNative(_boolToInt(trusted)); + +Future trustedDaemon() async => trustedDaemonNative() != 0; \ No newline at end of file diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 175bd96f5..772df420c 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -427,4 +427,8 @@ abstract class MoneroWalletBase extends WalletBase monero_wallet.setTrustedDaemon(arg); + + Future trustedDaemon() async => monero_wallet.trustedDaemon(); } diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index c14bdda5e..4b7e0ddc9 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -1,4 +1,6 @@ import 'package:cake_wallet/core/execution_state.dart'; +import 'package:cw_haven/haven_wallet.dart'; +import 'package:cw_monero/monero_wallet.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/wallet_base.dart'; @@ -78,6 +80,11 @@ abstract class NodeCreateOrEditViewModelBase with Store { final node = Node(uri: uri, type: _wallet.type, login: login, password: password, useSSL: useSSL, trusted: trusted); + if (_wallet.type == WalletType.monero) { + (_wallet as MoneroWallet).setTrustedDaemon(trusted); + } else if (_wallet.type == WalletType.haven) { + (_wallet as HavenWallet).setTrustedDaemon(trusted); + } await _nodeSource.add(node); state = ExecutedSuccessfullyState(); } catch (e) { From b0e188c0bd154ca9b95658a74d9369b0274bcc31 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 7 Oct 2022 20:06:33 +0200 Subject: [PATCH 012/203] Remove unused getter --- cw_core/lib/node.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index dd5969b99..dca429482 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -57,8 +57,6 @@ class Node extends HiveObject with Keyable { bool get isSSL => useSSL ?? false; - bool get isTrusted => trusted ?? false; - Uri get uri { switch (type) { case WalletType.monero: From 1eb9e65617e85ef2d70d7c324865c8cde8137565 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 20 Oct 2022 20:24:01 +0200 Subject: [PATCH 013/203] Set trusted daemon after node connection --- cw_haven/lib/haven_wallet.dart | 6 ++---- cw_monero/lib/monero_wallet.dart | 6 ++---- .../node_list/node_create_or_edit_view_model.dart | 7 ------- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/cw_haven/lib/haven_wallet.dart b/cw_haven/lib/haven_wallet.dart index 00d37ee08..14ff2f88e 100644 --- a/cw_haven/lib/haven_wallet.dart +++ b/cw_haven/lib/haven_wallet.dart @@ -121,6 +121,8 @@ abstract class HavenWalletBase extends WalletBase haven_wallet.setTrustedDaemon(arg); - - Future trustedDaemon() async => haven_wallet.trustedDaemon(); } diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index ff0104015..86a0358f0 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -136,6 +136,8 @@ abstract class MoneroWalletBase extends WalletBase monero_wallet.setTrustedDaemon(arg); - - Future trustedDaemon() async => monero_wallet.trustedDaemon(); } diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index 7b481f356..e24692059 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -1,6 +1,4 @@ import 'package:cake_wallet/core/execution_state.dart'; -import 'package:cw_haven/haven_wallet.dart'; -import 'package:cw_monero/monero_wallet.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/wallet_base.dart'; @@ -84,11 +82,6 @@ abstract class NodeCreateOrEditViewModelBase with Store { final node = Node(uri: uri, type: _wallet.type, login: login, password: password, useSSL: useSSL, trusted: trusted); - if (_wallet.type == WalletType.monero) { - (_wallet as MoneroWallet).setTrustedDaemon(trusted); - } else if (_wallet.type == WalletType.haven) { - (_wallet as HavenWallet).setTrustedDaemon(trusted); - } await _nodeSource.add(node); state = ExecutedSuccessfullyState(); } catch (e) { From a6d5a145b9a7edd5e112c16891232355430f7d0c Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 24 Oct 2022 14:47:39 +0300 Subject: [PATCH 014/203] flutter update fixes --- cw_core/lib/crypto_currency.dart | 364 +++++++++---------------------- 1 file changed, 106 insertions(+), 258 deletions(-) diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index c6e0c02c2..d348ebdd6 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -137,272 +137,120 @@ class CryptoCurrency extends EnumerableItem with Serializable { static const uni = CryptoCurrency(title: 'UNI', iconPath: 'assets/images/uni_icon.png', tag: 'ETH', raw: 61); static const stx = CryptoCurrency(title: 'STX', iconPath: 'assets/images/stx_icon.png', raw: 62); + static const mapFromInt = { + 0: CryptoCurrency.xmr, + 1: CryptoCurrency.ada, + 2: CryptoCurrency.bch, + 3: CryptoCurrency.bnb, + 4: CryptoCurrency.btc, + 5: CryptoCurrency.dai, + 6: CryptoCurrency.dash, + 7: CryptoCurrency.eos, + 8: CryptoCurrency.eth, + 9: CryptoCurrency.ltc, + 10: CryptoCurrency.nano, + 11: CryptoCurrency.trx, + 12: CryptoCurrency.usdt, + 13: CryptoCurrency.usdterc20, + 14: CryptoCurrency.xlm, + 15: CryptoCurrency.xrp, + 16: CryptoCurrency.xhv, + 17: CryptoCurrency.xag, + 18: CryptoCurrency.xau, + 19: CryptoCurrency.xaud, + 20: CryptoCurrency.xbtc, + 21: CryptoCurrency.xcad, + 22: CryptoCurrency.xchf, + 23: CryptoCurrency.xcny, + 24: CryptoCurrency.xeur, + 25: CryptoCurrency.xgbp, + 26: CryptoCurrency.xjpy, + 27: CryptoCurrency.xnok, + 28: CryptoCurrency.xnzd, + 29: CryptoCurrency.xusd, + 30: CryptoCurrency.ape, + 31: CryptoCurrency.avaxc, + 32: CryptoCurrency.btt, + 33: CryptoCurrency.bttbsc, + 34: CryptoCurrency.doge, + 35: CryptoCurrency.firo, + 36: CryptoCurrency.usdttrc20, + 37: CryptoCurrency.hbar, + 38: CryptoCurrency.sc, + 39: CryptoCurrency.sol, + 40: CryptoCurrency.usdc, + 41: CryptoCurrency.usdcsol, + 42: CryptoCurrency.zaddr, + 43: CryptoCurrency.zec, + 44: CryptoCurrency.zen, + 45: CryptoCurrency.xvg + }; + static const mapFromString = { + 'xmr': CryptoCurrency.xmr, + 'ada': CryptoCurrency.ada, + 'bch': CryptoCurrency.bch, + 'bnb': CryptoCurrency.bnb, + 'btc': CryptoCurrency.btc, + 'dai': CryptoCurrency.dai, + 'dash': CryptoCurrency.dash, + 'eos': CryptoCurrency.eos, + 'eth': CryptoCurrency.eth, + 'ltc': CryptoCurrency.ltc, + 'nano': CryptoCurrency.nano, + 'trx': CryptoCurrency.trx, + 'usdt': CryptoCurrency.usdt, + 'usdterc20': CryptoCurrency.usdterc20, + 'xlm': CryptoCurrency.xlm, + 'xrp': CryptoCurrency.xrp, + 'xhv': CryptoCurrency.xhv, + 'xag': CryptoCurrency.xag, + 'xau': CryptoCurrency.xau, + 'xaud': CryptoCurrency.xaud, + 'xbtc': CryptoCurrency.xbtc, + 'xcad': CryptoCurrency.xcad, + 'xchf': CryptoCurrency.xchf, + 'xcny': CryptoCurrency.xcny, + 'xeur': CryptoCurrency.xeur, + 'xgbp': CryptoCurrency.xgbp, + 'xjpy': CryptoCurrency.xjpy, + 'xnok': CryptoCurrency.xnok, + 'xnzd': CryptoCurrency.xnzd, + 'xusd': CryptoCurrency.xusd, + 'ape': CryptoCurrency.ape, + 'avaxc': CryptoCurrency.avaxc, + 'btt': CryptoCurrency.btt, + 'bttbsc': CryptoCurrency.bttbsc, + 'doge': CryptoCurrency.doge, + 'firo': CryptoCurrency.firo, + 'usdttrc20': CryptoCurrency.usdttrc20, + 'hbar': CryptoCurrency.hbar, + 'sc': CryptoCurrency.sc, + 'sol': CryptoCurrency.sol, + 'usdc': CryptoCurrency.usdc, + 'usdcsol': CryptoCurrency.usdcsol, + 'zaddr': CryptoCurrency.zaddr, + 'zec': CryptoCurrency.zec, + 'zen': CryptoCurrency.zen, + 'xvg': CryptoCurrency.xvg + }; static CryptoCurrency deserialize({required int raw}) { - switch (raw) { - case 0: - return CryptoCurrency.xmr; - case 1: - return CryptoCurrency.ada; - case 2: - return CryptoCurrency.bch; - case 3: - return CryptoCurrency.bnb; - case 4: - return CryptoCurrency.btc; - case 5: - return CryptoCurrency.dai; - case 6: - return CryptoCurrency.dash; - case 7: - return CryptoCurrency.eos; - case 8: - return CryptoCurrency.eth; - case 9: - return CryptoCurrency.ltc; - case 10: - return CryptoCurrency.nano; - case 11: - return CryptoCurrency.trx; - case 12: - return CryptoCurrency.usdt; - case 13: - return CryptoCurrency.usdterc20; - case 14: - return CryptoCurrency.xlm; - case 15: - return CryptoCurrency.xrp; - case 16: - return CryptoCurrency.xhv; - case 17: - return CryptoCurrency.xag; - case 18: - return CryptoCurrency.xau; - case 19: - return CryptoCurrency.xaud; - case 20: - return CryptoCurrency.xbtc; - case 21: - return CryptoCurrency.xcad; - case 22: - return CryptoCurrency.xchf; - case 23: - return CryptoCurrency.xcny; - case 24: - return CryptoCurrency.xeur; - case 25: - return CryptoCurrency.xgbp; - case 26: - return CryptoCurrency.xjpy; - case 27: - return CryptoCurrency.xnok; - case 28: - return CryptoCurrency.xnzd; - case 29: - return CryptoCurrency.xusd; - case 30: - return CryptoCurrency.ape; - case 31: - return CryptoCurrency.avaxc; - case 32: - return CryptoCurrency.btt; - case 33: - return CryptoCurrency.bttbsc; - case 34: - return CryptoCurrency.doge; - case 35: - return CryptoCurrency.firo; - case 36: - return CryptoCurrency.usdttrc20; - case 37: - return CryptoCurrency.hbar; - case 38: - return CryptoCurrency.sc; - case 39: - return CryptoCurrency.sol; - case 40: - return CryptoCurrency.usdc; - case 41: - return CryptoCurrency.usdcsol; - case 42: - return CryptoCurrency.zaddr; - case 43: - return CryptoCurrency.zec; - case 44: - return CryptoCurrency.zen; - case 45: - return CryptoCurrency.xvg; - case 46: - return CryptoCurrency.usdcpoly; - case 47: - return CryptoCurrency.dcr; - case 48: - return CryptoCurrency.husd; - case 49: - return CryptoCurrency.kmd; - case 50: - return CryptoCurrency.mana; - case 51: - return CryptoCurrency.maticpoly; - case 52: - return CryptoCurrency.matic; - case 53: - return CryptoCurrency.mkr; - case 54: - return CryptoCurrency.near; - case 55: - return CryptoCurrency.oxt; - case 56: - return CryptoCurrency.paxg; - case 57: - return CryptoCurrency.pivx; - case 58: - return CryptoCurrency.rune; - case 59: - return CryptoCurrency.rvn; - case 60: - return CryptoCurrency.scrt; - case 61: - return CryptoCurrency.uni; - case 62: - return CryptoCurrency.stx; - default: - throw Exception('Unexpected token: $raw for CryptoCurrency deserialize'); + + if (CryptoCurrency.mapFromInt[raw] == null) { + final s = 'Unexpected token: $raw for CryptoCurrency deserialize'; + throw ArgumentError.value(raw, 'raw', s); } + return CryptoCurrency.mapFromInt[raw]!; } static CryptoCurrency fromString(String raw) { - switch (raw.toLowerCase()) { - case 'xmr': - return CryptoCurrency.xmr; - case 'ada': - return CryptoCurrency.ada; - case 'bch': - return CryptoCurrency.bch; - case 'bnbmainnet': - return CryptoCurrency.bnb; - case 'btc': - return CryptoCurrency.btc; - case 'dai': - return CryptoCurrency.dai; - case 'dash': - return CryptoCurrency.dash; - case 'eos': - return CryptoCurrency.eos; - case 'eth': - return CryptoCurrency.eth; - case 'ltc': - return CryptoCurrency.ltc; - case 'nano': - return CryptoCurrency.nano; - case 'trx': - return CryptoCurrency.trx; - case 'usdc': - return CryptoCurrency.usdc; - case 'usdterc20': - return CryptoCurrency.usdterc20; - case 'xlm': - return CryptoCurrency.xlm; - case 'xrp': - return CryptoCurrency.xrp; - case 'xhv': - return CryptoCurrency.xhv; - case 'xag': - return CryptoCurrency.xag; - case 'xau': - return CryptoCurrency.xau; - case 'xaud': - return CryptoCurrency.xaud; - case 'xbtc': - return CryptoCurrency.xbtc; - case 'xcad': - return CryptoCurrency.xcad; - case 'xchf': - return CryptoCurrency.xchf; - case 'xcny': - return CryptoCurrency.xcny; - case 'xeur': - return CryptoCurrency.xeur; - case 'xgbp': - return CryptoCurrency.xgbp; - case 'xjpy': - return CryptoCurrency.xjpy; - case 'xnok': - return CryptoCurrency.xnok; - case 'xnzd': - return CryptoCurrency.xnzd; - case 'xusd': - return CryptoCurrency.xusd; - case 'ape': - return CryptoCurrency.ape; - case 'avax': - return CryptoCurrency.avaxc; - case 'btt': - return CryptoCurrency.btt; - case 'bttbsc': - return CryptoCurrency.bttbsc; - case 'doge': - return CryptoCurrency.doge; - case 'firo': - return CryptoCurrency.firo; - case 'usdttrc20': - return CryptoCurrency.usdttrc20; - case 'hbar': - return CryptoCurrency.hbar; - case 'sc': - return CryptoCurrency.sc; - case 'sol': - return CryptoCurrency.sol; - case 'usdt': - return CryptoCurrency.usdt; - case 'usdcsol': - return CryptoCurrency.usdcsol; - case 'zaddr': - return CryptoCurrency.zaddr; - case 'zec': - return CryptoCurrency.zec; - case 'zen': - return CryptoCurrency.zen; - case 'xvg': - return CryptoCurrency.xvg; - case 'usdcpoly': - return CryptoCurrency.usdcpoly; - case 'dcr': - return CryptoCurrency.dcr; - case 'husd': - return CryptoCurrency.husd; - case 'kmd': - return CryptoCurrency.kmd; - case 'mana': - return CryptoCurrency.mana; - case 'maticpoly': - return CryptoCurrency.maticpoly; - case 'matic': - return CryptoCurrency.matic; - case 'mkr': - return CryptoCurrency.mkr; - case 'near': - return CryptoCurrency.near; - case 'oxt': - return CryptoCurrency.oxt; - case 'paxg': - return CryptoCurrency.paxg; - case 'pivx': - return CryptoCurrency.pivx; - case 'rune': - return CryptoCurrency.rune; - case 'rvn': - return CryptoCurrency.rvn; - case 'scrt': - return CryptoCurrency.scrt; - case 'uni': - return CryptoCurrency.uni; - case 'stx': - return CryptoCurrency.stx; - default: - throw Exception('Unexpected token: $raw for CryptoCurrency fromString'); + + if (CryptoCurrency.mapFromString[raw.toLowerCase()] == null) { + final s = 'Unexpected token: $raw for CryptoCurrency fromString'; + throw ArgumentError.value(raw, 'raw', s); } + return CryptoCurrency.mapFromString[raw.toLowerCase()]!; } @override From afa16fbe1c33a07b1b5ff5a8095ffa1f591634d0 Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 24 Oct 2022 15:01:33 +0300 Subject: [PATCH 015/203] add new assets --- cw_core/lib/crypto_currency.dart | 38 ++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index d348ebdd6..446c667fd 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -183,7 +183,24 @@ class CryptoCurrency extends EnumerableItem with Serializable { 42: CryptoCurrency.zaddr, 43: CryptoCurrency.zec, 44: CryptoCurrency.zen, - 45: CryptoCurrency.xvg + 45: CryptoCurrency.xvg, + 46: CryptoCurrency.usdcpoly, + 47: CryptoCurrency.dcr, + 48: CryptoCurrency.husd, + 49: CryptoCurrency.kmd, + 50: CryptoCurrency.mana, + 51: CryptoCurrency.maticpoly, + 52: CryptoCurrency.matic, + 53: CryptoCurrency.mkr, + 54: CryptoCurrency.near, + 55: CryptoCurrency.oxt, + 56: CryptoCurrency.paxg, + 57: CryptoCurrency.pivx, + 58: CryptoCurrency.rune, + 59: CryptoCurrency.rvn, + 60: CryptoCurrency.scrt, + 61: CryptoCurrency.uni, + 62: CryptoCurrency.stx }; static const mapFromString = { @@ -232,7 +249,24 @@ class CryptoCurrency extends EnumerableItem with Serializable { 'zaddr': CryptoCurrency.zaddr, 'zec': CryptoCurrency.zec, 'zen': CryptoCurrency.zen, - 'xvg': CryptoCurrency.xvg + 'xvg': CryptoCurrency.xvg, + 'usdcpoly': CryptoCurrency.usdcpoly, + 'dcr': CryptoCurrency.dcr, + 'husd': CryptoCurrency.husd, + 'kmd': CryptoCurrency.kmd, + 'mana': CryptoCurrency.mana, + 'maticpoly': CryptoCurrency.maticpoly, + 'matic': CryptoCurrency.matic, + 'mkr': CryptoCurrency.mkr, + 'near': CryptoCurrency.near, + 'oxt': CryptoCurrency.oxt, + 'paxg': CryptoCurrency.paxg, + 'pivx': CryptoCurrency.pivx, + 'rune': CryptoCurrency.rune, + 'rvn': CryptoCurrency.rvn, + 'scrt': CryptoCurrency.scrt, + 'uni': CryptoCurrency.uni, + 'stx': CryptoCurrency.stx }; static CryptoCurrency deserialize({required int raw}) { From d4c7004a3cd7785d5f452cbc96089d7d0712cb4e Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 4 Nov 2022 13:58:04 +0200 Subject: [PATCH 016/203] add Disable fiat mode --- lib/entities/default_settings_migration.dart | 1 + lib/entities/preferences_key.dart | 1 + lib/reactions/fiat_rate_update.dart | 4 +++- .../dashboard/widgets/transactions_page.dart | 4 +++- .../exchange_trade/exchange_trade_page.dart | 11 +++++++--- lib/src/screens/send/send_page.dart | 14 ++++++------- lib/src/screens/send/widgets/send_card.dart | 6 ++++-- lib/src/screens/settings/settings.dart | 13 +++++++----- lib/store/settings_store.dart | 14 +++++++++++++ .../dashboard/balance_view_model.dart | 19 ++++++++++------- .../settings/settings_view_model.dart | 21 +++++++++++++++---- 11 files changed, 76 insertions(+), 32 deletions(-) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index b2036c3f6..ff8ffc2ed 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -61,6 +61,7 @@ Future defaultSettingsMigration( await sharedPreferences.setInt( PreferencesKey.currentBalanceDisplayModeKey, BalanceDisplayMode.availableBalance.raw); + await sharedPreferences.setBool('disable_fiat', false); await sharedPreferences.setBool('save_recipient_address', true); await resetToDefault(nodes); await changeMoneroCurrentNodeToDefault( diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 6cf7e5608..62c458fa0 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -9,6 +9,7 @@ class PreferencesKey { static const currentTransactionPriorityKeyLegacy = 'current_fee_priority'; static const currentBalanceDisplayModeKey = 'current_balance_display_mode'; static const shouldSaveRecipientAddressKey = 'save_recipient_address'; + static const shouldDisableFiatKey = 'disable_fiat'; static const allowBiometricalAuthenticationKey = 'allow_biometrical_authentication'; static const currentTheme = 'current_theme'; diff --git a/lib/reactions/fiat_rate_update.dart b/lib/reactions/fiat_rate_update.dart index 784a14e82..fb40a26e3 100644 --- a/lib/reactions/fiat_rate_update.dart +++ b/lib/reactions/fiat_rate_update.dart @@ -27,7 +27,9 @@ Future startFiatRateUpdate(AppStore appStore, SettingsStore settingsStore, if (appStore.wallet!.type == WalletType.haven) { await updateHavenRate(fiatConversionStore); } else { - fiatConversionStore.prices[appStore.wallet!.currency] = await FiatConversionService.fetchPrice( + fiatConversionStore.prices[appStore.wallet!.currency] = + settingsStore.shouldDisableFiat ? 0.0 + : await FiatConversionService.fetchPrice( appStore.wallet!.currency, settingsStore.fiatCurrency); } } catch(e) { diff --git a/lib/src/screens/dashboard/widgets/transactions_page.dart b/lib/src/screens/dashboard/widgets/transactions_page.dart index 8ab7c0efb..9e09bae8c 100644 --- a/lib/src/screens/dashboard/widgets/transactions_page.dart +++ b/lib/src/screens/dashboard/widgets/transactions_page.dart @@ -57,7 +57,9 @@ class TransactionsPage extends StatelessWidget { formattedDate: DateFormat('HH:mm') .format(transaction.date), formattedAmount: item.formattedCryptoAmount, - formattedFiatAmount: item.formattedFiatAmount, + formattedFiatAmount: + dashboardViewModel.balanceViewModel.disableFiat + ? '' : item.formattedFiatAmount, isPending: transaction.isPending)); } diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index aa3079197..4128fb9f2 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -74,9 +74,12 @@ class ExchangeTradePage extends BasePage { } class ExchangeTradeForm extends StatefulWidget { - ExchangeTradeForm(this.exchangeTradeViewModel); + ExchangeTradeForm(this.exchangeTradeViewModel) + : disableFiat = + exchangeTradeViewModel.sendViewModel.balanceViewModel.disableFiat; final ExchangeTradeViewModel exchangeTradeViewModel; + final bool disableFiat; @override ExchangeTradeState createState() => ExchangeTradeState(); @@ -378,9 +381,11 @@ class ExchangeTradeState extends State { }); }, actionLeftButton: () => Navigator.of(context).pop(), - feeFiatAmount: widget.exchangeTradeViewModel.sendViewModel.pendingTransactionFeeFiatAmount + feeFiatAmount: widget.disableFiat ? '' + : widget.exchangeTradeViewModel.sendViewModel.pendingTransactionFeeFiatAmount + ' ' + widget.exchangeTradeViewModel.sendViewModel.fiat.title, - fiatAmountValue: widget.exchangeTradeViewModel.sendViewModel + fiatAmountValue: widget.disableFiat ? '' + : widget.exchangeTradeViewModel.sendViewModel .pendingTransactionFiatAmount + ' ' + widget.exchangeTradeViewModel.sendViewModel.fiat.title, diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index e0cfff517..8815d8c58 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -386,16 +386,14 @@ class SendPage extends BasePage { amount: S.of(context).send_amount, amountValue: sendViewModel.pendingTransaction!.amountFormatted, - fiatAmountValue: - sendViewModel.pendingTransactionFiatAmount + - ' ' + - sendViewModel.fiat.title, + fiatAmountValue: sendViewModel.balanceViewModel.disableFiat + ? '' : sendViewModel.pendingTransactionFiatAmount + + ' ' + sendViewModel.fiat.title, fee: S.of(context).send_fee, feeValue: sendViewModel.pendingTransaction!.feeFormatted, - feeFiatAmount: - sendViewModel.pendingTransactionFeeFiatAmount + - ' ' + - sendViewModel.fiat.title, + feeFiatAmount: sendViewModel.balanceViewModel.disableFiat + ? '' : sendViewModel.pendingTransactionFeeFiatAmount + + ' ' + sendViewModel.fiat.title, outputs: sendViewModel.outputs, rightButtonText: S.of(context).ok, leftButtonText: S.of(context).cancel, diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index dc589923f..7e7194f88 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -332,6 +332,8 @@ class SendCardState extends State ], ), )), + sendViewModel.balanceViewModel.disableFiat ? + Container () : Padding( padding: const EdgeInsets.only(top: 20), child: BaseTextFormField( @@ -438,8 +440,8 @@ class SendCardState extends State Padding( padding: EdgeInsets.only(top: 5), - child: Text( - output + child: sendViewModel.balanceViewModel.disableFiat ? + Container () : Text(output .estimatedFeeFiatAmount + ' ' + sendViewModel diff --git a/lib/src/screens/settings/settings.dart b/lib/src/screens/settings/settings.dart index 3f6f41e7b..4a1f6bcb0 100644 --- a/lib/src/screens/settings/settings.dart +++ b/lib/src/screens/settings/settings.dart @@ -29,18 +29,20 @@ class SettingsPage extends BasePage { @override Widget body(BuildContext context) { // FIX-ME: Added `context` it was not used here before, maby bug ? - return SectionStandardList( + return Observer(builder: (_) { + final sections = settingsViewModel.getSections(); + return SectionStandardList( context: context, - sectionCount: settingsViewModel.sections.length, + sectionCount: sections.length, itemCounter: (int sectionIndex) { - if (sectionIndex < settingsViewModel.sections.length) { - return settingsViewModel.sections[sectionIndex].length; + if (sectionIndex < sections.length) { + return sections[sectionIndex].length; } return 0; }, itemBuilder: (_, sectionIndex, itemIndex) { - final item = settingsViewModel.sections[sectionIndex][itemIndex]; + final item = sections[sectionIndex][itemIndex]; if (item is PickerListItem) { return Observer(builder: (_) { @@ -94,5 +96,6 @@ class SettingsPage extends BasePage { return Container(); }); + }); } } diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 2b3105a34..5afd2c107 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -29,6 +29,7 @@ abstract class SettingsStoreBase with Store { required FiatCurrency initialFiatCurrency, required BalanceDisplayMode initialBalanceDisplayMode, required bool initialSaveRecipientAddress, + required bool initialDisableFiat, required bool initialAllowBiometricalAuthentication, required ThemeBase initialTheme, required int initialPinLength, @@ -46,6 +47,7 @@ abstract class SettingsStoreBase with Store { fiatCurrency = initialFiatCurrency, balanceDisplayMode = initialBalanceDisplayMode, shouldSaveRecipientAddress = initialSaveRecipientAddress, + shouldDisableFiat = initialDisableFiat, allowBiometricalAuthentication = initialAllowBiometricalAuthentication, currentTheme = initialTheme, pinCodeLength = initialPinLength, @@ -87,6 +89,12 @@ abstract class SettingsStoreBase with Store { PreferencesKey.shouldSaveRecipientAddressKey, shouldSaveRecipientAddress)); + reaction( + (_) => shouldDisableFiat, + (bool shouldDisableFiat) => sharedPreferences.setBool( + PreferencesKey.shouldDisableFiatKey, + shouldDisableFiat)); + reaction( (_) => currentTheme, (ThemeBase theme) => @@ -140,6 +148,9 @@ abstract class SettingsStoreBase with Store { @observable bool shouldSaveRecipientAddress; + @observable + bool shouldDisableFiat; + @observable bool allowBiometricalAuthentication; @@ -218,6 +229,8 @@ abstract class SettingsStoreBase with Store { // FIX-ME: Check for which default value we should have here final shouldSaveRecipientAddress = sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? false; + final shouldDisableFiat = + sharedPreferences.getBool(PreferencesKey.shouldDisableFiatKey) ?? false; final allowBiometricalAuthentication = sharedPreferences .getBool(PreferencesKey.allowBiometricalAuthenticationKey) ?? false; @@ -283,6 +296,7 @@ abstract class SettingsStoreBase with Store { initialFiatCurrency: currentFiatCurrency, initialBalanceDisplayMode: currentBalanceDisplayMode, initialSaveRecipientAddress: shouldSaveRecipientAddress, + initialDisableFiat: shouldDisableFiat, initialAllowBiometricalAuthentication: allowBiometricalAuthentication, initialTheme: savedTheme, actionlistDisplayMode: actionListDisplayMode, diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index 75d107b89..40502bb84 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -71,6 +71,9 @@ abstract class BalanceViewModelBase with Store { @computed BalanceDisplayMode get savedDisplayMode => settingsStore.balanceDisplayMode; + @computed + bool get disableFiat => settingsStore.shouldDisableFiat; + @computed String get asset { final typeFormatted = walletTypeToString(appStore.wallet!.type); @@ -180,8 +183,8 @@ abstract class BalanceViewModelBase with Store { return MapEntry(key, BalanceRecord( availableBalance: '---', additionalBalance: '---', - fiatAdditionalBalance: '---', - fiatAvailableBalance: '---', + fiatAdditionalBalance: disableFiat ? '' : '---', + fiatAvailableBalance: disableFiat ? '' : '---', asset: key, formattedAssetTitle: _formatterAsset(key))); } @@ -192,17 +195,17 @@ abstract class BalanceViewModelBase with Store { // throw Exception('Price is null for: $key'); // } - final additionalFiatBalance = fiatCurrency.toString() - + ' ' + final additionalFiatBalance = disableFiat ? '' : (fiatCurrency.toString() + + ' ' + _getFiatBalance( price: price, - cryptoAmount: value.formattedAdditionalBalance); + cryptoAmount: value.formattedAdditionalBalance)); - final availableFiatBalance = fiatCurrency.toString() - + ' ' + final availableFiatBalance = disableFiat ? '' : (fiatCurrency.toString() + + ' ' + _getFiatBalance( price: price, - cryptoAmount: value.formattedAvailableBalance); + cryptoAmount: value.formattedAvailableBalance)); return MapEntry(key, BalanceRecord( availableBalance: value.formattedAvailableBalance, diff --git a/lib/view_model/settings/settings_view_model.dart b/lib/view_model/settings/settings_view_model.dart index 96b2e7bdd..23ea0fded 100644 --- a/lib/view_model/settings/settings_view_model.dart +++ b/lib/view_model/settings/settings_view_model.dart @@ -61,7 +61,6 @@ abstract class SettingsViewModelBase with Store { : itemHeaders = {}, _walletType = wallet.type, _biometricAuth = BiometricAuth(), - sections = >[], currentVersion = '' { PackageInfo.fromPlatform().then( (PackageInfo packageInfo) => currentVersion = packageInfo.version); @@ -98,7 +97,7 @@ abstract class SettingsViewModelBase with Store { //} - sections = [ + getSections = () => [ [ SwitcherListItem( title: S.current.settings_display_balance, @@ -111,7 +110,7 @@ abstract class SettingsViewModelBase with Store { } }, ), - if (!isHaven) + if (!isHaven && !shouldDisableFiat) PickerListItem( title: S.current.settings_currency, searchHintText: S.current.search_currency, @@ -183,6 +182,11 @@ abstract class SettingsViewModelBase with Store { return LanguageService.list[code]?.toLowerCase().contains(searchText) ?? false; }, ), + SwitcherListItem( + title: 'S.current.disable_fiat', + value: () => shouldDisableFiat, + onValueChange: (_, bool value) => + setShouldDisableFiat(value)), SwitcherListItem( title: S.current.settings_allow_biometrical_authentication, value: () => allowBiometricalAuthentication, @@ -208,6 +212,7 @@ abstract class SettingsViewModelBase with Store { setAllowBiometricalAuthentication(value); } }), + ChoicesListItem( title: S.current.color_theme, items: ThemeList.all, @@ -275,6 +280,10 @@ abstract class SettingsViewModelBase with Store { bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress; + @computed + bool get shouldDisableFiat => + _settingsStore.shouldDisableFiat; + @computed bool get allowBiometricalAuthentication => _settingsStore.allowBiometricalAuthentication; @@ -285,7 +294,7 @@ abstract class SettingsViewModelBase with Store { bool get isBitcoinBuyEnabled => _settingsStore.isBitcoinBuyEnabled; final Map itemHeaders; - List> sections; + late List> Function() getSections; final SettingsStore _settingsStore; final YatStore _yatStore; final WalletType _walletType; @@ -303,6 +312,10 @@ abstract class SettingsViewModelBase with Store { void setShouldSaveRecipientAddress(bool value) => _settingsStore.shouldSaveRecipientAddress = value; + @action + void setShouldDisableFiat(bool value) => + _settingsStore.shouldDisableFiat = value; + @action void setAllowBiometricalAuthentication(bool value) => _settingsStore.allowBiometricalAuthentication = value; From b5e74874cef3a2f63105baca116d69e16b95e3ca Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 4 Nov 2022 14:11:06 +0200 Subject: [PATCH 017/203] update localization files --- res/values/strings_de.arb | 3 ++- res/values/strings_en.arb | 3 ++- res/values/strings_es.arb | 3 ++- res/values/strings_fr.arb | 3 ++- res/values/strings_hi.arb | 3 ++- res/values/strings_hr.arb | 3 ++- res/values/strings_it.arb | 3 ++- res/values/strings_ja.arb | 3 ++- res/values/strings_ko.arb | 3 ++- res/values/strings_nl.arb | 3 ++- res/values/strings_pl.arb | 3 ++- res/values/strings_pt.arb | 3 ++- res/values/strings_ru.arb | 3 ++- res/values/strings_uk.arb | 3 ++- res/values/strings_zh.arb | 3 ++- 15 files changed, 30 insertions(+), 15 deletions(-) diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index a580ab90a..e5d12d80b 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -651,5 +651,6 @@ "ignor": "Ignorieren", "use_suggested": "Vorgeschlagen verwenden", "do_not_share_warning_text" : "Teilen Sie diese nicht mit anderen, einschließlich des Supports.\n\nSie werden Ihr Geld stehlen!", - "help": "hilfe" + "help": "hilfe", + "disable_fiat": "Fiat deaktivieren" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 877d09231..aa995606f 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -651,5 +651,6 @@ "ignor": "Ignore", "use_suggested": "Use Suggested", "do_not_share_warning_text" : "Do not share these with anyone else, including support.\n\nThey will steal your money!", - "help": "help" + "help": "help", + "disable_fiat": "Disable fiat" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 505f3ffa8..843e7c9f9 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -651,5 +651,6 @@ "ignor": "Pasar por alto", "use_suggested": "Usar sugerido", "do_not_share_warning_text" : "No comparta estos con nadie más, incluido el soporte.\n\n¡Te robarán tu dinero!", - "help": "ayuda" + "help": "ayuda", + "disable_fiat": "Deshabilitar fiat" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 941016c0b..d4b36dc4d 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -649,5 +649,6 @@ "ignor": "Ignorer", "use_suggested": "Utilisation suggérée", "do_not_share_warning_text" : "Ne les partagez avec personne d'autre, y compris avec l'assistance.\n\nIls vont voler votre argent!", - "help": "aider" + "help": "aider", + "disable_fiat": "Désactiver fiat" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 7faa06f7f..a94bfb628 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -651,5 +651,6 @@ "ignor": "नज़रअंदाज़ करना", "use_suggested": "सुझाए गए का प्रयोग करें", "do_not_share_warning_text" : "इन्हें समर्थन सहित किसी और के साथ साझा न करें।\n\nवे आपका पैसा चुरा लेंगे!", - "help": "मदद करना" + "help": "मदद करना", + "disable_fiat": "िएट अक्षम करें" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 4fa77948a..dac4b5f23 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -651,5 +651,6 @@ "ignor": "Zanemariti", "use_suggested": "Koristite predloženo", "do_not_share_warning_text" : "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nUkrast će vam novac!", - "help": "pomozite" + "help": "pomozite", + "disable_fiat": "Isključi, fiat" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 9a42a588b..e14c4c7d4 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -651,5 +651,6 @@ "ignor": "Ignorare", "use_suggested": "Usa suggerito", "do_not_share_warning_text" : "Non condividerli con nessun altro, incluso il supporto.\n\nTi ruberanno i soldi!", - "help": "aiuto" + "help": "aiuto", + "disable_fiat": "Disabilita fiat" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index c1d0de4e3..62b12033a 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -651,5 +651,6 @@ "ignor": "無視", "use_suggested": "推奨を使用", "do_not_share_warning_text" : "サポートを含め、これらを他の誰とも共有しないでください。\n\n彼らはあなたのお金を盗みます!", - "help": "ヘルプ" + "help": "ヘルプ", + "disable_fiat": "フィアットを無効にする" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 127aa949e..35f0520d4 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -651,5 +651,6 @@ "ignor": "무시하다", "use_suggested": "추천 사용", "do_not_share_warning_text" : "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n그들은 당신의 돈을 훔칠 것입니다!", - "help": "돕다" + "help": "돕다", + "disable_fiat": "법정화폐 비활성화" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index bc53337a8..d8ced1592 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -651,5 +651,6 @@ "ignor": "Negeren", "use_suggested": "Gebruik aanbevolen", "do_not_share_warning_text" : "Deel deze met niemand anders, ook niet met support.\n\nZe zullen je geld stelen!", - "help": "helpen" + "help": "helpen", + "disable_fiat": "법정화폐 비활성화" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 454fe9717..59f7c227e 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -651,5 +651,6 @@ "ignor": "Ignorować", "use_suggested": "Użyj sugerowane", "do_not_share_warning_text" : "Nie udostępniaj ich nikomu innemu, w tym wsparcia.\n\nUkradną twoje pieniądze!", - "help": "pomoc" + "help": "pomoc", + "disable_fiat": "Wyłącz fiat" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 04a0a3ff2..defbf6ac1 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -651,5 +651,6 @@ "ignor": "Ignorar", "use_suggested": "Uso sugerido", "do_not_share_warning_text" : "Não os compartilhe com mais ninguém, incluindo suporte.\n\nEles vão roubar seu dinheiro!", - "help": "ajuda" + "help": "ajuda", + "disable_fiat": "Desativar fiat" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 632b0990c..9fa39b59b 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -651,5 +651,6 @@ "ignor": "Игнорировать", "use_suggested": "Использовать предложенный", "do_not_share_warning_text" : "Не делитесь ими с кем-либо еще, в том числе со службой поддержки.\n\nОни украдут ваши деньги!", - "help": "помощь" + "help": "помощь", + "disable_fiat": "Отключить фиат" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 5e0f0d18a..9e16d6696 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -650,5 +650,6 @@ "ignor": "Ігнорувати", "use_suggested": "Використати запропоноване", "do_not_share_warning_text" : "Не повідомляйте їх нікому, включно зі службою підтримки.\n\nВони вкрадуть ваші гроші!", - "help": "допомога" + "help": "допомога", + "disable_fiat": "Вимкнути фиат" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index c46d07d59..40ab71cad 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -649,5 +649,6 @@ "ignor": "忽视", "use_suggested": "使用建议", "do_not_share_warning_text" : "不要與其他任何人分享這些內容,包括支持。\n\n他們會偷你的錢!", - "help": "帮助" + "help": "帮助", + "disable_fiat": "禁用法令" } From c99e5f6f317ebbedd504c4068418a193acecbe34 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 4 Nov 2022 14:28:41 +0200 Subject: [PATCH 018/203] fix localization --- lib/view_model/settings/settings_view_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/view_model/settings/settings_view_model.dart b/lib/view_model/settings/settings_view_model.dart index 23ea0fded..4d0e9221a 100644 --- a/lib/view_model/settings/settings_view_model.dart +++ b/lib/view_model/settings/settings_view_model.dart @@ -183,7 +183,7 @@ abstract class SettingsViewModelBase with Store { }, ), SwitcherListItem( - title: 'S.current.disable_fiat', + title: S.current.disable_fiat, value: () => shouldDisableFiat, onValueChange: (_, bool value) => setShouldDisableFiat(value)), From 2cd748c151488a8378d1e28c25a98588ad163c6e Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 5 Nov 2022 20:05:55 +0200 Subject: [PATCH 019/203] filter contacts and wallets by type --- lib/di.dart | 9 ++++--- lib/router.dart | 8 ++++-- .../screens/contact/contact_list_page.dart | 25 +++++++++++-------- .../exchange/widgets/exchange_card.dart | 3 ++- lib/src/screens/send/widgets/send_card.dart | 1 + lib/src/widgets/address_text_field.dart | 7 ++++-- .../contact_list/contact_list_view_model.dart | 17 +++++++++++++ 7 files changed, 51 insertions(+), 19 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index 7ce2ff6d9..01d77b881 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -153,6 +153,7 @@ import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart'; import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart'; import 'package:cake_wallet/core/wallet_loading_service.dart'; +import 'package:cw_core/crypto_currency.dart'; final getIt = GetIt.instance; @@ -461,9 +462,11 @@ Future setup( getIt.registerFactory( () => ContactListViewModel(_contactSource, _walletInfoSource)); - getIt.registerFactoryParam( - (bool isEditable, _) => ContactListPage(getIt.get(), - isEditable: isEditable)); + getIt.registerFactoryParam((bool isEditable, CryptoCurrency? cur) + => ContactListPage( + getIt.get(), + isEditable: isEditable, + selectedCurrency: cur)); getIt.registerFactoryParam( (ContactRecord? contact, _) => diff --git a/lib/router.dart b/lib/router.dart index b255ce8b9..8b43fbaf5 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -74,6 +74,7 @@ import 'package:cake_wallet/src/screens/ionia/ionia.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart'; import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart'; import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; +import 'package:cw_core/crypto_currency.dart'; late RouteSettings currentRouteSettings; @@ -298,11 +299,14 @@ Route createRoute(RouteSettings settings) { case Routes.addressBook: return MaterialPageRoute( - builder: (_) => getIt.get(param1: true)); + builder: (_) => + getIt.get(param1: true, param2: null)); case Routes.pickerAddressBook: + final selectedCurrency = settings.arguments as CryptoCurrency; return MaterialPageRoute( - builder: (_) => getIt.get(param1: false)); + builder: (_) => getIt.get(param1: false, + param2: selectedCurrency)); case Routes.addressBookAddContact: return CupertinoPageRoute( diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 7912472d8..6d23518b8 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -16,10 +16,12 @@ import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart import 'package:cake_wallet/src/widgets/collapsible_standart_list.dart'; class ContactListPage extends BasePage { - ContactListPage(this.contactListViewModel, {this.isEditable = true}); + ContactListPage(this.contactListViewModel, + {this.isEditable = true, required this.selectedCurrency}); final ContactListViewModel contactListViewModel; final bool isEditable; + final CryptoCurrency? selectedCurrency; @override String get title => S.current.address_book; @@ -60,11 +62,13 @@ class ContactListPage extends BasePage { @override Widget body(BuildContext context) { + final contacts = + contactListViewModel.getContacts(isEditable, selectedCurrency); + final walletContacts = + contactListViewModel.getWallets(isEditable, selectedCurrency); return Container( padding: EdgeInsets.only(top: 20.0, bottom: 20.0), - child: Observer( - builder: (_) { - return CollapsibleSectionList( + child: CollapsibleSectionList( context: context, sectionCount: 2, themeColor: Theme.of(context).primaryTextTheme.headline6!.color!, @@ -82,15 +86,15 @@ class ContactListPage extends BasePage { child: Text(title, style: TextStyle(fontSize: 36))); }, itemCounter: (int sectionIndex) => sectionIndex == 0 - ? contactListViewModel.walletContacts.length - : contactListViewModel.contacts.length, + ? walletContacts.length + : contacts.length, itemBuilder: (_, sectionIndex, index) { if (sectionIndex == 0) { - final walletInfo = contactListViewModel.walletContacts[index]; + final walletInfo = walletContacts[index]; return generateRaw(context, walletInfo); } - final contact = contactListViewModel.contacts[index]; + final contact = contacts[index]; final content = generateRaw(context, contact); return !isEditable ? content @@ -100,9 +104,8 @@ class ContactListPage extends BasePage { child: content, ); }, - ); - }, - )); + ) + ); } Widget generateRaw(BuildContext context, ContactBase contact) { diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index 98843b1fb..40aa679a4 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -395,7 +395,8 @@ class ExchangeCardState extends State { buttonColor: widget.addressButtonsColor, validator: widget.addressTextFieldValidator, onPushPasteButton: widget.onPushPasteButton, - onPushAddressBookButton: widget.onPushAddressBookButton + onPushAddressBookButton: widget.onPushAddressBookButton, + selectedCurrency: _selectedCurrency ), ) diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index dc589923f..03e4471fe 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -155,6 +155,7 @@ class SendCardState extends State await output.fetchParsedAddress(context); }, validator: validator, + selectedCurrency: sendViewModel.currency, ); }), if (output.isParsedAddress) Padding( diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart index 35bf3ed85..7e0727312 100644 --- a/lib/src/widgets/address_text_field.dart +++ b/lib/src/widgets/address_text_field.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/entities/qr_scanner.dart'; import 'package:cake_wallet/entities/contact_base.dart'; +import 'package:cw_core/crypto_currency.dart'; enum AddressTextFieldOption { paste, qrCode, addressBook } @@ -26,7 +27,8 @@ class AddressTextField extends StatelessWidget { this.hintStyle, this.validator, this.onPushPasteButton, - this.onPushAddressBookButton}); + this.onPushAddressBookButton, + this.selectedCurrency}); static const prefixIconWidth = 34.0; static const prefixIconHeight = 34.0; @@ -47,6 +49,7 @@ class AddressTextField extends StatelessWidget { final FocusNode? focusNode; final Function(BuildContext context)? onPushPasteButton; final Function(BuildContext context)? onPushAddressBookButton; + final CryptoCurrency? selectedCurrency; @override Widget build(BuildContext context) { @@ -207,7 +210,7 @@ class AddressTextField extends StatelessWidget { Future _presetAddressBookPicker(BuildContext context) async { final contact = await Navigator.of(context, rootNavigator: true) - .pushNamed(Routes.pickerAddressBook); + .pushNamed(Routes.pickerAddressBook,arguments: selectedCurrency); if (contact is ContactBase && contact.address != null) { controller?.text = contact.address; diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart index ec145ad44..0f67245af 100644 --- a/lib/view_model/contact_list/contact_list_view_model.dart +++ b/lib/view_model/contact_list/contact_list_view_model.dart @@ -7,6 +7,7 @@ import 'package:mobx/mobx.dart'; import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/contact.dart'; import 'package:cake_wallet/utils/mobx.dart'; +import 'package:cw_core/crypto_currency.dart'; part 'contact_list_view_model.g.dart'; @@ -44,4 +45,20 @@ abstract class ContactListViewModelBase with Store { StreamSubscription? _subscription; Future delete(ContactRecord contact) async => contact.original.delete(); + + List getContacts(bool isEditable, CryptoCurrency? cur) { + if (!isEditable) { + return contacts.where((element) => element.type == cur).toList(); + } + + return contacts; + } + + List getWallets(bool isEditable, CryptoCurrency? cur) { + if (!isEditable) { + return walletContacts.where((element) => element.type == cur).toList(); + } + + return walletContacts; + } } From f078457c7b6eab9cb8977b777727e366e090f636 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 8 Nov 2022 16:56:27 +0200 Subject: [PATCH 020/203] Update Branch to null safety Add deep linking to iOS --- android/app/src/main/AndroidManifestBase.xml | 2 +- ios/Runner/InfoBase.plist | 54 +++++++++++++++----- lib/di.dart | 4 +- lib/main.dart | 29 +++++++---- lib/router.dart | 2 +- lib/src/screens/send/widgets/send_card.dart | 9 ++-- lib/utils/payment_request.dart | 6 +-- lib/view_model/send/send_view_model.dart | 4 +- 8 files changed, 74 insertions(+), 36 deletions(-) diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index f4023f532..8d94ba24f 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -38,7 +38,7 @@ android:scheme="cakewallet" android:host="y.at" /> - + diff --git a/ios/Runner/InfoBase.plist b/ios/Runner/InfoBase.plist index ad8816ca3..794391665 100644 --- a/ios/Runner/InfoBase.plist +++ b/ios/Runner/InfoBase.plist @@ -21,18 +21,48 @@ CFBundleSignature ???? CFBundleURLTypes - - - CFBundleTypeRole - Editor - CFBundleURLName - y.at - CFBundleURLSchemes - - cakewallet - - - + + + CFBundleTypeRole + Editor + CFBundleURLName + y.at + CFBundleURLSchemes + + cakewallet + + + + CFBundleTypeRole + Editor + CFBundleURLName + bitcoin + CFBundleURLSchemes + + bitcoin + + + + CFBundleTypeRole + Editor + CFBundleURLName + monero + CFBundleURLSchemes + + monero + + + + CFBundleTypeRole + Editor + CFBundleURLName + litecoin + CFBundleURLSchemes + + litecoin + + + CFBundleVersion $(CURRENT_PROJECT_VERSION) LSRequiresIPhoneOS diff --git a/lib/di.dart b/lib/di.dart index 9a554b25a..3481d783e 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -377,8 +377,8 @@ Future setup( getIt.get(), _transactionDescriptionBox)); - getIt.registerFactoryParam( - (PaymentRequest initialPaymentRequest, _) => SendPage( + getIt.registerFactoryParam( + (PaymentRequest? initialPaymentRequest, _) => SendPage( sendViewModel: getIt.get(), settingsViewModel: getIt.get(), initialPaymentRequest: initialPaymentRequest, diff --git a/lib/main.dart b/lib/main.dart index 7a3cc5ffe..8e971ec4b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -39,6 +39,8 @@ import 'package:cw_core/unspent_coins_info.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; +import 'src/screens/auth/auth_page.dart'; + final navigatorKey = GlobalKey(); final rootKey = GlobalKey(); @@ -213,15 +215,15 @@ class AppState extends State with SingleTickerProviderStateMixin { super.dispose(); } - /// handle app links while the app is already started - be it in - /// the foreground or in the background. + /// handle app links while the app is already started + /// whether its in the foreground or in the background. Future initUniLinks() async { try { - stream = getUriLinksStream().listen((Uri uri) { + stream = uriLinkStream.listen((Uri? uri) { handleDeepLinking(uri); }); - final Uri initialUri = await getInitialUri(); + final Uri? initialUri = await getInitialUri(); handleDeepLinking(initialUri); } catch (e) { @@ -229,14 +231,21 @@ class AppState extends State with SingleTickerProviderStateMixin { } } - void handleDeepLinking(Uri uri) { + void handleDeepLinking(Uri? uri) { if (uri == null || !mounted) return; - Navigator.pushNamed( - navigatorKey.currentContext, - Routes.send, - arguments: PaymentRequest.fromUri(uri), - ); + Navigator.of(navigatorKey.currentContext!).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { + if (isAuthenticatedSuccessfully) { + auth.close(route: Routes.send, arguments: PaymentRequest.fromUri(uri)); + } + }); + + // Navigator.pushNamed( + // navigatorKey.currentContext!, + // Routes.send, + // arguments: PaymentRequest.fromUri(uri), + // ); } Future _handleInitialUri() async { diff --git a/lib/router.dart b/lib/router.dart index 08c91db22..065e91a31 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -210,7 +210,7 @@ Route createRoute(RouteSettings settings) { builder: (_) => getIt.get()); case Routes.send: - final initialPaymentRequest = settings.arguments as PaymentRequest; + final initialPaymentRequest = settings.arguments as PaymentRequest?; return CupertinoPageRoute( fullscreenDialog: true, builder: (_) => getIt.get( diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index acc53e782..07b33843a 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -1,4 +1,3 @@ -import 'dart:ui'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cw_core/transaction_priority.dart'; @@ -44,7 +43,7 @@ class SendCardState extends State required this.output, required this.sendViewModel, this.initialPaymentRequest}) - : addressController = TextEditingController(text: initialPaymentRequest?.address?.toLowerCase()), + : addressController = TextEditingController(text: initialPaymentRequest?.address.toLowerCase()), cryptoAmountController = TextEditingController(text: initialPaymentRequest?.amount), fiatAmountController = TextEditingController(), noteController = TextEditingController(), @@ -77,8 +76,8 @@ class SendCardState extends State /// if the current wallet doesn't match the one in the qr code if (initialPaymentRequest != null && - sendViewModel.walletCurrencyName != initialPaymentRequest.scheme?.toLowerCase()) { - WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { + sendViewModel.walletCurrencyName != initialPaymentRequest!.scheme.toLowerCase()) { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { showPopUp( context: context, builder: (BuildContext context) { @@ -544,7 +543,7 @@ class SendCardState extends State addressController.text = output.address; } if (output.cryptoAmount.isNotEmpty || - sendViewModel.walletCurrencyName != initialPaymentRequest?.scheme?.toLowerCase()) { + sendViewModel.walletCurrencyName != initialPaymentRequest?.scheme.toLowerCase()) { cryptoAmountController.text = output.cryptoAmount; } fiatAmountController.text = output.fiatAmount; diff --git a/lib/utils/payment_request.dart b/lib/utils/payment_request.dart index 0a6306cd8..88730f037 100644 --- a/lib/utils/payment_request.dart +++ b/lib/utils/payment_request.dart @@ -1,7 +1,7 @@ class PaymentRequest { - PaymentRequest(this.address, this.amount, this.note, {this.scheme}); + PaymentRequest(this.address, this.amount, this.note, this.scheme); - factory PaymentRequest.fromUri(Uri uri) { + factory PaymentRequest.fromUri(Uri? uri) { var address = ""; var amount = ""; var note = ""; @@ -15,7 +15,7 @@ class PaymentRequest { scheme = uri.scheme; } - return PaymentRequest(address, amount, note, scheme: scheme); + return PaymentRequest(address, amount, note, scheme); } final String address; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index a17635a89..5632f8855 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -137,7 +137,7 @@ abstract class SendViewModelBase with Store { PendingTransaction? pendingTransaction; @computed - String get balance => balanceViewModel.availableBalance ?? '0.0'; + String get balance => balanceViewModel.availableBalance; @computed bool get isReadyForSend => _wallet.syncStatus is SyncedSyncStatus; @@ -164,7 +164,7 @@ abstract class SendViewModelBase with Store { WalletType get walletType => _wallet.type; - String get walletCurrencyName => _wallet.currency.name.toLowerCase(); + String? get walletCurrencyName => _wallet.currency.name?.toLowerCase(); bool get hasCurrecyChanger => walletType == WalletType.haven; From dfb52223e02ba2c727c8f2561ea6bf388535a349 Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 8 Nov 2022 17:49:51 +0200 Subject: [PATCH 021/203] fix increasing brightness brightness decreases after leaving "gift card barcode screen" --- lib/main.dart | 2 + .../cards/ionia_gift_card_detail_page.dart | 16 +++-- lib/utils/route_aware.dart | 65 +++++++++++++++++++ 3 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 lib/utils/route_aware.dart diff --git a/lib/main.dart b/lib/main.dart index 3cd5679b3..035552eb7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -40,6 +40,7 @@ import 'package:cake_wallet/wallet_type_utils.dart'; final navigatorKey = GlobalKey(); final rootKey = GlobalKey(); +final RouteObserver routeObserver = RouteObserver(); Future main() async { try { @@ -282,6 +283,7 @@ class AppState extends State with SingleTickerProviderStateMixin { authenticationStore: authenticationStore, navigatorKey: navigatorKey, child: MaterialApp( + navigatorObservers: [routeObserver], navigatorKey: navigatorKey, debugShowCheckedModeBanner: false, theme: settingsStore.theme, diff --git a/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart b/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart index 1c768fa17..d2ff358ee 100644 --- a/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart +++ b/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart @@ -11,6 +11,7 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/utils/route_aware.dart'; import 'package:cake_wallet/view_model/ionia/ionia_gift_card_details_view_model.dart'; import 'package:device_display_brightness/device_display_brightness.dart'; import 'package:flutter/material.dart'; @@ -47,10 +48,7 @@ class IoniaGiftCardDetailPage extends BasePage { //highlightColor: Colors.transparent, //splashColor: Colors.transparent, //padding: EdgeInsets.all(0), - onPressed: () { - onClose(context); - DeviceDisplayBrightness.setBrightness(viewModel.brightness); - }, + onPressed: ()=> onClose(context), child: _backButton), ), ), @@ -67,7 +65,6 @@ class IoniaGiftCardDetailPage extends BasePage { @override Widget body(BuildContext context) { - viewModel.increaseBrightness(); reaction((_) => viewModel.redeemState, (ExecutionState state) { if (state is FailureState) { WidgetsBinding.instance.addPostFrameCallback((_) { @@ -84,7 +81,12 @@ class IoniaGiftCardDetailPage extends BasePage { } }); - return ScrollableWithBottomSection( + return RouteAwareWidget( + pushToWidget: ()=> viewModel.increaseBrightness(), + pushToNextWidget: ()=> DeviceDisplayBrightness.setBrightness(viewModel.brightness), + popNextWidget: ()=> viewModel.increaseBrightness(), + popWidget: ()=> DeviceDisplayBrightness.setBrightness(viewModel.brightness), + child: ScrollableWithBottomSection( contentPadding: EdgeInsets.all(24), content: Column( children: [ @@ -163,7 +165,7 @@ class IoniaGiftCardDetailPage extends BasePage { }, ), ), - ); + )); } Widget buildIoniaTile(BuildContext context, {required String title, required String subTitle}) { diff --git a/lib/utils/route_aware.dart b/lib/utils/route_aware.dart new file mode 100644 index 000000000..28c72c4a4 --- /dev/null +++ b/lib/utils/route_aware.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; +import 'package:cake_wallet/main.dart'; + +class RouteAwareWidget extends StatefulWidget { + RouteAwareWidget( + {required this.child, + this.pushToWidget, + this.pushToNextWidget, + this.popWidget, + this.popNextWidget}); + + final Widget child; + final Function()? pushToWidget; + final Function()? pushToNextWidget; + final Function()? popWidget; + final Function()? popNextWidget; + + @override + State createState() => RouteAwareWidgetState(); +} + +class RouteAwareWidgetState extends State with RouteAware { + @override + void didChangeDependencies() { + super.didChangeDependencies(); + routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute); + } + + @override + void dispose() { + routeObserver.unsubscribe(this); + super.dispose(); + } + + @override + void didPush() { + if (widget.pushToWidget != null) { + widget.pushToWidget!(); + } + } + + @override + void didPushNext() { + if (widget.pushToNextWidget != null) { + widget.pushToNextWidget!(); + } + } + + @override + void didPop() { + if (widget.popWidget != null) { + widget.popWidget!(); + } + } + + @override + void didPopNext() { + if (widget.popNextWidget != null) { + widget.popNextWidget!(); + } + } + + @override + Widget build(BuildContext context) => widget.child; +} From f68798dd197b3a09ac3b23f59c45fef959785562 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 8 Nov 2022 18:12:01 +0200 Subject: [PATCH 022/203] Move handling deep links to app root --- lib/main.dart | 44 ---------------------------------- lib/src/screens/root/root.dart | 39 +++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 45 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8e971ec4b..6431d2f6e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,7 +5,6 @@ import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/ionia/ionia_category.dart'; import 'package:cake_wallet/ionia/ionia_merchant.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; -import 'package:cake_wallet/utils/payment_request.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -39,8 +38,6 @@ import 'package:cw_core/unspent_coins_info.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; -import 'src/screens/auth/auth_page.dart'; - final navigatorKey = GlobalKey(); final rootKey = GlobalKey(); @@ -205,47 +202,6 @@ class AppState extends State with SingleTickerProviderStateMixin { super.initState(); //_handleIncomingLinks(); //_handleInitialUri(); - - initUniLinks(); - } - - @override - void dispose() { - stream?.cancel(); - super.dispose(); - } - - /// handle app links while the app is already started - /// whether its in the foreground or in the background. - Future initUniLinks() async { - try { - stream = uriLinkStream.listen((Uri? uri) { - handleDeepLinking(uri); - }); - - final Uri? initialUri = await getInitialUri(); - - handleDeepLinking(initialUri); - } catch (e) { - print(e); - } - } - - void handleDeepLinking(Uri? uri) { - if (uri == null || !mounted) return; - - Navigator.of(navigatorKey.currentContext!).pushNamed(Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { - if (isAuthenticatedSuccessfully) { - auth.close(route: Routes.send, arguments: PaymentRequest.fromUri(uri)); - } - }); - - // Navigator.pushNamed( - // navigatorKey.currentContext!, - // Routes.send, - // arguments: PaymentRequest.fromUri(uri), - // ); } Future _handleInitialUri() async { diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index c507f6e1f..014dd0451 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -1,10 +1,12 @@ import 'dart:async'; +import 'package:cake_wallet/utils/payment_request.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/authentication_store.dart'; import 'package:cake_wallet/entities/qr_scanner.dart'; +import 'package:uni_links/uni_links.dart'; class Root extends StatefulWidget { Root( @@ -35,6 +37,9 @@ class RootState extends State with WidgetsBindingObserver { bool _isInactive; bool _postFrameCallback; + StreamSubscription? stream; + Uri? launchUri; + @override void initState() { _isInactiveController = StreamController.broadcast(); @@ -42,6 +47,34 @@ class RootState extends State with WidgetsBindingObserver { _postFrameCallback = false; WidgetsBinding.instance.addObserver(this); super.initState(); + + initUniLinks(); + } + + @override + void dispose() { + stream?.cancel(); + super.dispose(); + } + + /// handle app links while the app is already started + /// whether its in the foreground or in the background. + Future initUniLinks() async { + try { + stream = uriLinkStream.listen((Uri? uri) { + handleDeepLinking(uri); + }); + + handleDeepLinking(await getInitialUri()); + } catch (e) { + print(e); + } + } + + void handleDeepLinking(Uri? uri) { + if (uri == null || !mounted) return; + + launchUri = uri; } @override @@ -75,7 +108,11 @@ class RootState extends State with WidgetsBindingObserver { } _reset(); - auth.close(); + auth.close( + route: launchUri != null ? Routes.send : null, + arguments: PaymentRequest.fromUri(launchUri), + ); + launchUri = null; }); }); } From 7d92a964c7b8dc369249a9507790b4f30b538099 Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 9 Nov 2022 12:14:21 +0200 Subject: [PATCH 023/203] Change synchronization status text changed the status from "Starting sync" to "Attempting sync". --- cw_bitcoin/lib/electrum_wallet.dart | 2 +- cw_core/lib/sync_status.dart | 2 +- cw_haven/lib/haven_wallet.dart | 2 +- cw_monero/lib/monero_wallet.dart | 2 +- lib/core/sync_status_title.dart | 4 ++-- res/values/strings_de.arb | 1 + res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_zh.arb | 1 + 20 files changed, 21 insertions(+), 6 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 7abed8c07..fad546d90 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -129,7 +129,7 @@ abstract class ElectrumWalletBase extends WalletBase startSync() async { try { - syncStatus = StartingSyncStatus(); + syncStatus = AttemptingSyncStatus(); await walletAddresses.discoverAddresses(); await updateTransactions(); _subscribeForUpdates(); diff --git a/cw_core/lib/sync_status.dart b/cw_core/lib/sync_status.dart index fabec67c8..4983967d0 100644 --- a/cw_core/lib/sync_status.dart +++ b/cw_core/lib/sync_status.dart @@ -28,7 +28,7 @@ class NotConnectedSyncStatus extends SyncStatus { double progress() => 0.0; } -class StartingSyncStatus extends SyncStatus { +class AttemptingSyncStatus extends SyncStatus { @override double progress() => 0.0; } diff --git a/cw_haven/lib/haven_wallet.dart b/cw_haven/lib/haven_wallet.dart index 4f360bdff..cf7c9dcdd 100644 --- a/cw_haven/lib/haven_wallet.dart +++ b/cw_haven/lib/haven_wallet.dart @@ -135,7 +135,7 @@ abstract class HavenWalletBase extends WalletBase Date: Wed, 9 Nov 2022 17:53:50 +0200 Subject: [PATCH 024/203] Update branch to null safety Fix Conflicts with main --- cw_core/lib/node.dart | 6 ++---- lib/di.dart | 5 +++-- .../advanced_privacy_settings_page.dart | 7 +++---- lib/src/screens/nodes/widgets/node_form.dart | 4 ++-- .../node_create_or_edit_view_model.dart | 13 ++++++------- .../privacy_settings_view_model.dart | 18 +++++++++--------- 6 files changed, 25 insertions(+), 28 deletions(-) diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 28a54947c..5fce69a8e 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -17,7 +17,7 @@ class Node extends HiveObject with Keyable { {this.login, this.password, this.useSSL, - this.trusted, + this.trusted = false, String? uri, WalletType? type,}) { if (uri != null) { @@ -33,7 +33,7 @@ class Node extends HiveObject with Keyable { login = map['login'] as String?, password = map['password'] as String?, useSSL = map['useSSL'] as bool?, - useSSL = map['trusted'] as bool? ?? false; + trusted = map['trusted'] as bool? ?? false; static const typeId = 1; static const boxName = 'Nodes'; @@ -58,8 +58,6 @@ class Node extends HiveObject with Keyable { bool get isSSL => useSSL ?? false; - bool get isTrusted => trusted ?? false; - Uri get uri { switch (type) { case WalletType.monero: diff --git a/lib/di.dart b/lib/di.dart index 73421c989..7a3a8631c 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -478,8 +478,9 @@ Future setup( getIt.registerFactory(() => NodeListPage(getIt.get())); - getIt.registerFactory(() => - NodeCreateOrEditViewModel(_nodeSource, getIt.get().wallet!)); + getIt.registerFactoryParam( + (WalletType? type, _) => + NodeCreateOrEditViewModel(_nodeSource, type ?? getIt.get().wallet!.type)); getIt.registerFactory( () => NodeCreateOrEditPage(getIt.get())); diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index cb3e4e8dc..58adc9d99 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -4,7 +4,6 @@ import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model. import 'package:cake_wallet/view_model/privacy_settings_view_model.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/cupertino.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; @@ -25,7 +24,7 @@ class AdvancedPrivacySettingsPage extends BasePage { } class AdvancedPrivacySettingsBody extends StatefulWidget { - const AdvancedPrivacySettingsBody(this.privacySettingsViewModel, this.nodeViewModel, {Key key}) + const AdvancedPrivacySettingsBody(this.privacySettingsViewModel, this.nodeViewModel, {Key? key}) : super(key: key); final PrivacySettingsViewModel privacySettingsViewModel; @@ -85,7 +84,7 @@ class _AdvancedPrivacySettingsBodyState LoadingPrimaryButton( onPressed: () {}, text: S.of(context).continue_text, - color: Theme.of(context).accentTextTheme.body2.color, + color: Theme.of(context).accentTextTheme.bodyText1!.color!, textColor: Colors.white, ), const SizedBox(height: 25), @@ -96,7 +95,7 @@ class _AdvancedPrivacySettingsBodyState S.of(context).settings_can_be_changed_later, textAlign: TextAlign.center, style: TextStyle( - color: Theme.of(context).accentTextTheme.display3.color, + color: Theme.of(context).accentTextTheme.headline2?.color, ), ), ), diff --git a/lib/src/screens/nodes/widgets/node_form.dart b/lib/src/screens/nodes/widgets/node_form.dart index 757032a2a..52851e063 100644 --- a/lib/src/screens/nodes/widgets/node_form.dart +++ b/lib/src/screens/nodes/widgets/node_form.dart @@ -10,8 +10,8 @@ import 'package:mobx/mobx.dart'; class NodeForm extends StatelessWidget { NodeForm({ - @required this.nodeViewModel, - @required this.formKey, + required this.nodeViewModel, + required this.formKey, }) : _addressController = TextEditingController(), _portController = TextEditingController(), _loginController = TextEditingController(), diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index 7137cdd2c..34167ae0a 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -1,7 +1,6 @@ import 'package:cake_wallet/core/execution_state.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; -import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/node.dart'; import 'package:cw_core/wallet_type.dart'; @@ -11,7 +10,7 @@ class NodeCreateOrEditViewModel = NodeCreateOrEditViewModelBase with _$NodeCreateOrEditViewModel; abstract class NodeCreateOrEditViewModelBase with Store { - NodeCreateOrEditViewModelBase(this._nodeSource, this._wallet) + NodeCreateOrEditViewModelBase(this._nodeSource, this._walletType) : state = InitialExecutionState(), connectionState = InitialExecutionState(), useSSL = false, @@ -49,8 +48,8 @@ abstract class NodeCreateOrEditViewModelBase with Store { bool get isReady => address.isNotEmpty && port.isNotEmpty; - bool get hasAuthCredentials => _wallet.type == WalletType.monero || - _wallet.type == WalletType.haven; + bool get hasAuthCredentials => _walletType == WalletType.monero || + _walletType == WalletType.haven; String get uri { var uri = address; @@ -62,7 +61,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { return uri; } - final WalletBase _wallet; + final WalletType _walletType; final Box _nodeSource; @action @@ -80,7 +79,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { try { state = IsExecutingState(); final node = - Node(uri: uri, type: _wallet.type, login: login, password: password, + Node(uri: uri, type: _walletType, login: login, password: password, useSSL: useSSL, trusted: trusted); await _nodeSource.add(node); state = ExecutedSuccessfullyState(); @@ -94,7 +93,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { try { connectionState = IsExecutingState(); final node = - Node(uri: uri, type: _wallet.type, login: login, password: password); + Node(uri: uri, type: _walletType, login: login, password: password); final isAlive = await node.requestNode(); connectionState = ExecutedSuccessfullyState(payload: isAlive); } catch (e) { diff --git a/lib/view_model/privacy_settings_view_model.dart b/lib/view_model/privacy_settings_view_model.dart index ce5a3f7a6..760c577ef 100644 --- a/lib/view_model/privacy_settings_view_model.dart +++ b/lib/view_model/privacy_settings_view_model.dart @@ -9,13 +9,13 @@ class PrivacySettingsViewModel = PrivacySettingsViewModelBase with _$PrivacySettingsViewModel; abstract class PrivacySettingsViewModelBase with Store { - PrivacySettingsViewModelBase(this.type) { - _disableFiat = false; - _disableExchange = false; - _addCustomNode = false; - + PrivacySettingsViewModelBase(this.type) + : _disableFiat = false, + _disableExchange = false, + _addCustomNode = false { settings = [ SwitcherListItem( + // TODO: replace when Disable Fiat PR is merged title: "Disable Fiat API", // title: S.current.disable_fiat, value: () => _disableFiat, @@ -36,16 +36,16 @@ abstract class PrivacySettingsViewModelBase with Store { ]; } - List settings; + late List settings; @observable - bool _disableFiat; + bool _disableFiat = false; @observable - bool _disableExchange; + bool _disableExchange = false; @observable - bool _addCustomNode; + bool _addCustomNode = false; final WalletType type; From ec10732eda3296cd4878bd94b02e8df8f2f87c2c Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 9 Nov 2022 19:40:12 +0200 Subject: [PATCH 025/203] Save node on continue --- .../screens/new_wallet/advanced_privacy_settings_page.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index 58adc9d99..da67d4511 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -82,7 +82,9 @@ class _AdvancedPrivacySettingsBodyState bottomSection: Column( children: [ LoadingPrimaryButton( - onPressed: () {}, + onPressed: () { + nodeViewModel.save(); + }, text: S.of(context).continue_text, color: Theme.of(context).accentTextTheme.bodyText1!.color!, textColor: Colors.white, From 1f08d8747159a6455a637544714bf69bf9d9eb8b Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 10 Nov 2022 13:25:03 +0200 Subject: [PATCH 026/203] Rework filter on the transactions list screen --- .../exchange_provider_description.dart | 5 + .../dashboard/widgets/filter_tile.dart | 7 +- .../dashboard/widgets/filter_widget.dart | 231 ++++++++++-------- lib/src/widgets/rounded_checkbox.dart | 91 +++++++ lib/store/dashboard/trade_filter_store.dart | 82 ++++--- .../dashboard/transaction_filter_store.dart | 57 +++-- .../dashboard/dashboard_view_model.dart | 28 ++- lib/view_model/dashboard/filter_item.dart | 6 +- 8 files changed, 350 insertions(+), 157 deletions(-) create mode 100644 lib/src/widgets/rounded_checkbox.dart diff --git a/lib/exchange/exchange_provider_description.dart b/lib/exchange/exchange_provider_description.dart index f9e359454..2fd231085 100644 --- a/lib/exchange/exchange_provider_description.dart +++ b/lib/exchange/exchange_provider_description.dart @@ -24,6 +24,9 @@ class ExchangeProviderDescription extends EnumerableItem static const simpleSwap = ExchangeProviderDescription(title: 'SimpleSwap', raw: 4, image: 'assets/images/simpleSwap.png'); + static const all = + ExchangeProviderDescription(title: 'All trades', raw: 5, image:''); + static ExchangeProviderDescription deserialize({required int raw}) { switch (raw) { case 0: @@ -36,6 +39,8 @@ class ExchangeProviderDescription extends EnumerableItem return sideShift; case 4: return simpleSwap; + case 5: + return all; default: throw Exception('Unexpected token: $raw for ExchangeProviderDescription deserialize'); } diff --git a/lib/src/screens/dashboard/widgets/filter_tile.dart b/lib/src/screens/dashboard/widgets/filter_tile.dart index 9a5646ac9..3be96073a 100644 --- a/lib/src/screens/dashboard/widgets/filter_tile.dart +++ b/lib/src/screens/dashboard/widgets/filter_tile.dart @@ -9,12 +9,7 @@ class FilterTile extends StatelessWidget { Widget build(BuildContext context) { return Container( width: double.infinity, - padding: EdgeInsets.only( - top: 18, - bottom: 18, - left: 24, - right: 24 - ), + padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 24.0), child: child, ); } diff --git a/lib/src/screens/dashboard/widgets/filter_widget.dart b/lib/src/screens/dashboard/widgets/filter_widget.dart index 98d5add81..8719df562 100644 --- a/lib/src/screens/dashboard/widgets/filter_widget.dart +++ b/lib/src/screens/dashboard/widgets/filter_widget.dart @@ -6,20 +6,21 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/alert_background.dart'; import 'package:cake_wallet/src/widgets/alert_close_button.dart'; -import 'package:cake_wallet/src/widgets/checkbox_widget.dart'; +import 'package:cake_wallet/src/widgets/rounded_checkbox.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; //import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker; class FilterWidget extends StatelessWidget { FilterWidget({required this.dashboardViewModel}); final DashboardViewModel dashboardViewModel; - final backVector = Image.asset('assets/images/back_vector.png', - color: Palette.darkBlueCraiola - ); + final closeIcon = + Image.asset('assets/images/close.png', color: Palette.darkBlueCraiola); @override Widget build(BuildContext context) { + const sectionDivider = SectionDivider(); return AlertBackground( child: Stack( alignment: Alignment.center, @@ -38,118 +39,150 @@ class FilterWidget extends StatelessWidget { ), ), Padding( - padding: EdgeInsets.only( - left: 24, - right: 24, - top: 24 - ), + padding: EdgeInsets.only(left: 24, right: 24, top: 24), child: ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(14)), + borderRadius: BorderRadius.all(Radius.circular(24)), child: Container( - color: Theme.of(context).textTheme!.bodyText1!.decorationColor!, - child: ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: dashboardViewModel.filterItems.length, - separatorBuilder: (context, _) => Container( - height: 1, - color: Theme.of(context).accentTextTheme!.subtitle1!.backgroundColor!, - ), - itemBuilder: (_, index1) { - final title = dashboardViewModel.filterItems.keys.elementAt(index1); - final section = dashboardViewModel.filterItems.values.elementAt(index1); - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: EdgeInsets.only( - top: 20, - left: 24, - right: 24 - ), - child: Text( - title, - style: TextStyle( - color: Theme.of(context).accentTextTheme!.subtitle1!.color!, - fontSize: 16, - fontWeight: FontWeight.w500, - fontFamily: 'Lato', - decoration: TextDecoration.none - ), + color: Theme.of(context) + .textTheme! + .bodyText1! + .decorationColor!, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.all(24.0), + child: Text( + S.of(context).filters, + style: TextStyle( + color: Theme.of(context) + .textTheme! + .bodyText1! + .decorationColor!, + fontSize: 16, + fontFamily: 'Lato', + decoration: TextDecoration.none, ), ), - ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: section.length, - separatorBuilder: (context, _) => Container( - height: 1, - padding: EdgeInsets.only(left: 24), - color: Theme.of(context).textTheme!.bodyText1!.decorationColor!, - child: Container( - height: 1, - color: Theme.of(context).accentTextTheme!.subtitle1!.backgroundColor!, - ), - ), - itemBuilder: (_, index2) { - - final item = section[index2]; - final content = item.onChanged != null - ? CheckboxWidget( - value: item.value(), - caption: item.caption, - onChanged: item.onChanged - ) - : GestureDetector( - onTap: () async { - //final List picked = - //await date_rage_picker.showDatePicker( - // context: context, - // initialFirstDate: DateTime.now() - // .subtract(Duration(days: 1)), - // initialLastDate: (DateTime.now()), - // firstDate: DateTime(2015), - // lastDate: DateTime.now() - // .add(Duration(days: 1))); - - //if (picked != null && picked.length == 2) { - // dashboardViewModel.transactionFilterStore - // .changeStartDate(picked.first); - // dashboardViewModel.transactionFilterStore - // .changeEndDate(picked.last); - //} - }, - child: Padding( - padding: EdgeInsets.only(left: 32), + ), + sectionDivider, + ListView.separated( + padding: EdgeInsets.zero, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: dashboardViewModel.filterItems.length, + separatorBuilder: (context, _) => sectionDivider, + itemBuilder: (_, index1) { + final title = dashboardViewModel.filterItems.keys + .elementAt(index1); + final section = dashboardViewModel + .filterItems.values + .elementAt(index1); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only( + top: 20, left: 24, right: 24), child: Text( - item.caption, + title, style: TextStyle( - color: Theme.of(context).primaryTextTheme!.headline6!.color!, - fontSize: 18, + color: Theme.of(context) + .primaryTextTheme! + .headline6! + .color!, + fontSize: 16, fontFamily: 'Lato', - fontWeight: FontWeight.w500, - decoration: TextDecoration.none - ), + fontWeight: FontWeight.bold, + decoration: TextDecoration.none), ), ), - ); + ListView.builder( + padding: + EdgeInsets.symmetric(vertical: 8.0), + shrinkWrap: true, + physics: + const NeverScrollableScrollPhysics(), + itemCount: section.length, + itemBuilder: (_, index2) { + final item = section[index2]; + final content = item.onChanged != null + ? Observer( + builder: (_) => + RoundedCheckboxWidget( + value: item.value.value, + caption: item.caption, + onChanged: item.onChanged, + currentTheme: + dashboardViewModel + .settingsStore + .currentTheme, + )) + : GestureDetector( + onTap: () async { + //final List picked = + //await date_rage_picker.showDatePicker( + // context: context, + // initialFirstDate: DateTime.now() + // .subtract(Duration(days: 1)), + // initialLastDate: (DateTime.now()), + // firstDate: DateTime(2015), + // lastDate: DateTime.now() + // .add(Duration(days: 1))); - return FilterTile(child: content); - }, - ) - ], - ); - }, - ), + //if (picked != null && picked.length == 2) { + // dashboardViewModel.transactionFilterStore + // .changeStartDate(picked.first); + // dashboardViewModel.transactionFilterStore + // .changeEndDate(picked.last); + //} + }, + child: Padding( + padding: + EdgeInsets.only(left: 32), + child: Text( + item.caption, + style: TextStyle( + color: Colors.red, + //Theme.of(context).primaryTextTheme.title.color,// + fontSize: 18, + fontFamily: 'Lato', + fontWeight: + FontWeight.w500, + decoration: + TextDecoration.none), + ), + ), + ); + + return FilterTile(child: content); + }, + ) + ], + ); + }, + ), + ]), ), ), ), ], ), - AlertCloseButton(image: backVector) + AlertCloseButton(image: closeIcon) ], ), ); } +} + +class SectionDivider extends StatelessWidget { + const SectionDivider(); + + @override + Widget build(BuildContext context) { + return Container( + height: 1, + color: Colors.red,//Fixme Theme.of(context).accentTextTheme.subhead.backgroundColor, + ); + } } \ No newline at end of file diff --git a/lib/src/widgets/rounded_checkbox.dart b/lib/src/widgets/rounded_checkbox.dart new file mode 100644 index 000000000..6e5b08f1e --- /dev/null +++ b/lib/src/widgets/rounded_checkbox.dart @@ -0,0 +1,91 @@ +import 'package:cake_wallet/palette.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/theme_base.dart'; + +class RoundedCheckboxWidget extends StatelessWidget { + RoundedCheckboxWidget( + {required this.value, + required this.caption, + required this.onChanged, + this.currentTheme}); + + final bool value; + final String caption; + final Function onChanged; + final ThemeBase? currentTheme; + + bool get darkTheme => currentTheme!.type == ThemeType.dark; + + @override + Widget build(BuildContext context) { + + final baseGradient = LinearGradient(colors: [ + Colors.red, //Fixme Theme.of(context).primaryTextTheme!.subtitle!.color!, + Colors.red //Fixme Theme.of(context).primaryTextTheme!.subtitle!.decorationColor!, + ], begin: Alignment.centerLeft, end: Alignment.centerRight); + + final darkThemeGradient = LinearGradient(colors: [ + Palette.blueCraiola, + Palette.blueGreyCraiola, + ], begin: Alignment.topLeft, end: Alignment.bottomRight); + + final gradient = darkTheme ? darkThemeGradient : baseGradient; + + final uncheckedColor = darkTheme + ? Colors.red //Fixme Theme.of(context).accentTextTheme.subhead.decorationColor + : Colors.white; + + final borderColor = darkTheme + ? Colors.red //Fixme Theme.of(context).accentTextTheme.subtitle.backgroundColor + : Colors.transparent; + + final checkedOuterBoxDecoration = + BoxDecoration(shape: BoxShape.circle, gradient: gradient); + final outerBoxDecoration = BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context).accentTextTheme.overline!.color!, + border: Border.all(color: borderColor)); + + final checkedInnerBoxDecoration = + BoxDecoration(shape: BoxShape.circle, color: Colors.white); + final innerBoxDecoration = + BoxDecoration(shape: BoxShape.circle, color: uncheckedColor); + + return GestureDetector( + onTap: () => onChanged(), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + height: 24.0, + width: 24.0, + child: DecoratedBox( + decoration: + value ? checkedOuterBoxDecoration : outerBoxDecoration, + child: Padding( + padding: EdgeInsets.all(value ? 4.0 : 1.0), + child: DecoratedBox( + decoration: + value ? checkedInnerBoxDecoration : innerBoxDecoration, + ), + ), + ), + ), + Padding( + padding: EdgeInsets.only(left: 16), + child: Text( + caption, + style: TextStyle( + color: Colors.red, //Fixme Theme.of(context).primaryTextTheme.title.color, + fontSize: 18, + fontFamily: 'Lato', + fontWeight: FontWeight.w500, + decoration: TextDecoration.none), + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/store/dashboard/trade_filter_store.dart b/lib/store/dashboard/trade_filter_store.dart index bee63b21e..4319c3bc7 100644 --- a/lib/store/dashboard/trade_filter_store.dart +++ b/lib/store/dashboard/trade_filter_store.dart @@ -8,39 +8,61 @@ part'trade_filter_store.g.dart'; class TradeFilterStore = TradeFilterStoreBase with _$TradeFilterStore; abstract class TradeFilterStoreBase with Store { - TradeFilterStoreBase( - {this.displayXMRTO = true, - this.displayChangeNow = true, - this.displayMorphToken = true, - this.displaySimpleSwap = true, - }); + TradeFilterStoreBase(); - @observable - bool displayXMRTO; - - @observable - bool displayChangeNow; - - @observable - bool displayMorphToken; - - @observable - bool displaySimpleSwap; + Observable displayXMRTO = Observable(true); + Observable displayAllTrades = Observable(true); + Observable displayChangeNow = Observable(true); + Observable displaySideShift = Observable(true); + Observable displayMorphToken = Observable(true); + Observable displaySimpleSwap = Observable(true); @action void toggleDisplayExchange(ExchangeProviderDescription provider) { switch (provider) { case ExchangeProviderDescription.changeNow: - displayChangeNow = !displayChangeNow; + displayAllTrades.value = false; + displayChangeNow.value = !displayChangeNow.value; + if (displayChangeNow.value && displaySideShift.value && displaySimpleSwap.value) { + displayAllTrades.value = true; + } break; - case ExchangeProviderDescription.xmrto: - displayXMRTO = !displayXMRTO; - break; - case ExchangeProviderDescription.morphToken: - displayMorphToken = !displayMorphToken; + case ExchangeProviderDescription.sideShift: + displayAllTrades.value = false; + displaySideShift.value = !displaySideShift.value; + if (displayChangeNow.value && displaySideShift.value && displaySimpleSwap.value) { + displayAllTrades.value = true; + } break; case ExchangeProviderDescription.simpleSwap: - displaySimpleSwap = !displaySimpleSwap; + displayAllTrades.value = false; + displaySimpleSwap.value = !displaySimpleSwap.value; + if (displayChangeNow.value && displaySideShift.value && displaySimpleSwap.value) { + displayAllTrades.value = true; + } + break; + case ExchangeProviderDescription.xmrto: + displayXMRTO.value = !displayXMRTO.value; + break; + case ExchangeProviderDescription.morphToken: + displayMorphToken.value = !displayMorphToken.value; + break; + case ExchangeProviderDescription.all: + displayAllTrades.value = !displayAllTrades.value; + if (displayAllTrades.value) { + displayChangeNow.value = true; + displaySideShift.value = true; + displayXMRTO.value = true; + displayMorphToken.value = true; + displaySimpleSwap.value = true; + } + if (!displayAllTrades.value) { + displayChangeNow.value = false; + displaySideShift.value = false; + displayXMRTO.value = false; + displayMorphToken.value = false; + displaySimpleSwap.value = false; + } break; } } @@ -48,20 +70,22 @@ abstract class TradeFilterStoreBase with Store { List filtered({required List trades, required WalletBase wallet}) { final _trades = trades.where((item) => item.trade.walletId == wallet.id).toList(); - final needToFilter = !displayChangeNow || !displayXMRTO || !displayMorphToken || !displaySimpleSwap; + final needToFilter = !displayChangeNow.value || !displaySideShift.value + || !displayXMRTO.value || !displayMorphToken.value + || !displaySimpleSwap.value; return needToFilter ? _trades .where((item) => - (displayXMRTO && + (displayXMRTO.value && item.trade.provider == ExchangeProviderDescription.xmrto) || - (displayChangeNow && + (displayChangeNow.value && item.trade.provider == ExchangeProviderDescription.changeNow) || - (displayMorphToken && + (displayMorphToken.value && item.trade.provider == ExchangeProviderDescription.morphToken) - ||(displaySimpleSwap && + ||(displaySimpleSwap.value && item.trade.provider == ExchangeProviderDescription.simpleSwap)) .toList() diff --git a/lib/store/dashboard/transaction_filter_store.dart b/lib/store/dashboard/transaction_filter_store.dart index 4444075b7..4198f7d8c 100644 --- a/lib/store/dashboard/transaction_filter_store.dart +++ b/lib/store/dashboard/transaction_filter_store.dart @@ -1,6 +1,8 @@ import 'package:mobx/mobx.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart'; +import 'package:cake_wallet/view_model/dashboard/filter_item.dart'; +import 'package:cake_wallet/generated/i18n.dart'; part 'transaction_filter_store.g.dart'; @@ -8,14 +10,11 @@ class TransactionFilterStore = TransactionFilterStoreBase with _$TransactionFilterStore; abstract class TransactionFilterStoreBase with Store { - TransactionFilterStoreBase( - {this.displayIncoming = true, this.displayOutgoing = true}); + TransactionFilterStoreBase(); - @observable - bool displayIncoming; - - @observable - bool displayOutgoing; + Observable displayAll = Observable(true); + Observable displayIncoming = Observable(true); + Observable displayOutgoing = Observable(true); @observable DateTime? startDate; @@ -24,10 +23,40 @@ abstract class TransactionFilterStoreBase with Store { DateTime? endDate; @action - void toggleIncoming() => displayIncoming = !displayIncoming; + void toggleIAll() { + displayAll.value = (!displayAll.value); + if (displayAll.value) { + displayOutgoing.value = true; + displayIncoming.value = true; + } + if (!displayAll.value) { + displayOutgoing.value = false; + displayIncoming.value = false; + } + } @action - void toggleOutgoing() => displayOutgoing = !displayOutgoing; + void toggleIncoming() { + displayIncoming.value = (!displayIncoming.value); + if (displayIncoming.value && displayOutgoing.value) { + displayAll.value = true; + } + if (!displayIncoming.value || !displayOutgoing.value) { + displayAll.value = false; + } + } + + + @action + void toggleOutgoing() { + displayOutgoing.value = (!displayOutgoing.value); + if (displayIncoming.value && displayOutgoing.value) { + displayAll.value = true; + } + if (!displayIncoming.value || !displayOutgoing.value) { + displayAll.value = false; + } + } @action void changeStartDate(DateTime date) => startDate = date; @@ -37,8 +66,8 @@ abstract class TransactionFilterStoreBase with Store { List filtered({required List transactions}) { var _transactions = []; - final needToFilter = !displayOutgoing || - !displayIncoming || + final needToFilter = !displayOutgoing.value || + !displayIncoming.value || (startDate != null && endDate != null); if (needToFilter) { @@ -50,11 +79,11 @@ abstract class TransactionFilterStoreBase with Store { && (endDate?.isAfter(item.transaction.date) ?? false); } - if (allowed && (!displayOutgoing || !displayIncoming)) { - allowed = (displayOutgoing && + if (allowed && (!displayOutgoing.value || !displayIncoming.value)) { + allowed = (displayOutgoing.value && item.transaction.direction == TransactionDirection.outgoing) || - (displayIncoming && + (displayIncoming.value && item.transaction.direction == TransactionDirection.incoming); } diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 49dd2437a..d736769e2 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -60,13 +60,17 @@ abstract class DashboardViewModelBase with Store { filterItems = { S.current.transactions: [ FilterItem( - value: () => transactionFilterStore.displayIncoming, - caption: S.current.incoming, - onChanged: (value) => transactionFilterStore.toggleIncoming()), + value: transactionFilterStore.displayAll, + caption: 'S.current.all_transactions',//Fixme + onChanged: () => transactionFilterStore.toggleIAll()), FilterItem( - value: () => transactionFilterStore.displayOutgoing, + value: transactionFilterStore.displayIncoming, + caption: S.current.incoming, + onChanged: () => transactionFilterStore.toggleIncoming()), + FilterItem( + value: transactionFilterStore.displayOutgoing, caption: S.current.outgoing, - onChanged: (value) => transactionFilterStore.toggleOutgoing()), + onChanged: () => transactionFilterStore.toggleOutgoing()), // FilterItem( // value: () => false, // caption: S.current.transactions_by_date, @@ -74,10 +78,20 @@ abstract class DashboardViewModelBase with Store { ], S.current.trades: [ FilterItem( - value: () => tradeFilterStore.displayChangeNow, + value: tradeFilterStore.displayAllTrades, + caption: 'S.current.all_trades',//Fixme + onChanged: () => tradeFilterStore + .toggleDisplayExchange(ExchangeProviderDescription.all)), + FilterItem( + value: tradeFilterStore.displayChangeNow, caption: 'Change.NOW', - onChanged: (value) => tradeFilterStore + onChanged: () => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.changeNow)), + FilterItem( + value: tradeFilterStore.displaySideShift, + caption: 'SideShift', + onChanged: () => tradeFilterStore + .toggleDisplayExchange(ExchangeProviderDescription.sideShift)), ] }, subname = '', diff --git a/lib/view_model/dashboard/filter_item.dart b/lib/view_model/dashboard/filter_item.dart index 0230899b4..8bc0f0bf1 100644 --- a/lib/view_model/dashboard/filter_item.dart +++ b/lib/view_model/dashboard/filter_item.dart @@ -1,10 +1,12 @@ +import 'package:mobx/mobx.dart'; + class FilterItem { FilterItem({ required this.value, required this.caption, required this.onChanged}); - bool Function() value; + Observable value; String caption; - Function(bool) onChanged; + Function onChanged; } \ No newline at end of file From 4269f18d013162b7fec61e5b0f37dc77fee00a86 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 10 Nov 2022 16:43:01 +0200 Subject: [PATCH 027/203] fix colors --- .../dashboard/widgets/filter_widget.dart | 18 +++--------------- lib/src/widgets/rounded_checkbox.dart | 10 +++++----- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/lib/src/screens/dashboard/widgets/filter_widget.dart b/lib/src/screens/dashboard/widgets/filter_widget.dart index 8719df562..10bda6798 100644 --- a/lib/src/screens/dashboard/widgets/filter_widget.dart +++ b/lib/src/screens/dashboard/widgets/filter_widget.dart @@ -28,16 +28,6 @@ class FilterWidget extends StatelessWidget { Column( mainAxisSize: MainAxisSize.min, children: [ - Text( - S.of(context).filters, - style: TextStyle( - color: Colors.white, - fontSize: 18, - fontWeight: FontWeight.bold, - fontFamily: 'Lato', - decoration: TextDecoration.none, - ), - ), Padding( padding: EdgeInsets.only(left: 24, right: 24, top: 24), child: ClipRRect( @@ -55,10 +45,8 @@ class FilterWidget extends StatelessWidget { child: Text( S.of(context).filters, style: TextStyle( - color: Theme.of(context) - .textTheme! - .bodyText1! - .decorationColor!, + color: Theme.of(context).primaryTextTheme + .overline!.color!, fontSize: 16, fontFamily: 'Lato', decoration: TextDecoration.none, @@ -182,7 +170,7 @@ class SectionDivider extends StatelessWidget { Widget build(BuildContext context) { return Container( height: 1, - color: Colors.red,//Fixme Theme.of(context).accentTextTheme.subhead.backgroundColor, + color: Theme.of(context).dividerColor, ); } } \ No newline at end of file diff --git a/lib/src/widgets/rounded_checkbox.dart b/lib/src/widgets/rounded_checkbox.dart index 6e5b08f1e..1bdfb267d 100644 --- a/lib/src/widgets/rounded_checkbox.dart +++ b/lib/src/widgets/rounded_checkbox.dart @@ -20,8 +20,8 @@ class RoundedCheckboxWidget extends StatelessWidget { Widget build(BuildContext context) { final baseGradient = LinearGradient(colors: [ - Colors.red, //Fixme Theme.of(context).primaryTextTheme!.subtitle!.color!, - Colors.red //Fixme Theme.of(context).primaryTextTheme!.subtitle!.decorationColor!, + Theme.of(context).primaryTextTheme.subtitle1!.color!, + Theme.of(context).primaryTextTheme.subtitle1!.decorationColor!, ], begin: Alignment.centerLeft, end: Alignment.centerRight); final darkThemeGradient = LinearGradient(colors: [ @@ -32,11 +32,11 @@ class RoundedCheckboxWidget extends StatelessWidget { final gradient = darkTheme ? darkThemeGradient : baseGradient; final uncheckedColor = darkTheme - ? Colors.red //Fixme Theme.of(context).accentTextTheme.subhead.decorationColor + ? Theme.of(context).primaryTextTheme.subtitle1!.decorationColor! : Colors.white; final borderColor = darkTheme - ? Colors.red //Fixme Theme.of(context).accentTextTheme.subtitle.backgroundColor + ? Theme.of(context).accentTextTheme.subtitle2!.backgroundColor! : Colors.transparent; final checkedOuterBoxDecoration = @@ -77,7 +77,7 @@ class RoundedCheckboxWidget extends StatelessWidget { child: Text( caption, style: TextStyle( - color: Colors.red, //Fixme Theme.of(context).primaryTextTheme.title.color, + color: Theme.of(context).primaryTextTheme.headline6!.color!, fontSize: 18, fontFamily: 'Lato', fontWeight: FontWeight.w500, From bf86fd6ed08890ef62a7b320d4d7b3595eb1ea68 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 10 Nov 2022 17:38:23 +0200 Subject: [PATCH 028/203] update localization --- lib/view_model/dashboard/dashboard_view_model.dart | 4 ++-- res/values/strings_de.arb | 6 ++++-- res/values/strings_en.arb | 6 ++++-- res/values/strings_es.arb | 6 ++++-- res/values/strings_fr.arb | 6 ++++-- res/values/strings_hi.arb | 6 ++++-- res/values/strings_hr.arb | 6 ++++-- res/values/strings_it.arb | 6 ++++-- res/values/strings_ja.arb | 6 ++++-- res/values/strings_ko.arb | 6 ++++-- res/values/strings_nl.arb | 6 ++++-- res/values/strings_pl.arb | 6 ++++-- res/values/strings_pt.arb | 6 ++++-- res/values/strings_ru.arb | 6 ++++-- res/values/strings_uk.arb | 6 ++++-- res/values/strings_zh.arb | 4 +++- 16 files changed, 61 insertions(+), 31 deletions(-) diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index d736769e2..c1d57e241 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -61,7 +61,7 @@ abstract class DashboardViewModelBase with Store { S.current.transactions: [ FilterItem( value: transactionFilterStore.displayAll, - caption: 'S.current.all_transactions',//Fixme + caption: S.current.all_transactions, onChanged: () => transactionFilterStore.toggleIAll()), FilterItem( value: transactionFilterStore.displayIncoming, @@ -79,7 +79,7 @@ abstract class DashboardViewModelBase with Store { S.current.trades: [ FilterItem( value: tradeFilterStore.displayAllTrades, - caption: 'S.current.all_trades',//Fixme + caption: S.current.all_trades, onChanged: () => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.all)), FilterItem( diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 685d817d5..36f3b5172 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -48,7 +48,7 @@ "outgoing" : "Ausgehend", "transactions_by_date" : "Transaktionen nach Datum", "trades" : "Börsen", - "filters" : "Filter", + "filters" : "Filtern nach", "today" : "Heute", "yesterday" : "Gestern", "received" : "Empfangen", @@ -651,5 +651,7 @@ "ignor": "Ignorieren", "use_suggested": "Vorgeschlagen verwenden", "do_not_share_warning_text" : "Teilen Sie diese nicht mit anderen, einschließlich des Supports.\n\nSie werden Ihr Geld stehlen!", - "help": "hilfe" + "help": "hilfe", + "all_transactions": "Alle Transaktionen", + "all_trades": "Alle Gewerke" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 877d09231..694de99c3 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -48,7 +48,7 @@ "outgoing" : "Outgoing", "transactions_by_date" : "Transactions by date", "trades" : "Trades", - "filters" : "Filter", + "filters" : "Filter by", "today" : "Today", "yesterday" : "Yesterday", "received" : "Received", @@ -651,5 +651,7 @@ "ignor": "Ignore", "use_suggested": "Use Suggested", "do_not_share_warning_text" : "Do not share these with anyone else, including support.\n\nThey will steal your money!", - "help": "help" + "help": "help", + "all_transactions": "All transactions", + "all_trades": "All trades" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 505f3ffa8..b3af2a5c7 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -48,7 +48,7 @@ "outgoing" : "Saliente", "transactions_by_date" : "Transacciones por fecha", "trades" : "Cambios", - "filters" : "Filtrar", + "filters" : "Filtrado por", "today" : "Hoy", "yesterday" : "Ayer", "received" : "Recibido", @@ -651,5 +651,7 @@ "ignor": "Pasar por alto", "use_suggested": "Usar sugerido", "do_not_share_warning_text" : "No comparta estos con nadie más, incluido el soporte.\n\n¡Te robarán tu dinero!", - "help": "ayuda" + "help": "ayuda", + "all_transactions": "Todas las transacciones", + "all_trades": "Todos los oficios" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 941016c0b..aa50a4859 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -46,7 +46,7 @@ "outgoing" : "Sortantes", "transactions_by_date" : "Transactions par date", "trades" : "Échanges", - "filters" : "Filtre", + "filters" : "Filtrer par", "today" : "Aujourd'hui", "yesterday" : "Hier", "received" : "Reçus", @@ -649,5 +649,7 @@ "ignor": "Ignorer", "use_suggested": "Utilisation suggérée", "do_not_share_warning_text" : "Ne les partagez avec personne d'autre, y compris avec l'assistance.\n\nIls vont voler votre argent!", - "help": "aider" + "help": "aider", + "all_transactions": "Toutes transactions", + "all_trades": "Tous métiers" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 7faa06f7f..f64e1c42c 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -48,7 +48,7 @@ "outgoing" : "निवर्तमान", "transactions_by_date" : "तारीख से लेन-देन", "trades" : "ट्रेडों", - "filters" : "फ़िल्टर", + "filters" : "के द्वारा छनित", "today" : "आज", "yesterday" : "बिता कल", "received" : "प्राप्त किया", @@ -651,5 +651,7 @@ "ignor": "नज़रअंदाज़ करना", "use_suggested": "सुझाए गए का प्रयोग करें", "do_not_share_warning_text" : "इन्हें समर्थन सहित किसी और के साथ साझा न करें।\n\nवे आपका पैसा चुरा लेंगे!", - "help": "मदद करना" + "help": "मदद करना", + "all_transactions": "सभी लेन - देन", + "all_trades": "सभी व्यापार" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 4fa77948a..94668ff47 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -48,7 +48,7 @@ "outgoing" : "Odlazno", "transactions_by_date" : "Transakcije prema datumu", "trades" : "Razmjene", - "filters" : "Filter", + "filters" : "Filtrirati po", "today" : "Danas", "yesterday" : "Jučer", "received" : "Primljeno", @@ -651,5 +651,7 @@ "ignor": "Zanemariti", "use_suggested": "Koristite predloženo", "do_not_share_warning_text" : "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nUkrast će vam novac!", - "help": "pomozite" + "help": "pomozite", + "all_transactions": "Sve transakcije", + "all_trades": "Svi obrti" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 9a42a588b..c8016f481 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -48,7 +48,7 @@ "outgoing" : "In uscita", "transactions_by_date" : "Transazioni per data", "trades" : "Scambi", - "filters" : "Filtri", + "filters" : "Filtrirati po", "today" : "Oggi", "yesterday" : "Ieri", "received" : "Ricevuto", @@ -651,5 +651,7 @@ "ignor": "Ignorare", "use_suggested": "Usa suggerito", "do_not_share_warning_text" : "Non condividerli con nessun altro, incluso il supporto.\n\nTi ruberanno i soldi!", - "help": "aiuto" + "help": "aiuto", + "all_transactions": "Sve transakcije", + "all_trades": "Svi obrti" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index c1d0de4e3..220e4f5df 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -48,7 +48,7 @@ "outgoing" : "発信", "transactions_by_date" : "日付ごとの取引", "trades" : "取引", - "filters" : "フィルタ", + "filters" : "でフィルタリング", "today" : "今日", "yesterday" : "昨日", "received" : "受け取った", @@ -651,5 +651,7 @@ "ignor": "無視", "use_suggested": "推奨を使用", "do_not_share_warning_text" : "サポートを含め、これらを他の誰とも共有しないでください。\n\n彼らはあなたのお金を盗みます!", - "help": "ヘルプ" + "help": "ヘルプ", + "all_transactions": "全取引", + "all_trades": "すべての取引" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 127aa949e..1bef56dbc 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -48,7 +48,7 @@ "outgoing" : "나가는", "transactions_by_date" : "날짜 별 거래", "trades" : "거래", - "filters" : "필터", + "filters" : "필터링 기준", "today" : "오늘", "yesterday" : "어제", "received" : "받았습니다", @@ -651,5 +651,7 @@ "ignor": "무시하다", "use_suggested": "추천 사용", "do_not_share_warning_text" : "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n그들은 당신의 돈을 훔칠 것입니다!", - "help": "돕다" + "help": "돕다", + "all_transactions": "모든 거래 창구", + "all_trades": "A모든 거래" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index fa748b552..3db8ad2f7 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -48,7 +48,7 @@ "outgoing" : "Uitgaande", "transactions_by_date" : "Transacties op datum", "trades" : "Trades", - "filters" : "Filter", + "filters" : "Filteren op", "today" : "Vandaag", "yesterday" : "Gisteren", "received" : "Ontvangen", @@ -651,5 +651,7 @@ "ignor": "Negeren", "use_suggested": "Gebruik aanbevolen", "do_not_share_warning_text" : "Deel deze met niemand anders, ook niet met support.\n\nZe zullen je geld stelen!", - "help": "helpen" + "help": "helpen", + "all_transactions": "Alle transacties", + "all_trades": "Alle transacties" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 454fe9717..83ec99d99 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -48,7 +48,7 @@ "outgoing" : "Towarzyski", "transactions_by_date" : "Transakcje według daty", "trades" : "Transakcje", - "filters" : "Filtr", + "filters" : "Filtruj według", "today" : "Dzisiaj", "yesterday" : "Wczoraj", "received" : "Odebrane", @@ -651,5 +651,7 @@ "ignor": "Ignorować", "use_suggested": "Użyj sugerowane", "do_not_share_warning_text" : "Nie udostępniaj ich nikomu innemu, w tym wsparcia.\n\nUkradną twoje pieniądze!", - "help": "pomoc" + "help": "pomoc", + "all_transactions": "Wszystkie transakcje", + "all_trades": "Wszystkie operacje" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 04a0a3ff2..866dcd26c 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -48,7 +48,7 @@ "outgoing" : "Enviadas", "transactions_by_date" : "Transações por data", "trades" : "Trocas", - "filters" : "Filtro", + "filters" : "Filtrar por", "today" : "Hoje", "yesterday" : "Ontem", "received" : "Recebida", @@ -651,5 +651,7 @@ "ignor": "Ignorar", "use_suggested": "Uso sugerido", "do_not_share_warning_text" : "Não os compartilhe com mais ninguém, incluindo suporte.\n\nEles vão roubar seu dinheiro!", - "help": "ajuda" + "help": "ajuda", + "all_transactions": "Todas as transacções", + "all_trades": "Todas as negociações" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 632b0990c..b34d4df15 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -48,7 +48,7 @@ "outgoing" : "Исходящие", "transactions_by_date" : "Сортировать по дате", "trades" : "Сделки", - "filters" : "Фильтр", + "filters" : "Фильтровать по", "today" : "Сегодня", "yesterday" : "Вчера", "received" : "Полученные", @@ -651,5 +651,7 @@ "ignor": "Игнорировать", "use_suggested": "Использовать предложенный", "do_not_share_warning_text" : "Не делитесь ими с кем-либо еще, в том числе со службой поддержки.\n\nОни украдут ваши деньги!", - "help": "помощь" + "help": "помощь", + "all_transactions": "Все транзакции", + "all_trades": "Все сделки" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 5e0f0d18a..285a67fa5 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -48,7 +48,7 @@ "outgoing" : "Вихідні", "transactions_by_date" : "Сортувати по даті", "trades" : "Торгові операції", - "filters" : "Фільтр", + "filters" : "Фільтрувати по", "today" : "Сьогодні", "yesterday" : "Вчора", "received" : "Отримані", @@ -650,5 +650,7 @@ "ignor": "Ігнорувати", "use_suggested": "Використати запропоноване", "do_not_share_warning_text" : "Не повідомляйте їх нікому, включно зі службою підтримки.\n\nВони вкрадуть ваші гроші!", - "help": "допомога" + "help": "допомога", + "all_transactions": "Всі транзакції", + "all_trades": "Всі операції" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index c46d07d59..8212d83b6 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -649,5 +649,7 @@ "ignor": "忽视", "use_suggested": "使用建议", "do_not_share_warning_text" : "不要與其他任何人分享這些內容,包括支持。\n\n他們會偷你的錢!", - "help": "帮助" + "help": "帮助", + "all_transactions": "所有交易", + "all_trades": "所有的变化" } From cf7c21946b4550d793158a753800857d5d859708 Mon Sep 17 00:00:00 2001 From: Justin Ehrenhofer Date: Thu, 10 Nov 2022 14:45:10 -0600 Subject: [PATCH 029/203] Improve warning wording Recommended in the Telegram testing group --- res/values/strings_de.arb | 2 +- res/values/strings_en.arb | 2 +- res/values/strings_es.arb | 2 +- res/values/strings_fr.arb | 2 +- res/values/strings_hi.arb | 2 +- res/values/strings_hr.arb | 2 +- res/values/strings_it.arb | 2 +- res/values/strings_ja.arb | 2 +- res/values/strings_ko.arb | 2 +- res/values/strings_nl.arb | 2 +- res/values/strings_pl.arb | 2 +- res/values/strings_pt.arb | 2 +- res/values/strings_ru.arb | 2 +- res/values/strings_uk.arb | 2 +- res/values/strings_zh.arb | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 685d817d5..dda932168 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -650,6 +650,6 @@ "low_fee_alert": "Sie verwenden derzeit eine niedrige Netzwerkgebührenpriorität. Dies kann zu langen Wartezeiten, unterschiedlichen Kursen oder stornierten Trades führen. Wir empfehlen, für ein besseres Erlebnis eine höhere Gebühr festzulegen.", "ignor": "Ignorieren", "use_suggested": "Vorgeschlagen verwenden", - "do_not_share_warning_text" : "Teilen Sie diese nicht mit anderen, einschließlich des Supports.\n\nSie werden Ihr Geld stehlen!", + "do_not_share_warning_text" : "Teilen Sie diese nicht mit anderen, einschließlich Support.\n\nIhr Geld kann und wird gestohlen werden!", "help": "hilfe" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 877d09231..464f9ee06 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -650,6 +650,6 @@ "low_fee_alert": "You currently are using a low network fee priority. This could cause long waits, different rates, or canceled trades. We recommend setting a higher fee for a better experience.", "ignor": "Ignore", "use_suggested": "Use Suggested", - "do_not_share_warning_text" : "Do not share these with anyone else, including support.\n\nThey will steal your money!", + "do_not_share_warning_text" : "Do not share these with anyone else, including support.\n\nYour funds can and will be stolen!", "help": "help" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 505f3ffa8..45a2a6ae7 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -650,6 +650,6 @@ "low_fee_alert": "Actualmente está utilizando una prioridad de tarifa de red baja. Esto podría causar largas esperas, tarifas diferentes o transacciones canceladas. Recomendamos establecer una tarifa más alta para una mejor experiencia.", "ignor": "Pasar por alto", "use_suggested": "Usar sugerido", - "do_not_share_warning_text" : "No comparta estos con nadie más, incluido el soporte.\n\n¡Te robarán tu dinero!", + "do_not_share_warning_text" : "No comparta estos con nadie más, incluido el soporte.\n\n¡Sus fondos pueden ser y serán robados!", "help": "ayuda" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 941016c0b..fda7904b9 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -648,6 +648,6 @@ "low_fee_alert": "Vous utilisez actuellement une priorité de frais de réseau peu élevés. Cela pourrait entraîner de longues attentes, des taux différents ou des transactions annulées. Nous vous recommandons de fixer des frais plus élevés pour une meilleure expérience.", "ignor": "Ignorer", "use_suggested": "Utilisation suggérée", - "do_not_share_warning_text" : "Ne les partagez avec personne d'autre, y compris avec l'assistance.\n\nIls vont voler votre argent!", + "do_not_share_warning_text" : "Ne les partagez avec personne d'autre, y compris avec l'assistance.\n\nVos fonds peuvent et seront volés!", "help": "aider" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 7faa06f7f..5cd157c91 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -650,6 +650,6 @@ "low_fee_alert": "आप वर्तमान में कम नेटवर्क शुल्क प्राथमिकता का उपयोग कर रहे हैं। यह लंबे इंतजार, अलग-अलग दरों या रद्द किए गए ट्रेडों का कारण बन सकता है। हम बेहतर अनुभव के लिए अधिक शुल्क निर्धारित करने की सलाह देते हैं।", "ignor": "नज़रअंदाज़ करना", "use_suggested": "सुझाए गए का प्रयोग करें", - "do_not_share_warning_text" : "इन्हें समर्थन सहित किसी और के साथ साझा न करें।\n\nवे आपका पैसा चुरा लेंगे!", + "do_not_share_warning_text" : "समर्थन सहित, इन्हें किसी और के साथ साझा न करें।\n\nआपके धन की चोरी हो सकती है और होगी!", "help": "मदद करना" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 4fa77948a..369e573d4 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -650,6 +650,6 @@ "low_fee_alert": "Trenutačno koristite niski prioritet mrežne naknade. To bi moglo uzrokovati duga čekanja, različite tečajeve ili otkazane trgovine. Preporučujemo postavljanje veće naknade za bolje iskustvo.", "ignor": "Zanemariti", "use_suggested": "Koristite predloženo", - "do_not_share_warning_text" : "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nUkrast će vam novac!", + "do_not_share_warning_text" : "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nVaša sredstva mogu i bit će ukradena!", "help": "pomozite" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 9a42a588b..f1430aa5b 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -650,6 +650,6 @@ "low_fee_alert": "Attualmente stai utilizzando una priorità a tariffa di rete bassa. Ciò potrebbe causare lunghe attese, tariffe diverse o operazioni annullate. Ti consigliamo di impostare una tariffa più alta per un'esperienza migliore.", "ignor": "Ignorare", "use_suggested": "Usa suggerito", - "do_not_share_warning_text" : "Non condividerli con nessun altro, incluso il supporto.\n\nTi ruberanno i soldi!", + "do_not_share_warning_text" : "Non condividerli con nessun altro, incluso il supporto.\n\nI tuoi fondi possono e saranno rubati!", "help": "aiuto" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index c1d0de4e3..56622a2b2 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -650,6 +650,6 @@ "low_fee_alert": "現在、低ネットワーク料金優先度を使用しています。これにより、長い待ち時間、異なるレート、またはキャンセルされた取引が発生する可能性があります。より良い体験のために、より高い料金を設定することをお勧めします。", "ignor": "無視", "use_suggested": "推奨を使用", - "do_not_share_warning_text" : "サポートを含め、これらを他の誰とも共有しないでください。\n\n彼らはあなたのお金を盗みます!", + "do_not_share_warning_text" : "サポートを含め、これらを他の誰とも共有しないでください。\n\nあなたの資金は盗まれる可能性があります!", "help": "ヘルプ" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 127aa949e..ea7a722f9 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -650,6 +650,6 @@ "low_fee_alert": "현재 낮은 네트워크 요금 우선 순위를 사용하고 있습니다. 이로 인해 긴 대기 시간, 다른 요금 또는 취소된 거래가 발생할 수 있습니다. 더 나은 경험을 위해 더 높은 요금을 설정하는 것이 좋습니다.", "ignor": "무시하다", "use_suggested": "추천 사용", - "do_not_share_warning_text" : "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n그들은 당신의 돈을 훔칠 것입니다!", + "do_not_share_warning_text" : "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n귀하의 자금은 도난당할 수 있고 도난당할 수 있습니다!", "help": "돕다" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index fa748b552..a25087498 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -650,6 +650,6 @@ "low_fee_alert": "U gebruikt momenteel een lage prioriteit voor netwerkkosten. Dit kan lange wachttijden, andere tarieven of geannuleerde transacties veroorzaken. We raden aan een hogere vergoeding in te stellen voor een betere ervaring.", "ignor": "Negeren", "use_suggested": "Gebruik aanbevolen", - "do_not_share_warning_text" : "Deel deze met niemand anders, ook niet met support.\n\nZe zullen je geld stelen!", + "do_not_share_warning_text" : "Deel deze met niemand anders, ook niet met support.\n\nUw geld kan en zal worden gestolen!", "help": "helpen" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 454fe9717..d66c084e6 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -650,6 +650,6 @@ "low_fee_alert": "Obecnie korzystasz z niskiego priorytetu opłaty sieciowej. Może to spowodować długie oczekiwanie, różne stawki lub anulowane transakcje. Zalecamy ustawienie wyższej opłaty, aby zapewnić lepsze wrażenia.", "ignor": "Ignorować", "use_suggested": "Użyj sugerowane", - "do_not_share_warning_text" : "Nie udostępniaj ich nikomu innemu, w tym wsparcia.\n\nUkradną twoje pieniądze!", + "do_not_share_warning_text" : "Nie udostępniaj ich nikomu innemu, w tym pomocy.\n\nTwoje środki mogą i zostaną skradzione!", "help": "pomoc" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 04a0a3ff2..5db2e7a6a 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -650,6 +650,6 @@ "low_fee_alert": "No momento, você está usando uma prioridade de taxa de rede baixa. Isso pode causar longas esperas, taxas diferentes ou negociações canceladas. Recomendamos definir uma taxa mais alta para uma melhor experiência.", "ignor": "Ignorar", "use_suggested": "Uso sugerido", - "do_not_share_warning_text" : "Não os compartilhe com mais ninguém, incluindo suporte.\n\nEles vão roubar seu dinheiro!", + "do_not_share_warning_text" : "Não os compartilhe com mais ninguém, incluindo suporte.\n\nSeus fundos podem e serão roubados!", "help": "ajuda" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 632b0990c..b454a4ffb 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -650,6 +650,6 @@ "low_fee_alert": "В настоящее время вы используете низкий приоритет платы за сеть. Это может привести к длительному ожиданию, изменению ставок или отмене сделок. Мы рекомендуем установить более высокую плату для лучшего опыта.", "ignor": "Игнорировать", "use_suggested": "Использовать предложенный", - "do_not_share_warning_text" : "Не делитесь ими с кем-либо еще, в том числе со службой поддержки.\n\nОни украдут ваши деньги!", + "do_not_share_warning_text" : "Не сообщайте их никому, включая техподдержку.\n\nВаши средства могут и будут украдены!", "help": "помощь" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 5e0f0d18a..f8669f528 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -649,6 +649,6 @@ "low_fee_alert": "Зараз ви використовуєте низький пріоритет плати за мережу. Це може спричинити тривале очікування, інший курс або скасування угод. Ми рекомендуємо встановити вищу плату для кращого досвіду.", "ignor": "Ігнорувати", "use_suggested": "Використати запропоноване", - "do_not_share_warning_text" : "Не повідомляйте їх нікому, включно зі службою підтримки.\n\nВони вкрадуть ваші гроші!", + "do_not_share_warning_text" : "Не діліться цим нікому, включно зі службою підтримки.\n\nВаші кошти можуть і будуть вкрадені!", "help": "допомога" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index c46d07d59..c586315e4 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -648,6 +648,6 @@ "low_fee_alert": "您当前正在使用低网络费用优先级。这可能会导致长时间等待、不同的费率或取消交易。我们建议设置更高的费用以获得更好的体验。", "ignor": "忽视", "use_suggested": "使用建议", - "do_not_share_warning_text" : "不要與其他任何人分享這些內容,包括支持。\n\n他們會偷你的錢!", + "do_not_share_warning_text" : "请勿与其他任何人分享这些信息,包括支持人员。\n\n您的资金可能而且将会被盗!", "help": "帮助" } From 668e9fcf076b9bf5603e9651d31de5828ab0f325 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Fri, 11 Nov 2022 15:55:21 +0200 Subject: [PATCH 030/203] [CW-73] Fix matching .exchange domain to openAlias --- lib/entities/parse_address_from_domain.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index 7fcaeeaad..775f6e229 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -4,7 +4,6 @@ import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; import 'package:cake_wallet/entities/emoji_string_extension.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:flutter/foundation.dart'; import 'package:cake_wallet/entities/fio_address_provider.dart'; class AddressResolver { @@ -51,7 +50,7 @@ class AddressResolver { return ParsedAddress(addresses: [text]); } - if (unstoppableDomains.any((domain) => name.contains(domain))) { + if (unstoppableDomains.any((domain) => name.trim() == domain)) { final address = await fetchUnstoppableDomainAddress(text, ticker); return ParsedAddress.fetchUnstoppableDomainAddress(address: address, name: text); } From 69886372660be5e204083e9e05e2dbb789a4c597 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sun, 13 Nov 2022 20:06:45 +0200 Subject: [PATCH 031/203] fix fetching trade state for SideShift --- lib/exchange/sideshift/sideshift_exchange_provider.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/sideshift/sideshift_exchange_provider.dart index a732f7ef2..8cd4593c1 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/sideshift/sideshift_exchange_provider.dart @@ -250,8 +250,10 @@ class SideShiftExchangeProvider extends ExchangeProvider { final deposits = responseJSON['deposits'] as List?; TradeState? state; - if (deposits != null && deposits.isNotEmpty) { - final status = deposits[0]['status'] as String; + if (deposits != null && deposits.isEmpty) { + state = TradeState.deserialize(raw: 'created'); + } else { + final status = deposits?[0]['status'] as String; state = TradeState.deserialize(raw: status); } From 74cbb6f0018c2b27d7f2fb42ed9b371f795af290 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sun, 13 Nov 2022 21:18:01 +0200 Subject: [PATCH 032/203] fix UI with new design CW-138 --- lib/view_model/trade_details_view_model.dart | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/view_model/trade_details_view_model.dart b/lib/view_model/trade_details_view_model.dart index f2985463c..5a1f78774 100644 --- a/lib/view_model/trade_details_view_model.dart +++ b/lib/view_model/trade_details_view_model.dart @@ -142,17 +142,5 @@ abstract class TradeDetailsViewModelBase with Store { items.add(TrackTradeListItem( title: 'Track', value: buildURL, onTap: () => launch(buildURL))); } - - if (trade.createdAt != null) { - items.add(StandartListItem( - title: S.current.trade_details_created_at, - value: trade.createdAt != null ? dateFormat.format(trade.createdAt!).toString() : '')); - } - - if (trade.from != null && trade.to != null) { - items.add(StandartListItem( - title: S.current.trade_details_pair, - value: '${trade.from.toString()} → ${trade.to.toString()}')); - } } } From 9ce8a1944befb200a2afc2ab19ca7467ac479954 Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 14 Nov 2022 22:50:07 +0200 Subject: [PATCH 033/203] fix empty containers --- lib/src/screens/send/widgets/send_card.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 7e7194f88..384f4f2cc 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -332,8 +332,7 @@ class SendCardState extends State ], ), )), - sendViewModel.balanceViewModel.disableFiat ? - Container () : + if (sendViewModel.balanceViewModel.disableFiat) Padding( padding: const EdgeInsets.only(top: 20), child: BaseTextFormField( @@ -440,8 +439,9 @@ class SendCardState extends State Padding( padding: EdgeInsets.only(top: 5), - child: sendViewModel.balanceViewModel.disableFiat ? - Container () : Text(output + child: sendViewModel.balanceViewModel.disableFiat + ? const SizedBox(height: 14) + : Text(output .estimatedFeeFiatAmount + ' ' + sendViewModel From 549975ecc17316141ab22b20892fd5d7fe24140a Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 16 Nov 2022 09:29:14 +0200 Subject: [PATCH 034/203] Reorganize settings --- lib/di.dart | 18 +- lib/router.dart | 29 ++- lib/routes.dart | 5 + lib/src/screens/dashboard/wallet_menu.dart | 136 +++++------- .../screens/nodes/widgets/node_list_row.dart | 7 +- .../settings/connection_sync_page.dart | 155 +++++++++++++ .../settings/display_settings_page.dart | 80 +++++++ .../screens/settings/other_settings_page.dart | 45 ++++ lib/src/screens/settings/privacy_page.dart | 30 +++ .../settings/security_backup_page.dart | 84 +++++++ lib/src/screens/settings/settings.dart | 98 --------- lib/src/widgets/standard_list.dart | 4 +- .../settings/settings_view_model.dart | 207 ++++-------------- res/values/strings_de.arb | 6 +- res/values/strings_en.arb | 9 +- res/values/strings_es.arb | 6 +- res/values/strings_fr.arb | 6 +- res/values/strings_hi.arb | 6 +- res/values/strings_hr.arb | 6 +- res/values/strings_it.arb | 6 +- res/values/strings_ja.arb | 6 +- res/values/strings_ko.arb | 6 +- res/values/strings_nl.arb | 6 +- res/values/strings_pl.arb | 6 +- res/values/strings_pt.arb | 6 +- res/values/strings_ru.arb | 6 +- res/values/strings_uk.arb | 7 +- res/values/strings_zh.arb | 6 +- 28 files changed, 619 insertions(+), 373 deletions(-) create mode 100644 lib/src/screens/settings/connection_sync_page.dart create mode 100644 lib/src/screens/settings/display_settings_page.dart create mode 100644 lib/src/screens/settings/other_settings_page.dart create mode 100644 lib/src/screens/settings/privacy_page.dart create mode 100644 lib/src/screens/settings/security_backup_page.dart delete mode 100644 lib/src/screens/settings/settings.dart diff --git a/lib/di.dart b/lib/di.dart index 90549cf6f..265a5036b 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -5,9 +5,14 @@ import 'package:cake_wallet/ionia/ionia_anypay.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/ionia/ionia_tip.dart'; import 'package:cake_wallet/src/screens/buy/onramper_page.dart'; +import 'package:cake_wallet/src/screens/setting/display_settings_page.dart'; +import 'package:cake_wallet/src/screens/setting/other_settings_page.dart'; +import 'package:cake_wallet/src/screens/setting/privacy_page.dart'; +import 'package:cake_wallet/src/screens/setting/security_backup_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; +import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_custom_tip_view_model.dart'; @@ -59,7 +64,6 @@ import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart'; import 'package:cake_wallet/src/screens/send/send_template_page.dart'; -import 'package:cake_wallet/src/screens/settings/settings.dart'; import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart'; import 'package:cake_wallet/src/screens/support/support_page.dart'; import 'package:cake_wallet/src/screens/trade_details/trade_details_page.dart'; @@ -439,8 +443,6 @@ Future setup( return SettingsViewModel(appStore.settingsStore, yatStore, appStore.wallet!); }); - getIt.registerFactory(() => SettingsPage(getIt.get())); - getIt .registerFactory(() => WalletSeedViewModel(getIt.get().wallet!)); @@ -477,6 +479,16 @@ Future setup( getIt.registerFactory(() => NodeListPage(getIt.get())); + getIt.registerFactory(() => ConnectionSyncPage(getIt.get(), getIt.get())); + + getIt.registerFactory(() => SecurityBackupPage(getIt.get())); + + getIt.registerFactory(() => PrivacyPage(getIt.get())); + + getIt.registerFactory(() => DisplaySettingsPage(getIt.get())); + + getIt.registerFactory(() => OtherSettingsPage(getIt.get())); + getIt.registerFactory(() => NodeCreateOrEditViewModel(_nodeSource, getIt.get().wallet!)); diff --git a/lib/router.dart b/lib/router.dart index b255ce8b9..e35ba19ef 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -5,6 +5,10 @@ import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart'; import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart'; import 'package:cake_wallet/src/screens/buy/onramper_page.dart'; import 'package:cake_wallet/src/screens/buy/pre_order_page.dart'; +import 'package:cake_wallet/src/screens/setting/display_settings_page.dart'; +import 'package:cake_wallet/src/screens/setting/other_settings_page.dart'; +import 'package:cake_wallet/src/screens/setting/privacy_page.dart'; +import 'package:cake_wallet/src/screens/setting/security_backup_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_cards_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dart'; @@ -16,6 +20,7 @@ import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; +import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; import 'package:cake_wallet/src/screens/support/support_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; @@ -56,7 +61,6 @@ import 'package:cake_wallet/src/screens/contact/contact_page.dart'; import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart'; import 'package:cake_wallet/src/screens/restore/restore_wallet_from_seed_details.dart'; import 'package:cake_wallet/src/screens/exchange/exchange_page.dart'; -import 'package:cake_wallet/src/screens/settings/settings.dart'; import 'package:cake_wallet/src/screens/rescan/rescan_page.dart'; import 'package:cake_wallet/src/screens/faq/faq_page.dart'; import 'package:cake_wallet/src/screens/trade_details/trade_details_page.dart'; @@ -278,6 +282,26 @@ Route createRoute(RouteSettings settings) { return CupertinoPageRoute( builder: (_) => getIt.get()); + case Routes.connectionSync: + return CupertinoPageRoute( + builder: (_) => getIt.get()); + + case Routes.securityBackupPage: + return CupertinoPageRoute( + builder: (_) => getIt.get()); + + case Routes.privacyPage: + return CupertinoPageRoute( + builder: (_) => getIt.get()); + + case Routes.displaySettingsPage: + return CupertinoPageRoute( + builder: (_) => getIt.get()); + + case Routes.otherSettingsPage: + return CupertinoPageRoute( + builder: (_) => getIt.get()); + case Routes.newNode: return CupertinoPageRoute( builder: (_) => getIt.get()); @@ -360,9 +384,6 @@ Route createRoute(RouteSettings settings) { return CupertinoPageRoute( builder: (_) => getIt.get()); - case Routes.settings: - return MaterialPageRoute(builder: (_) => getIt.get()); - case Routes.rescan: return MaterialPageRoute(builder: (_) => getIt.get()); diff --git a/lib/routes.dart b/lib/routes.dart index 3a781ac3a..04642ba34 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -77,4 +77,9 @@ class Routes { static const ioniaMoreOptionsPage = '/ionia_more_options_page'; static const ioniaCustomRedeemPage = '/ionia_custom_redeem_page'; static const onramperPage = '/onramper'; + static const connectionSync = '/connection_sync_page'; + static const securityBackupPage = '/security_and_backup_page'; + static const privacyPage = '/privacy_page'; + static const displaySettingsPage = '/display_settings_page'; + static const otherSettingsPage = '/other_settings_page'; } diff --git a/lib/src/screens/dashboard/wallet_menu.dart b/lib/src/screens/dashboard/wallet_menu.dart index 68e7cc76d..bc1f20a5d 100644 --- a/lib/src/screens/dashboard/wallet_menu.dart +++ b/lib/src/screens/dashboard/wallet_menu.dart @@ -1,81 +1,64 @@ import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/src/screens/dashboard/wallet_menu_item.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/auth/auth_page.dart'; -import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; -import 'package:cake_wallet/wallet_type_utils.dart'; // FIXME: terrible design class WalletMenu { WalletMenu(this.context, this.reconnect, this.hasRescan) : items = [] { items.addAll([ - WalletMenuItem( - title: S.current.reconnect, - image: Image.asset('assets/images/reconnect_menu.png', - height: 16, width: 16), - handler: () => _presentReconnectAlert(context)), - if (hasRescan) - WalletMenuItem( - title: S.current.rescan, - image: Image.asset('assets/images/filter_icon.png', - height: 16, width: 16, color: Palette.darkBlue), - handler: () => Navigator.of(context).pushNamed(Routes.rescan)), - WalletMenuItem( - title: S.current.wallets, - image: Image.asset('assets/images/wallet_menu.png', - height: 16, width: 16), - handler: () => Navigator.of(context).pushNamed(Routes.walletList)), - WalletMenuItem( - title: S.current.nodes, - image: Image.asset('assets/images/nodes_menu.png', - height: 16, width: 16), - handler: () => Navigator.of(context).pushNamed(Routes.nodeList)), - WalletMenuItem( - title: S.current.show_keys, - image: - Image.asset('assets/images/key_menu.png', height: 16, width: 16), - handler: () { - Navigator.of(context).pushNamed(Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { - if (isAuthenticatedSuccessfully) { - auth.close(route: Routes.showKeys); - } - }); - }), - WalletMenuItem( - title: S.current.address_book_menu, - image: Image.asset('assets/images/open_book_menu.png', - height: 16, width: 16), - handler: () => Navigator.of(context).pushNamed(Routes.addressBook)), - WalletMenuItem( - title: S.current.backup, - image: Image.asset('assets/images/restore_wallet.png', - height: 16, - width: 16, - color: Palette.darkBlue), - handler: () { - Navigator.of(context).pushNamed( - Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { - if (isAuthenticatedSuccessfully) { - auth.close(route:Routes.backup); - } - }); - }), - WalletMenuItem( - title: S.current.settings_title, - image: Image.asset('assets/images/settings_menu.png', - height: 16, width: 16), - handler: () => Navigator.of(context).pushNamed(Routes.settings)), - WalletMenuItem( - title: S.current.settings_support, - image: Image.asset('assets/images/question_mark.png', - height: 16, width: 16, color: Palette.darkBlue), - handler: () => Navigator.of(context).pushNamed(Routes.support)), + WalletMenuItem( + title: S.current.connection_sync, + image: Image.asset('assets/images/nodes_menu.png', + height: 16, width: 16), + handler: () => Navigator.of(context).pushNamed(Routes.connectionSync), + ), + WalletMenuItem( + title: S.current.wallets, + image: Image.asset('assets/images/wallet_menu.png', + height: 16, width: 16), + handler: () => Navigator.of(context).pushNamed(Routes.walletList), + ), + WalletMenuItem( + title: S.current.security_and_backup, + image: + Image.asset('assets/images/key_menu.png', height: 16, width: 16), + handler: () { + Navigator.of(context).pushNamed(Routes.securityBackupPage); + }), + WalletMenuItem( + title: S.current.privacy, + image: + Image.asset('assets/images/eye_menu.png', height: 16, width: 16), + handler: () { + Navigator.of(context).pushNamed(Routes.privacyPage); + }), + WalletMenuItem( + title: S.current.address_book_menu, + image: Image.asset('assets/images/open_book_menu.png', + height: 16, width: 16), + handler: () => Navigator.of(context).pushNamed(Routes.addressBook), + ), + WalletMenuItem( + title: S.current.display_settings, + image: Image.asset('assets/images/eye_menu.png', + height: 16, width: 16), + handler: () => Navigator.of(context).pushNamed(Routes.displaySettingsPage), + ), + WalletMenuItem( + title: S.current.other_settings, + image: Image.asset('assets/images/settings_menu.png', + height: 16, width: 16), + handler: () => Navigator.of(context).pushNamed(Routes.otherSettingsPage), + ), + WalletMenuItem( + title: S.current.settings_support, + image: Image.asset('assets/images/question_mark.png', + height: 16, width: 16, color: Palette.darkBlue), + handler: () => Navigator.of(context).pushNamed(Routes.support), + ), ]); } @@ -86,23 +69,6 @@ class WalletMenu { void action(int index) { final item = items[index]; - item?.handler(); - } - - Future _presentReconnectAlert(BuildContext context) async { - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: S.of(context).reconnection, - alertContent: S.of(context).reconnect_alert_text, - rightButtonText: S.of(context).ok, - leftButtonText: S.of(context).cancel, - actionRightButton: () async { - Navigator.of(context).pop(); - await reconnect?.call(); - }, - actionLeftButton: () => Navigator.of(context).pop()); - }); + item.handler(); } } diff --git a/lib/src/screens/nodes/widgets/node_list_row.dart b/lib/src/screens/nodes/widgets/node_list_row.dart index 3008d450c..580aba170 100644 --- a/lib/src/screens/nodes/widgets/node_list_row.dart +++ b/lib/src/screens/nodes/widgets/node_list_row.dart @@ -37,7 +37,10 @@ class NodeHeaderListRow extends StandardListRow { @override Widget buildTrailing(BuildContext context) { - return Icon(Icons.add, - color: Theme.of(context).accentTextTheme!.subtitle1!.color!, size: 24.0); + return SizedBox( + width: 20, + child: Icon(Icons.add, + color: Theme.of(context).accentTextTheme!.subtitle1!.color!, size: 24.0), + ); } } diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart new file mode 100644 index 000000000..0e56d6e58 --- /dev/null +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -0,0 +1,155 @@ +import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cw_core/node.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/nodes/widgets/node_list_row.dart'; +import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; + +class ConnectionSyncPage extends BasePage { + ConnectionSyncPage(this.nodeListViewModel, this.dashboardViewModel); + + @override + String get title => S.current.connection_sync; + + final NodeListViewModel nodeListViewModel; + final DashboardViewModel dashboardViewModel; + + @override + Widget body(BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 10), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SettingsCellWithArrow( + title: S.current.reconnect, + handler: (context) => _presentReconnectAlert(context), + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + SettingsCellWithArrow( + title: S.current.rescan, + handler: (context) => Navigator.of(context).pushNamed(Routes.rescan), + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + NodeHeaderListRow( + title: S.of(context).add_new_node, + onTap: (_) async => await Navigator.of(context).pushNamed(Routes.newNode), + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + SizedBox(height: 100), + Observer( + builder: (BuildContext context) { + return Flexible( + child: SectionStandardList( + sectionCount: 1, + context: context, + dividerPadding: EdgeInsets.symmetric(horizontal: 24), + itemCounter: (int sectionIndex) { + return nodeListViewModel.nodes.length; + }, + itemBuilder: (_, sectionIndex, index) { + final node = nodeListViewModel.nodes[index]; + final isSelected = node.keyIndex == nodeListViewModel.currentNode.keyIndex; + final nodeListRow = NodeListRow( + title: node.uriRaw, + isSelected: isSelected, + isAlive: node.requestNode(), + onTap: (_) async { + if (isSelected) { + return; + } + + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).change_current_node_title, + alertContent: S.of(context).change_current_node(node.uriRaw), + leftButtonText: S.of(context).cancel, + rightButtonText: S.of(context).change, + actionLeftButton: () => Navigator.of(context).pop(), + actionRightButton: () async { + await nodeListViewModel.setAsCurrent(node); + Navigator.of(context).pop(); + }, + ); + }); + }, + ); + + final dismissibleRow = Slidable( + key: Key('${node.keyIndex}'), + startActionPane: _actionPane(context, node), + endActionPane: _actionPane(context, node), + child: nodeListRow, + ); + + return isSelected ? nodeListRow : dismissibleRow; + }, + ), + ); + }, + ), + ], + ), + ); + } + + Future _presentReconnectAlert(BuildContext context) async { + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).reconnection, + alertContent: S.of(context).reconnect_alert_text, + rightButtonText: S.of(context).ok, + leftButtonText: S.of(context).cancel, + actionRightButton: () async { + Navigator.of(context).pop(); + await dashboardViewModel.reconnect(); + }, + actionLeftButton: () => Navigator.of(context).pop()); + }, + ); + } + + ActionPane _actionPane(BuildContext context, Node node) => ActionPane( + motion: const ScrollMotion(), + extentRatio: 0.3, + children: [ + SlidableAction( + onPressed: (context) async { + final confirmed = await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).remove_node, + alertContent: S.of(context).remove_node_message, + rightButtonText: S.of(context).remove, + leftButtonText: S.of(context).cancel, + actionRightButton: () => Navigator.pop(context, true), + actionLeftButton: () => Navigator.pop(context, false)); + }) ?? + false; + + if (confirmed) { + await nodeListViewModel.delete(node); + } + }, + backgroundColor: Colors.red, + foregroundColor: Colors.white, + icon: CupertinoIcons.delete, + label: S.of(context).delete, + ), + ], + ); +} diff --git a/lib/src/screens/settings/display_settings_page.dart b/lib/src/screens/settings/display_settings_page.dart new file mode 100644 index 000000000..a5a855b59 --- /dev/null +++ b/lib/src/screens/settings/display_settings_page.dart @@ -0,0 +1,80 @@ +import 'package:cake_wallet/entities/fiat_currency.dart'; +import 'package:cake_wallet/entities/language_service.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:cake_wallet/themes/theme_list.dart'; +import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; +import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; +import 'package:cake_wallet/wallet_type_utils.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class DisplaySettingsPage extends BasePage { + DisplaySettingsPage(this.settingsViewModel); + + @override + String get title => S.current.display_settings; + + final SettingsViewModel settingsViewModel; + + @override + Widget body(BuildContext context) { + return Observer(builder: (_) { + return Container( + padding: EdgeInsets.only(top: 10), + child: Column( + children: [ + SettingsSwitcherCell( + title: S.current.settings_save_recipient_address, + value: settingsViewModel.shouldSaveRecipientAddress, + onValueChange: (BuildContext _, bool value) { + settingsViewModel.setShouldSaveRecipientAddress(value); + }), + if (!isHaven) + SettingsPickerCell( + title: S.current.settings_currency, + searchHintText: S.current.search_currency, + items: FiatCurrency.all, + selectedItem: settingsViewModel.fiatCurrency, + onItemSelected: (FiatCurrency currency) => settingsViewModel.setFiatCurrency(currency), + images: FiatCurrency.all.map((e) => Image.asset("assets/images/flags/${e.countryCode}.png")).toList(), + isGridView: true, + matchingCriteria: (FiatCurrency currency, String searchText) { + return currency.title.toLowerCase().contains(searchText) || + currency.fullName.toLowerCase().contains(searchText); + }, + ), + SettingsPickerCell( + title: S.current.settings_change_language, + searchHintText: S.current.search_language, + items: LanguageService.list.keys.toList(), + displayItem: (dynamic code) { + return LanguageService.list[code] ?? ''; + }, + selectedItem: settingsViewModel.languageCode, + onItemSelected: settingsViewModel.onLanguageSelected, + images: LanguageService.list.keys + .map((e) => Image.asset("assets/images/flags/${LanguageService.localeCountryCode[e]}.png")) + .toList(), + matchingCriteria: (String code, String searchText) { + return LanguageService.list[code]?.toLowerCase().contains(searchText) ?? false; + }, + ), + SettingsChoicesCell( + ChoicesListItem( + title: S.current.color_theme, + items: ThemeList.all, + selectedItem: settingsViewModel.theme, + onItemSelected: (ThemeBase theme) => settingsViewModel.setTheme(theme), + ), + ), + ], + ), + ); + }); + } +} diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart new file mode 100644 index 000000000..7d1ec311d --- /dev/null +++ b/lib/src/screens/settings/other_settings_page.dart @@ -0,0 +1,45 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_version_cell.dart'; +import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class OtherSettingsPage extends BasePage { + OtherSettingsPage(this._settingsViewModel); + + @override + String get title => S.current.other_settings; + + final SettingsViewModel _settingsViewModel; + + @override + Widget body(BuildContext context) { + return Observer(builder: (_) { + return Container( + padding: EdgeInsets.only(top: 10), + child: Column(children: [ + SettingsPickerCell( + title: S.current.settings_fee_priority, + items: priorityForWalletType(_settingsViewModel.walletType), + displayItem: _settingsViewModel.getDisplayPriority, + selectedItem: _settingsViewModel.transactionPriority, + onItemSelected: _settingsViewModel.onDisplayPrioritySelected, + ), + SettingsCellWithArrow( + title: S.current.settings_terms_and_conditions, + handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.readDisclaimer), + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + Spacer(), + SettingsVersionCell(title: S.of(context).version(_settingsViewModel.currentVersion)) + ]), + ); + }); + } +} diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart new file mode 100644 index 000000000..d8518ce3b --- /dev/null +++ b/lib/src/screens/settings/privacy_page.dart @@ -0,0 +1,30 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class PrivacyPage extends BasePage { + PrivacyPage(this.settingsViewModel); + + @override + String get title => S.current.privacy_settings; + + final SettingsViewModel settingsViewModel; + + @override + Widget body(BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 10), + child: Observer(builder: (_) { + return SettingsSwitcherCell( + title: S.current.settings_save_recipient_address, + value: settingsViewModel.shouldSaveRecipientAddress, + onValueChange: (BuildContext _, bool value) { + settingsViewModel.setShouldSaveRecipientAddress(value); + }); + }), + ); + } +} diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart new file mode 100644 index 000000000..d950597f0 --- /dev/null +++ b/lib/src/screens/settings/security_backup_page.dart @@ -0,0 +1,84 @@ +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/auth/auth_page.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class SecurityBackupPage extends BasePage { + SecurityBackupPage(this.settingsViewModel); + + @override + String get title => S.current.security_and_backup; + + final SettingsViewModel settingsViewModel; + + @override + Widget body(BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 10), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + SettingsCellWithArrow( + title: S.current.show_keys, + handler: (_) => Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { + if (isAuthenticatedSuccessfully) { + auth.close(route: Routes.showKeys); + } + }), + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + SettingsCellWithArrow( + title: S.current.create_backup, + handler: (_) => Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { + if (isAuthenticatedSuccessfully) { + auth.close(route: Routes.backup); + } + }), + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + SettingsCellWithArrow( + title: S.current.settings_change_pin, + handler: (_) => Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { + auth.close( + route: isAuthenticatedSuccessfully ? Routes.setupPin : null, + arguments: (PinCodeState setupPinContext, String _) { + setupPinContext.close(); + }, + ); + })), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + Observer(builder: (_) { + return SettingsSwitcherCell( + title: S.current.settings_allow_biometrical_authentication, + value: settingsViewModel.allowBiometricalAuthentication, + onValueChange: (BuildContext context, bool value) { + if (value) { + Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { + if (isAuthenticatedSuccessfully) { + if (await settingsViewModel.biometricAuthenticated()) { + settingsViewModel.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); + } + } else { + settingsViewModel.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); + } + + auth.close(); + }); + } else { + settingsViewModel.setAllowBiometricalAuthentication(value); + } + }); + }), + ]), + ); + } +} diff --git a/lib/src/screens/settings/settings.dart b/lib/src/screens/settings/settings.dart deleted file mode 100644 index 3f6f41e7b..000000000 --- a/lib/src/screens/settings/settings.dart +++ /dev/null @@ -1,98 +0,0 @@ -import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart'; -import 'package:cake_wallet/src/screens/settings/widgets/settings_version_cell.dart'; -import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; -import 'package:cake_wallet/view_model/settings/version_list_item.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; -import 'package:cake_wallet/view_model/settings/link_list_item.dart'; -import 'package:cake_wallet/view_model/settings/picker_list_item.dart'; -import 'package:cake_wallet/view_model/settings/regular_list_item.dart'; -import 'package:cake_wallet/view_model/settings/switcher_list_item.dart'; -import 'package:cake_wallet/src/screens/settings/widgets/settings_link_provider_cell.dart'; -import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; -import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; -import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; -import 'package:cake_wallet/src/widgets/standard_list.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; - -class SettingsPage extends BasePage { - SettingsPage(this.settingsViewModel); - - final SettingsViewModel settingsViewModel; - - @override - String get title => S.current.settings_title; - - @override - Widget body(BuildContext context) { - // FIX-ME: Added `context` it was not used here before, maby bug ? - return SectionStandardList( - context: context, - sectionCount: settingsViewModel.sections.length, - itemCounter: (int sectionIndex) { - if (sectionIndex < settingsViewModel.sections.length) { - return settingsViewModel.sections[sectionIndex].length; - } - - return 0; - }, - itemBuilder: (_, sectionIndex, itemIndex) { - final item = settingsViewModel.sections[sectionIndex][itemIndex]; - - if (item is PickerListItem) { - return Observer(builder: (_) { - return SettingsPickerCell( - displayItem: item.displayItem, - title: item.title, - selectedItem: item.selectedItem(), - items: item.items, - onItemSelected: (dynamic value) => item.onItemSelected(value), - images: item.images, - searchHintText: item.searchHintText, - isGridView: item.isGridView, - matchingCriteria: (dynamic value, String searchText) => item.matchingCriteria(value, searchText), - ); - }); - } - - if (item is SwitcherListItem) { - return Observer(builder: (_) { - return SettingsSwitcherCell( - title: item.title, - value: item.value(), - onValueChange: item.onValueChange); - }); - } - - if (item is RegularListItem) { - return SettingsCellWithArrow( - title: item.title, handler: item.handler); - } - - if (item is LinkListItem) { - return SettingsLinkProviderCell( - title: item.title, - icon: item.icon, - link: item.link, - linkTitle: item.linkTitle); - } - - if (item is VersionListItem) { - return Observer(builder: (_) { - return SettingsVersionCell( - title: - S.of(context).version(settingsViewModel.currentVersion)); - }); - } - - if (item is ChoicesListItem) { - return SettingsChoicesCell(item); - } - - return Container(); - }); - } -} diff --git a/lib/src/widgets/standard_list.dart b/lib/src/widgets/standard_list.dart index ae8978eb4..f5abdd900 100644 --- a/lib/src/widgets/standard_list.dart +++ b/lib/src/widgets/standard_list.dart @@ -123,6 +123,7 @@ class SectionStandardList extends StatelessWidget { required this.itemBuilder, required this.sectionCount, required BuildContext context, + this.dividerPadding = const EdgeInsets.only(left: 24), this.themeColor, this.dividerThemeColor, this.sectionTitleBuilder, @@ -149,6 +150,7 @@ class SectionStandardList extends StatelessWidget { final List totalRows; final Color? themeColor; final Color? dividerThemeColor; + final EdgeInsets dividerPadding; List transform( bool hasTopSeparator, @@ -178,7 +180,7 @@ class SectionStandardList extends StatelessWidget { items.add(sectionIndex + 1 != sectionCount ? SectionHeaderListRow() - : StandardListSeparator(padding: EdgeInsets.only(left: 24))); + : StandardListSeparator(padding: dividerPadding)); } return items; diff --git a/lib/view_model/settings/settings_view_model.dart b/lib/view_model/settings/settings_view_model.dart index aabe51ef1..bf870af2e 100644 --- a/lib/view_model/settings/settings_view_model.dart +++ b/lib/view_model/settings/settings_view_model.dart @@ -1,11 +1,6 @@ -import 'package:cake_wallet/entities/language_service.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; -import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; -import 'package:flutter/cupertino.dart'; import 'package:mobx/mobx.dart'; import 'package:package_info/package_info.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/generated/i18n.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/entities/biometric_auth.dart'; @@ -16,21 +11,12 @@ import 'package:cw_core/node.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/haven/haven.dart'; import 'package:cake_wallet/entities/action_list_display_mode.dart'; -import 'package:cake_wallet/view_model/settings/version_list_item.dart'; -import 'package:cake_wallet/view_model/settings/picker_list_item.dart'; -import 'package:cake_wallet/view_model/settings/regular_list_item.dart'; -import 'package:cake_wallet/view_model/settings/settings_list_item.dart'; -import 'package:cake_wallet/view_model/settings/switcher_list_item.dart'; -import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/themes/theme_base.dart'; -import 'package:cake_wallet/themes/theme_list.dart'; -import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; -import 'package:cake_wallet/wallet_type_utils.dart'; part 'settings_view_model.g.dart'; @@ -59,9 +45,9 @@ abstract class SettingsViewModelBase with Store { TransactionInfo> wallet) : itemHeaders = {}, - _walletType = wallet.type, + walletType = wallet.type, + _wallet = wallet, _biometricAuth = BiometricAuth(), - sections = >[], currentVersion = '' { PackageInfo.fromPlatform().then( (PackageInfo packageInfo) => currentVersion = packageInfo.version); @@ -97,171 +83,30 @@ abstract class SettingsViewModelBase with Store { // createNewYatUrl += '?sub1=' + createNewYatUrlParameters; //} - - sections = [ - [ - SwitcherListItem( - title: S.current.settings_display_balance, - value: () => balanceDisplayMode == BalanceDisplayMode.displayableBalance, - onValueChange: (_, bool value) { - if (value) { - _settingsStore.balanceDisplayMode = BalanceDisplayMode.displayableBalance; - } else { - _settingsStore.balanceDisplayMode = BalanceDisplayMode.hiddenBalance; - } - }, - ), - if (!isHaven) - PickerListItem( - title: S.current.settings_currency, - searchHintText: S.current.search_currency, - items: FiatCurrency.all, - selectedItem: () => fiatCurrency, - onItemSelected: (FiatCurrency currency) => - setFiatCurrency(currency), - images: FiatCurrency.all.map( - (e) => Image.asset("assets/images/flags/${e.countryCode}.png")) - .toList(), - isGridView: true, - matchingCriteria: (FiatCurrency currency, String searchText) { - return currency.title.toLowerCase().contains(searchText) || currency.fullName.toLowerCase().contains(searchText); - }, - ), - PickerListItem( - title: S.current.settings_fee_priority, - items: priorityForWalletType(wallet.type), - displayItem: (dynamic priority) { - final _priority = priority as TransactionPriority; - - if (wallet.type == WalletType.bitcoin - || wallet.type == WalletType.litecoin) { - final rate = bitcoin!.getFeeRate(wallet, _priority); - return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); - } - - return priority.toString(); - }, - selectedItem: () => transactionPriority, - onItemSelected: (TransactionPriority priority) => - _settingsStore.priority[wallet.type] = priority), - SwitcherListItem( - title: S.current.settings_save_recipient_address, - value: () => shouldSaveRecipientAddress, - onValueChange: (_, bool value) => - setShouldSaveRecipientAddress(value)) - ], - [ - RegularListItem( - title: S.current.settings_change_pin, - handler: (BuildContext context) { - Navigator.of(context).pushNamed(Routes.auth, arguments: - (bool isAuthenticatedSuccessfully, AuthPageState auth) { - auth.close( - route: isAuthenticatedSuccessfully ? Routes.setupPin : null, - arguments: (PinCodeState setupPinContext, - String _) { - setupPinContext.close(); - }, - ); - }); - }), - PickerListItem( - title: S.current.settings_change_language, - searchHintText: S.current.search_language, - items: LanguageService.list.keys.toList(), - displayItem: (dynamic code) { - return LanguageService.list[code] ?? ''; - }, - selectedItem: () => _settingsStore.languageCode, - onItemSelected: (String code) { - _settingsStore.languageCode = code; - }, - images: LanguageService.list.keys.map( - (e) => Image.asset("assets/images/flags/${LanguageService.localeCountryCode[e]}.png")) - .toList(), - matchingCriteria: (String code, String searchText) { - return LanguageService.list[code]?.toLowerCase().contains(searchText) ?? false; - }, - ), - SwitcherListItem( - title: S.current.settings_allow_biometrical_authentication, - value: () => allowBiometricalAuthentication, - onValueChange: (BuildContext context, bool value) { - if (value) { - Navigator.of(context).pushNamed(Routes.auth, arguments: - (bool isAuthenticatedSuccessfully, - AuthPageState auth) async { - if (isAuthenticatedSuccessfully) { - if (await _biometricAuth.canCheckBiometrics() && - await _biometricAuth.isAuthenticated()) { - setAllowBiometricalAuthentication( - isAuthenticatedSuccessfully); - } - } else { - setAllowBiometricalAuthentication( - isAuthenticatedSuccessfully); - } - - auth.close(); - }); - } else { - setAllowBiometricalAuthentication(value); - } - }), - ChoicesListItem( - title: S.current.color_theme, - items: ThemeList.all, - selectedItem: theme, - onItemSelected: (ThemeBase theme) => _settingsStore.currentTheme = theme, - ), - ], - //[ - //if (_yatStore.emoji.isNotEmpty) ...[ - // LinkListItem( - // title: S.current.manage_yats, - // link: manageYatUrl, - // linkTitle: ''), - //] else ...[ - //LinkListItem( - // title: S.current.connect_yats, - // link: connectYatUrl, - // linkTitle: ''), - //LinkListItem( - // title: 'Create new Yats', - // link: createNewYatUrl, - // linkTitle: '') - //] - //], - [ - RegularListItem( - title: S.current.settings_terms_and_conditions, - handler: (BuildContext context) => - Navigator.of(context).pushNamed(Routes.readDisclaimer), - ) - ], - [VersionListItem(title: currentVersion)] - ]; } @observable String currentVersion; @computed - Node get node => _settingsStore.getCurrentNode(_walletType); + Node get node => _settingsStore.getCurrentNode(walletType); @computed FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency; + @computed + String get languageCode => _settingsStore.languageCode; + @computed ObservableList get actionlistDisplayMode => _settingsStore.actionlistDisplayMode; @computed TransactionPriority get transactionPriority { - final priority = _settingsStore.priority[_walletType]; + final priority = _settingsStore.priority[walletType]; if (priority == null) { - throw Exception('Unexpected type ${_walletType.toString()}'); + throw Exception('Unexpected type ${walletType.toString()}'); } return priority; @@ -285,11 +130,12 @@ abstract class SettingsViewModelBase with Store { bool get isBitcoinBuyEnabled => _settingsStore.isBitcoinBuyEnabled; final Map itemHeaders; - List> sections; final SettingsStore _settingsStore; final YatStore _yatStore; - final WalletType _walletType; + final WalletType walletType; final BiometricAuth _biometricAuth; + final WalletBase, + TransactionInfo> _wallet; @action void setBalanceDisplayMode(BalanceDisplayMode value) => @@ -333,4 +179,35 @@ abstract class SettingsViewModelBase with Store { @action void _showTrades() => actionlistDisplayMode.add(ActionListDisplayMode.trades); + + @action + Future biometricAuthenticated()async{ + return await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated(); + } + + @action + void onLanguageSelected (String code) { + _settingsStore.languageCode = code; + } + + @action + void setTheme(ThemeBase newTheme){ + _settingsStore.currentTheme = newTheme; + } + + String getDisplayPriority(TransactionPriority priority) { + final _priority = priority; + + if (_wallet.type == WalletType.bitcoin + || _wallet.type == WalletType.litecoin) { + final rate = bitcoin!.getFeeRate(_wallet, _priority); + return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); + } + + return priority.toString(); + } + + void onDisplayPrioritySelected(TransactionPriority priority) => + _settingsStore.priority[_wallet.type] = priority; + } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 685d817d5..cea889b15 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -651,5 +651,9 @@ "ignor": "Ignorieren", "use_suggested": "Vorgeschlagen verwenden", "do_not_share_warning_text" : "Teilen Sie diese nicht mit anderen, einschließlich des Supports.\n\nSie werden Ihr Geld stehlen!", - "help": "hilfe" + "help": "hilfe", + "privacy_settings": "Datenschutzeinstellungen", + "privacy": "Datenschutz", + "display_settings": "Anzeigeeinstellungen", + "other_settings": "Andere Einstellungen" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 877d09231..e764a0b90 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -651,5 +651,12 @@ "ignor": "Ignore", "use_suggested": "Use Suggested", "do_not_share_warning_text" : "Do not share these with anyone else, including support.\n\nThey will steal your money!", - "help": "help" + "help": "help", + "connection_sync": "Connection and sync", + "security_and_backup": "Security and backup", + "create_backup": "Create backup", + "privacy_settings": "Privacy settings", + "privacy": "Privacy", + "display_settings": "Display settings", + "other_settings": "Other settings" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 505f3ffa8..bd43abe58 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -651,5 +651,9 @@ "ignor": "Pasar por alto", "use_suggested": "Usar sugerido", "do_not_share_warning_text" : "No comparta estos con nadie más, incluido el soporte.\n\n¡Te robarán tu dinero!", - "help": "ayuda" + "help": "ayuda", + "privacy_settings": "Configuración de privacidad", + "privacy": "Privacidad", + "display_settings": "Configuración de pantalla", + "other_settings": "Otras configuraciones" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 941016c0b..df43f41a6 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -649,5 +649,9 @@ "ignor": "Ignorer", "use_suggested": "Utilisation suggérée", "do_not_share_warning_text" : "Ne les partagez avec personne d'autre, y compris avec l'assistance.\n\nIls vont voler votre argent!", - "help": "aider" + "help": "aider", + "privacy_settings": "Paramètres de confidentialité", + "privacy": "Confidentialité", + "display_settings": "Paramètres d'affichage", + "other_settings": "Autres paramètres" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 7faa06f7f..06d95d3b2 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -651,5 +651,9 @@ "ignor": "नज़रअंदाज़ करना", "use_suggested": "सुझाए गए का प्रयोग करें", "do_not_share_warning_text" : "इन्हें समर्थन सहित किसी और के साथ साझा न करें।\n\nवे आपका पैसा चुरा लेंगे!", - "help": "मदद करना" + "help": "मदद करना", + "privacy_settings": "गोपनीयता सेटिंग्स", + "privacy": "गोपनीयता", + "display_settings": "प्रदर्शन सेटिंग्स", + "other_settings": "अन्य सेटिंग्स" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 4fa77948a..7c25928e5 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -651,5 +651,9 @@ "ignor": "Zanemariti", "use_suggested": "Koristite predloženo", "do_not_share_warning_text" : "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nUkrast će vam novac!", - "help": "pomozite" + "help": "pomozite", + "privacy_settings": "Postavke privatnosti", + "privacy": "Privatnost", + "display_settings": "Postavke zaslona", + "other_settings": "Ostale postavke" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 9a42a588b..45d9d8164 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -651,5 +651,9 @@ "ignor": "Ignorare", "use_suggested": "Usa suggerito", "do_not_share_warning_text" : "Non condividerli con nessun altro, incluso il supporto.\n\nTi ruberanno i soldi!", - "help": "aiuto" + "help": "aiuto", + "privacy_settings": "Impostazioni privacy", + "privacy": "Privacy", + "display_settings": "Impostazioni di visualizzazione", + "other_settings": "Altre impostazioni" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index c1d0de4e3..ffb2cbb71 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -651,5 +651,9 @@ "ignor": "無視", "use_suggested": "推奨を使用", "do_not_share_warning_text" : "サポートを含め、これらを他の誰とも共有しないでください。\n\n彼らはあなたのお金を盗みます!", - "help": "ヘルプ" + "help": "ヘルプ", + "privacy_settings": "プライバシー設定", + "privacy": "プライバシー", + "display_settings": "表示設定", + "other_settings": "その他の設定" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 127aa949e..598fe2f56 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -651,5 +651,9 @@ "ignor": "무시하다", "use_suggested": "추천 사용", "do_not_share_warning_text" : "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n그들은 당신의 돈을 훔칠 것입니다!", - "help": "돕다" + "help": "돕다", + "privacy_settings": "개인정보 설정", + "privacy": "프라이버시", + "display_settings": "디스플레이 설정", + "other_settings": "기타 설정" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index fa748b552..12e2f5569 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -651,5 +651,9 @@ "ignor": "Negeren", "use_suggested": "Gebruik aanbevolen", "do_not_share_warning_text" : "Deel deze met niemand anders, ook niet met support.\n\nZe zullen je geld stelen!", - "help": "helpen" + "help": "helpen", + "privacy_settings": "Privacy-instellingen", + "privacy": "Privacy", + "display_settings": "Weergave-instellingen", + "other_settings": "Andere instellingen" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 454fe9717..fd092d332 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -651,5 +651,9 @@ "ignor": "Ignorować", "use_suggested": "Użyj sugerowane", "do_not_share_warning_text" : "Nie udostępniaj ich nikomu innemu, w tym wsparcia.\n\nUkradną twoje pieniądze!", - "help": "pomoc" + "help": "pomoc", + "privacy_settings": "Ustawienia prywatności", + "privacy": "Prywatność", + "display_settings": "Ustawienia wyświetlania", + "other_settings": "Inne ustawienia" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 04a0a3ff2..e4d7ef647 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -651,5 +651,9 @@ "ignor": "Ignorar", "use_suggested": "Uso sugerido", "do_not_share_warning_text" : "Não os compartilhe com mais ninguém, incluindo suporte.\n\nEles vão roubar seu dinheiro!", - "help": "ajuda" + "help": "ajuda", + "privacy_settings": "Configurações de privacidade", + "privacy": "Privacidade", + "display_settings": "Configurações de exibição", + "other_settings": "Outras configurações" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 632b0990c..786f11e36 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -651,5 +651,9 @@ "ignor": "Игнорировать", "use_suggested": "Использовать предложенный", "do_not_share_warning_text" : "Не делитесь ими с кем-либо еще, в том числе со службой поддержки.\n\nОни украдут ваши деньги!", - "help": "помощь" + "help": "помощь", + "privacy_settings": "Настройки конфиденциальности", + "privacy": "Конфиденциальность", + "display_settings": "Настройки отображения", + "other_settings": "Другие настройки" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 5e0f0d18a..48951e806 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -650,5 +650,10 @@ "ignor": "Ігнорувати", "use_suggested": "Використати запропоноване", "do_not_share_warning_text" : "Не повідомляйте їх нікому, включно зі службою підтримки.\n\nВони вкрадуть ваші гроші!", - "help": "допомога" + "help": "допомога", + "privacy_settings": "Налаштування конфіденційності", + "privacy": "Конфіденційність", + "display_settings": "Налаштування дисплея", + "other_settings": "Інші налаштування" + } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index c46d07d59..29d7351d5 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -649,5 +649,9 @@ "ignor": "忽视", "use_suggested": "使用建议", "do_not_share_warning_text" : "不要與其他任何人分享這些內容,包括支持。\n\n他們會偷你的錢!", - "help": "帮助" + "help": "帮助", + "privacy_settings": "隐私设置", + "privacy":"隐私", + "display_settings": "显示设置", + "other_settings": "其他设置" } From 91d7e87334d9374904c0bf3098510a8c5c20d1a2 Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 16 Nov 2022 23:31:42 +0200 Subject: [PATCH 035/203] fix gift card filter colors --- lib/src/screens/ionia/cards/ionia_manage_cards_page.dart | 2 +- lib/src/screens/ionia/widgets/ionia_filter_modal.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart b/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart index 2fbb1d57d..1c13f7a88 100644 --- a/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart +++ b/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart @@ -118,7 +118,7 @@ class IoniaManageCardsPage extends BasePage { width: 32, padding: EdgeInsets.all(8), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.15), + color: Theme.of(context).textTheme!.headline6!.backgroundColor!, border: Border.all( color: Colors.white.withOpacity(0.2), ), diff --git a/lib/src/screens/ionia/widgets/ionia_filter_modal.dart b/lib/src/screens/ionia/widgets/ionia_filter_modal.dart index ec6e84cc0..2b885f736 100644 --- a/lib/src/screens/ionia/widgets/ionia_filter_modal.dart +++ b/lib/src/screens/ionia/widgets/ionia_filter_modal.dart @@ -20,7 +20,7 @@ class IoniaFilterModal extends StatelessWidget { padding: EdgeInsets.all(10), child: Image.asset( 'assets/images/mini_search_icon.png', - color: Theme.of(context).accentColor, + color: Theme.of(context).textTheme.subtitle2!.color!, ), ); return Scaffold( @@ -53,7 +53,7 @@ class IoniaFilterModal extends StatelessWidget { prefixIcon: searchIcon, hintText: S.of(context).search_category, contentPadding: EdgeInsets.only(bottom: 5), - fillColor: Theme.of(context).textTheme!.subtitle1!.backgroundColor!, + fillColor: Theme.of(context).primaryTextTheme!.caption!.decorationColor!.withOpacity(0.5), border: OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.circular(8), From a82803de3ae6902cd94b0ec0348d5726404cb62a Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 18 Nov 2022 20:32:52 +0200 Subject: [PATCH 036/203] Fix Casting issue --- lib/view_model/settings/settings_view_model.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/view_model/settings/settings_view_model.dart b/lib/view_model/settings/settings_view_model.dart index bf870af2e..359ebfaf5 100644 --- a/lib/view_model/settings/settings_view_model.dart +++ b/lib/view_model/settings/settings_view_model.dart @@ -180,7 +180,7 @@ abstract class SettingsViewModelBase with Store { @action void _showTrades() => actionlistDisplayMode.add(ActionListDisplayMode.trades); - @action + @action Future biometricAuthenticated()async{ return await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated(); } @@ -195,8 +195,8 @@ abstract class SettingsViewModelBase with Store { _settingsStore.currentTheme = newTheme; } - String getDisplayPriority(TransactionPriority priority) { - final _priority = priority; + String getDisplayPriority(dynamic priority) { + final _priority = priority as TransactionPriority; if (_wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin) { From c67e8c5037e4aafea5da830db30dd68a5dd85b89 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Fri, 18 Nov 2022 20:53:35 +0200 Subject: [PATCH 037/203] [CW-233] Fix missing display balance setting --- lib/di.dart | 8 ++++---- lib/router.dart | 8 ++++---- lib/src/screens/dashboard/dashboard_page.dart | 2 +- lib/src/screens/settings/display_settings_page.dart | 10 +++++----- lib/src/screens/settings/other_settings_page.dart | 2 +- lib/view_model/settings/settings_view_model.dart | 12 ++++++++++++ 6 files changed, 27 insertions(+), 15 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index 265a5036b..815a3740e 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -5,10 +5,10 @@ import 'package:cake_wallet/ionia/ionia_anypay.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/ionia/ionia_tip.dart'; import 'package:cake_wallet/src/screens/buy/onramper_page.dart'; -import 'package:cake_wallet/src/screens/setting/display_settings_page.dart'; -import 'package:cake_wallet/src/screens/setting/other_settings_page.dart'; -import 'package:cake_wallet/src/screens/setting/privacy_page.dart'; -import 'package:cake_wallet/src/screens/setting/security_backup_page.dart'; +import 'package:cake_wallet/src/screens/settings/display_settings_page.dart'; +import 'package:cake_wallet/src/screens/settings/other_settings_page.dart'; +import 'package:cake_wallet/src/screens/settings/privacy_page.dart'; +import 'package:cake_wallet/src/screens/settings/security_backup_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; diff --git a/lib/router.dart b/lib/router.dart index e35ba19ef..7818cc52f 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -5,10 +5,10 @@ import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart'; import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart'; import 'package:cake_wallet/src/screens/buy/onramper_page.dart'; import 'package:cake_wallet/src/screens/buy/pre_order_page.dart'; -import 'package:cake_wallet/src/screens/setting/display_settings_page.dart'; -import 'package:cake_wallet/src/screens/setting/other_settings_page.dart'; -import 'package:cake_wallet/src/screens/setting/privacy_page.dart'; -import 'package:cake_wallet/src/screens/setting/security_backup_page.dart'; +import 'package:cake_wallet/src/screens/settings/display_settings_page.dart'; +import 'package:cake_wallet/src/screens/settings/other_settings_page.dart'; +import 'package:cake_wallet/src/screens/settings/privacy_page.dart'; +import 'package:cake_wallet/src/screens/settings/security_backup_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_cards_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dart'; diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index f3d5a21fb..cb90bb8e0 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -60,7 +60,7 @@ class DashboardPage extends BasePage { Widget middle(BuildContext context) { return SyncIndicator(dashboardViewModel: walletViewModel, onTap: () => Navigator.of(context, rootNavigator: true) - .pushNamed(Routes.nodeList)); + .pushNamed(Routes.connectionSync)); } @override diff --git a/lib/src/screens/settings/display_settings_page.dart b/lib/src/screens/settings/display_settings_page.dart index a5a855b59..0c18ce09a 100644 --- a/lib/src/screens/settings/display_settings_page.dart +++ b/lib/src/screens/settings/display_settings_page.dart @@ -29,11 +29,11 @@ class DisplaySettingsPage extends BasePage { child: Column( children: [ SettingsSwitcherCell( - title: S.current.settings_save_recipient_address, - value: settingsViewModel.shouldSaveRecipientAddress, - onValueChange: (BuildContext _, bool value) { - settingsViewModel.setShouldSaveRecipientAddress(value); - }), + title: S.current.settings_display_balance, + value: settingsViewModel.shouldDisplayBalance, + onValueChange: (_, bool value) { + settingsViewModel.setShouldDisplayBalance(value); + }), if (!isHaven) SettingsPickerCell( title: S.current.settings_currency, diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart index 7d1ec311d..65d976708 100644 --- a/lib/src/screens/settings/other_settings_page.dart +++ b/lib/src/screens/settings/other_settings_page.dart @@ -24,7 +24,7 @@ class OtherSettingsPage extends BasePage { return Container( padding: EdgeInsets.only(top: 10), child: Column(children: [ - SettingsPickerCell( + SettingsPickerCell( title: S.current.settings_fee_priority, items: priorityForWalletType(_settingsViewModel.walletType), displayItem: _settingsViewModel.getDisplayPriority, diff --git a/lib/view_model/settings/settings_view_model.dart b/lib/view_model/settings/settings_view_model.dart index 359ebfaf5..9caacb211 100644 --- a/lib/view_model/settings/settings_view_model.dart +++ b/lib/view_model/settings/settings_view_model.dart @@ -116,6 +116,9 @@ abstract class SettingsViewModelBase with Store { BalanceDisplayMode get balanceDisplayMode => _settingsStore.balanceDisplayMode; + @computed + bool get shouldDisplayBalance => balanceDisplayMode == BalanceDisplayMode.displayableBalance; + @computed bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress; @@ -195,6 +198,15 @@ abstract class SettingsViewModelBase with Store { _settingsStore.currentTheme = newTheme; } + @action + void setShouldDisplayBalance(bool value){ + if (value) { + _settingsStore.balanceDisplayMode = BalanceDisplayMode.displayableBalance; + } else { + _settingsStore.balanceDisplayMode = BalanceDisplayMode.hiddenBalance; + } + } + String getDisplayPriority(dynamic priority) { final _priority = priority as TransactionPriority; From 196187255fcd731decee29ce1d34dd321250840e Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 21 Nov 2022 21:09:00 +0200 Subject: [PATCH 038/203] refactoring mapFromInt static variable --- cw_core/lib/crypto_currency.dart | 74 +++----------------------------- 1 file changed, 7 insertions(+), 67 deletions(-) diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index 446c667fd..b483f8aa5 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -137,71 +137,11 @@ class CryptoCurrency extends EnumerableItem with Serializable { static const uni = CryptoCurrency(title: 'UNI', iconPath: 'assets/images/uni_icon.png', tag: 'ETH', raw: 61); static const stx = CryptoCurrency(title: 'STX', iconPath: 'assets/images/stx_icon.png', raw: 62); - static const mapFromInt = { - 0: CryptoCurrency.xmr, - 1: CryptoCurrency.ada, - 2: CryptoCurrency.bch, - 3: CryptoCurrency.bnb, - 4: CryptoCurrency.btc, - 5: CryptoCurrency.dai, - 6: CryptoCurrency.dash, - 7: CryptoCurrency.eos, - 8: CryptoCurrency.eth, - 9: CryptoCurrency.ltc, - 10: CryptoCurrency.nano, - 11: CryptoCurrency.trx, - 12: CryptoCurrency.usdt, - 13: CryptoCurrency.usdterc20, - 14: CryptoCurrency.xlm, - 15: CryptoCurrency.xrp, - 16: CryptoCurrency.xhv, - 17: CryptoCurrency.xag, - 18: CryptoCurrency.xau, - 19: CryptoCurrency.xaud, - 20: CryptoCurrency.xbtc, - 21: CryptoCurrency.xcad, - 22: CryptoCurrency.xchf, - 23: CryptoCurrency.xcny, - 24: CryptoCurrency.xeur, - 25: CryptoCurrency.xgbp, - 26: CryptoCurrency.xjpy, - 27: CryptoCurrency.xnok, - 28: CryptoCurrency.xnzd, - 29: CryptoCurrency.xusd, - 30: CryptoCurrency.ape, - 31: CryptoCurrency.avaxc, - 32: CryptoCurrency.btt, - 33: CryptoCurrency.bttbsc, - 34: CryptoCurrency.doge, - 35: CryptoCurrency.firo, - 36: CryptoCurrency.usdttrc20, - 37: CryptoCurrency.hbar, - 38: CryptoCurrency.sc, - 39: CryptoCurrency.sol, - 40: CryptoCurrency.usdc, - 41: CryptoCurrency.usdcsol, - 42: CryptoCurrency.zaddr, - 43: CryptoCurrency.zec, - 44: CryptoCurrency.zen, - 45: CryptoCurrency.xvg, - 46: CryptoCurrency.usdcpoly, - 47: CryptoCurrency.dcr, - 48: CryptoCurrency.husd, - 49: CryptoCurrency.kmd, - 50: CryptoCurrency.mana, - 51: CryptoCurrency.maticpoly, - 52: CryptoCurrency.matic, - 53: CryptoCurrency.mkr, - 54: CryptoCurrency.near, - 55: CryptoCurrency.oxt, - 56: CryptoCurrency.paxg, - 57: CryptoCurrency.pivx, - 58: CryptoCurrency.rune, - 59: CryptoCurrency.rvn, - 60: CryptoCurrency.scrt, - 61: CryptoCurrency.uni, - 62: CryptoCurrency.stx - }; + static Map rawCurrencyMap = + all.fold>({}, (acc, item) { + acc.addAll({item.raw: item}); + return acc; + }); static const mapFromString = { 'xmr': CryptoCurrency.xmr, @@ -271,11 +211,11 @@ class CryptoCurrency extends EnumerableItem with Serializable { static CryptoCurrency deserialize({required int raw}) { - if (CryptoCurrency.mapFromInt[raw] == null) { + if (CryptoCurrency.rawCurrencyMap[raw] == null) { final s = 'Unexpected token: $raw for CryptoCurrency deserialize'; throw ArgumentError.value(raw, 'raw', s); } - return CryptoCurrency.mapFromInt[raw]!; + return CryptoCurrency.rawCurrencyMap[raw]!; } static CryptoCurrency fromString(String raw) { From 05f1b17a732932ed12b2b93b751acf218160214b Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 21 Nov 2022 22:41:09 +0200 Subject: [PATCH 039/203] fix contact list bug --- lib/router.dart | 2 +- lib/src/screens/contact/contact_list_page.dart | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/router.dart b/lib/router.dart index 8b43fbaf5..9fe22e22d 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -300,7 +300,7 @@ Route createRoute(RouteSettings settings) { case Routes.addressBook: return MaterialPageRoute( builder: (_) => - getIt.get(param1: true, param2: null)); + getIt.get(param1: true)); case Routes.pickerAddressBook: final selectedCurrency = settings.arguments as CryptoCurrency; diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 6d23518b8..8e9de23fd 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -68,7 +68,9 @@ class ContactListPage extends BasePage { contactListViewModel.getWallets(isEditable, selectedCurrency); return Container( padding: EdgeInsets.only(top: 20.0, bottom: 20.0), - child: CollapsibleSectionList( + child: Observer( + builder: (_) { + return CollapsibleSectionList( context: context, sectionCount: 2, themeColor: Theme.of(context).primaryTextTheme.headline6!.color!, @@ -104,7 +106,7 @@ class ContactListPage extends BasePage { child: content, ); }, - ) + );}) ); } From 2db75344802296ad6fe0d68c4bcedc997e9263af Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 22 Nov 2022 00:07:27 +0200 Subject: [PATCH 040/203] small fix --- lib/src/screens/contact/contact_list_page.dart | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 8e9de23fd..7895a1df3 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -62,14 +62,15 @@ class ContactListPage extends BasePage { @override Widget body(BuildContext context) { - final contacts = - contactListViewModel.getContacts(isEditable, selectedCurrency); - final walletContacts = - contactListViewModel.getWallets(isEditable, selectedCurrency); + return Container( padding: EdgeInsets.only(top: 20.0, bottom: 20.0), child: Observer( builder: (_) { + final contacts = + contactListViewModel.getContacts(isEditable, selectedCurrency); + final walletContacts = + contactListViewModel.getWallets(isEditable, selectedCurrency); return CollapsibleSectionList( context: context, sectionCount: 2, From 92328c41029405800f9b18249debef54fbe404ef Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 22 Nov 2022 19:33:24 +0200 Subject: [PATCH 041/203] move logic to viewmodels --- .../screens/exchange_trade/exchange_trade_page.dart | 12 ++++-------- lib/src/screens/send/send_page.dart | 8 ++------ .../exchange/exchange_trade_view_model.dart | 12 ++++++++++++ lib/view_model/send/send_view_model.dart | 10 ++++++++++ 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index 4128fb9f2..001c13ba9 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -381,14 +381,10 @@ class ExchangeTradeState extends State { }); }, actionLeftButton: () => Navigator.of(context).pop(), - feeFiatAmount: widget.disableFiat ? '' - : widget.exchangeTradeViewModel.sendViewModel.pendingTransactionFeeFiatAmount - + ' ' + widget.exchangeTradeViewModel.sendViewModel.fiat.title, - fiatAmountValue: widget.disableFiat ? '' - : widget.exchangeTradeViewModel.sendViewModel - .pendingTransactionFiatAmount + - ' ' + - widget.exchangeTradeViewModel.sendViewModel.fiat.title, + feeFiatAmount: widget.exchangeTradeViewModel + .pendingTransactionFeeFiatAmountFormatted, + fiatAmountValue: widget.exchangeTradeViewModel + .pendingTransactionFiatAmountValueFormatted, outputs: widget.exchangeTradeViewModel.sendViewModel .outputs); }); diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 8815d8c58..b0891c6e5 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -386,14 +386,10 @@ class SendPage extends BasePage { amount: S.of(context).send_amount, amountValue: sendViewModel.pendingTransaction!.amountFormatted, - fiatAmountValue: sendViewModel.balanceViewModel.disableFiat - ? '' : sendViewModel.pendingTransactionFiatAmount + - ' ' + sendViewModel.fiat.title, + fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted, fee: S.of(context).send_fee, feeValue: sendViewModel.pendingTransaction!.feeFormatted, - feeFiatAmount: sendViewModel.balanceViewModel.disableFiat - ? '' : sendViewModel.pendingTransactionFeeFiatAmount + - ' ' + sendViewModel.fiat.title, + feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted, outputs: sendViewModel.outputs, rightButtonText: S.of(context).ok, leftButtonText: S.of(context).cancel, diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index 796397429..133b4a228 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -72,6 +72,18 @@ abstract class ExchangeTradeViewModelBase with Store { ? '\n\n' + S.current.xrp_extra_info : ''; + @computed + String get pendingTransactionFiatAmountValueFormatted => + sendViewModel.balanceViewModel.disableFiat + ? '' : sendViewModel.pendingTransactionFiatAmount + + ' ' + sendViewModel.fiat.title; + + @computed + String get pendingTransactionFeeFiatAmountFormatted => + sendViewModel.balanceViewModel.disableFiat + ? '' : sendViewModel.pendingTransactionFeeFiatAmount + + ' ' + sendViewModel.fiat.title; + @observable ObservableList items; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index cdef6faba..fbfba2313 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -139,6 +139,16 @@ abstract class SendViewModelBase with Store { @computed String get balance => balanceViewModel.availableBalance ?? '0.0'; + @computed + String get pendingTransactionFiatAmountFormatted => + balanceViewModel.disableFiat ? '' : pendingTransactionFiatAmount + + ' ' + fiat.title; + + @computed + String get pendingTransactionFeeFiatAmountFormatted => + balanceViewModel.disableFiat ? '' : pendingTransactionFeeFiatAmount + + ' ' + fiat.title; + @computed bool get isReadyForSend => _wallet.syncStatus is SyncedSyncStatus; From 818a8afe208418136cfa49cdf801be928d0a1d74 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Tue, 22 Nov 2022 22:52:28 +0200 Subject: [PATCH 042/203] [CW-225] Add pin timeout setting --- lib/core/auth_service.dart | 24 +++++++ lib/di.dart | 3 +- lib/entities/pin_code_required_duration.dart | 32 ++++++++++ lib/entities/preferences_key.dart | 3 + .../settings/security_backup_page.dart | 64 ++++++++++++------- .../screens/wallet_list/wallet_list_page.dart | 47 ++++++++++---- lib/store/settings_store.dart | 20 ++++-- lib/view_model/auth_view_model.dart | 12 +++- .../settings/settings_view_model.dart | 30 ++++++--- .../wallet_list/wallet_list_view_model.dart | 6 +- res/values/strings_de.arb | 5 +- res/values/strings_en.arb | 5 +- res/values/strings_es.arb | 5 +- res/values/strings_fr.arb | 5 +- res/values/strings_hi.arb | 5 +- res/values/strings_hr.arb | 5 +- res/values/strings_it.arb | 5 +- res/values/strings_ja.arb | 5 +- res/values/strings_ko.arb | 5 +- res/values/strings_nl.arb | 5 +- res/values/strings_pl.arb | 5 +- res/values/strings_pt.arb | 5 +- res/values/strings_ru.arb | 5 +- res/values/strings_uk.arb | 5 +- res/values/strings_zh.arb | 5 +- 25 files changed, 250 insertions(+), 66 deletions(-) create mode 100644 lib/entities/pin_code_required_duration.dart diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index 2ae37e2b0..6b167fa40 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -4,6 +4,8 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/encrypt.dart'; +import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/store/settings_store.dart'; class AuthService with Store { AuthService({required this.secureStorage, required this.sharedPreferences}); @@ -39,4 +41,26 @@ class AuthService with Store { return decodedPin == pin; } + + void saveLastAuthTime(){ + int timestamp = DateTime.now().millisecondsSinceEpoch; + sharedPreferences.setInt(PreferencesKey.lastAuthTimeMilliseconds, timestamp); + } + + bool requireAuth(){ + final timestamp = sharedPreferences.getInt(PreferencesKey.lastAuthTimeMilliseconds); + final duration = _durationToRequireAuth(timestamp ?? 0); + final requiredPinInterval = getIt.get().pinTimeOutDuration; + + return duration >= requiredPinInterval.value; + } + + int _durationToRequireAuth(int timestamp){ + + DateTime before = DateTime.fromMillisecondsSinceEpoch(timestamp); + DateTime now = DateTime.now(); + Duration timeDifference = now.difference(before); + + return timeDifference.inMinutes; + } } diff --git a/lib/di.dart b/lib/di.dart index 815a3740e..fe8032513 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -440,7 +440,8 @@ Future setup( getIt.registerFactory(() { final appStore = getIt.get(); final yatStore = getIt.get(); - return SettingsViewModel(appStore.settingsStore, yatStore, appStore.wallet!); + final authService = getIt.get(); + return SettingsViewModel(appStore.settingsStore, yatStore, authService, appStore.wallet!); }); getIt diff --git a/lib/entities/pin_code_required_duration.dart b/lib/entities/pin_code_required_duration.dart new file mode 100644 index 000000000..fef5715b5 --- /dev/null +++ b/lib/entities/pin_code_required_duration.dart @@ -0,0 +1,32 @@ +import 'package:cake_wallet/generated/i18n.dart'; + +enum PinCodeRequiredDuration { + always(0), + tenminutes(10), + onehour(60); + + const PinCodeRequiredDuration(this.value); + final int value; + + static PinCodeRequiredDuration deserialize({required int raw}) => + PinCodeRequiredDuration.values.firstWhere((e) => e.value == raw); + + @override + String toString(){ + String label = ''; + switch (this) { + case PinCodeRequiredDuration.always: + label = S.current.always; + break; + case PinCodeRequiredDuration.tenminutes: + label = S.current.minutes_to_pin_code('10'); + break; + case PinCodeRequiredDuration.onehour: + label = S.current.minutes_to_pin_code('60'); + break; + } + return label; + + } + +} \ No newline at end of file diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 6cf7e5608..36394d936 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -23,6 +23,9 @@ class PreferencesKey { static const shouldShowReceiveWarning = 'should_show_receive_warning'; static const shouldShowYatPopup = 'should_show_yat_popup'; static const moneroWalletPasswordUpdateV1Base = 'monero_wallet_update_v1'; + static const pinTimeOutDuration = 'pin_timeout_duration'; + static const lastAuthTimeMilliseconds = 'last_auth_time_milliseconds'; + static String moneroWalletUpdateV1Key(String name) => '${PreferencesKey.moneroWalletPasswordUpdateV1Base}_${name}'; diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index d950597f0..a3babb0bb 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -1,9 +1,11 @@ +import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; @@ -20,27 +22,28 @@ class SecurityBackupPage extends BasePage { @override Widget body(BuildContext context) { + return Container( padding: EdgeInsets.only(top: 10), child: Column(mainAxisSize: MainAxisSize.min, children: [ SettingsCellWithArrow( title: S.current.show_keys, - handler: (_) => Navigator.of(context).pushNamed(Routes.auth, + handler: (_) => settingsViewModel.checkPinCodeRiquired() ? Navigator.of(context).pushNamed(Routes.auth, arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { if (isAuthenticatedSuccessfully) { auth.close(route: Routes.showKeys); } - }), + }) : Navigator.of(context).pushNamed(Routes.showKeys), ), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), SettingsCellWithArrow( title: S.current.create_backup, - handler: (_) => Navigator.of(context).pushNamed(Routes.auth, + handler: (_) => settingsViewModel.checkPinCodeRiquired() ? Navigator.of(context).pushNamed(Routes.auth, arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { if (isAuthenticatedSuccessfully) { auth.close(route: Routes.backup); } - }), + }) : Navigator.of(context).pushNamed(Routes.backup), ), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), SettingsCellWithArrow( @@ -56,28 +59,41 @@ class SecurityBackupPage extends BasePage { })), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), Observer(builder: (_) { - return SettingsSwitcherCell( - title: S.current.settings_allow_biometrical_authentication, - value: settingsViewModel.allowBiometricalAuthentication, - onValueChange: (BuildContext context, bool value) { - if (value) { - Navigator.of(context).pushNamed(Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { - if (isAuthenticatedSuccessfully) { - if (await settingsViewModel.biometricAuthenticated()) { - settingsViewModel.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); - } - } else { - settingsViewModel.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); - } + return Column( + children: [ + SettingsSwitcherCell( + title: S.current.settings_allow_biometrical_authentication, + value: settingsViewModel.allowBiometricalAuthentication, + onValueChange: (BuildContext context, bool value) { + if (value) { + Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { + if (isAuthenticatedSuccessfully) { + if (await settingsViewModel.biometricAuthenticated()) { + settingsViewModel.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); + } + } else { + settingsViewModel.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); + } - auth.close(); - }); - } else { - settingsViewModel.setAllowBiometricalAuthentication(value); - } - }); + auth.close(); + }); + } else { + settingsViewModel.setAllowBiometricalAuthentication(value); + } + }), + SettingsPickerCell( + title: S.current.require_pin_after, + items: PinCodeRequiredDuration.values, + selectedItem: settingsViewModel.pinCodeRequiredDuration, + onItemSelected: (PinCodeRequiredDuration code) { + settingsViewModel.setPinCodeRequiredDuration(code); + }, + ), + ], + ); }), + ]), ); } diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index c1a7ea953..5d9650ef2 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -220,7 +220,8 @@ class WalletListBodyState extends State { } Future _loadWallet(WalletListItem wallet) async { - await Navigator.of(context).pushNamed(Routes.auth, arguments: + if(await widget.walletListViewModel.checkIfAuthRequired()){ + await Navigator.of(context).pushNamed(Routes.auth, arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { if (!isAuthenticatedSuccessfully) { return; @@ -241,17 +242,36 @@ class WalletListBodyState extends State { .wallet_list_failed_to_load(wallet.name, e.toString())); } }); + }else{ + try { + changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name)); + await widget.walletListViewModel.loadWallet(wallet); + hideProgressText(); + Navigator.of(context).pop(); + } catch (e) { + changeProcessText(S + .of(context) + .wallet_list_failed_to_load(wallet.name, e.toString())); + } + } } Future _removeWallet(WalletListItem wallet) async { - await Navigator.of(context).pushNamed(Routes.auth, arguments: + if(widget.walletListViewModel.checkIfAuthRequired()){ + await Navigator.of(context).pushNamed(Routes.auth, arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { if (!isAuthenticatedSuccessfully) { return; } + _onSuccessfulAuth(wallet, auth); + }); + }else{ + _onSuccessfulAuth(wallet, null); + } + } - bool confirmed = false; - + _onSuccessfulAuth(WalletListItem wallet, AuthPageState? auth)async{ + bool confirmed = false; await showPopUp( context: context, builder: (BuildContext context) { @@ -270,18 +290,23 @@ class WalletListBodyState extends State { if (confirmed) { try { - auth.changeProcessText( - S.of(context).wallet_list_removing_wallet(wallet.name)); + auth != null ? + auth.changeProcessText( + S.of(context).wallet_list_removing_wallet(wallet.name)) + : changeProcessText( S.of(context).wallet_list_removing_wallet(wallet.name)); await widget.walletListViewModel.remove(wallet); } catch (e) { - auth.changeProcessText(S - .of(context) - .wallet_list_failed_to_remove(wallet.name, e.toString())); + auth != null ? + auth.changeProcessText( + S.of(context).wallet_list_failed_to_remove(wallet.name, e.toString()), + ) + : changeProcessText( + S.of(context).wallet_list_failed_to_remove(wallet.name, e.toString()), + ); } } - auth.close(); - }); + auth?.close(); } void changeProcessText(String text) { diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 2b3105a34..c6534bcea 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -1,9 +1,9 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/themes/theme_list.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; @@ -17,7 +17,6 @@ import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cw_core/node.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/entities/action_list_display_mode.dart'; -import 'package:cake_wallet/.secrets.g.dart' as secrets; part 'settings_store.g.dart'; @@ -39,6 +38,7 @@ abstract class SettingsStoreBase with Store { required this.shouldShowYatPopup, required this.isBitcoinBuyEnabled, required this.actionlistDisplayMode, + required this.pinTimeOutDuration, TransactionPriority? initialBitcoinTransactionPriority, TransactionPriority? initialMoneroTransactionPriority}) : nodes = ObservableMap.of(nodes), @@ -108,6 +108,11 @@ abstract class SettingsStoreBase with Store { (String languageCode) => sharedPreferences.setString( PreferencesKey.currentLanguageCode, languageCode)); + reaction( + (_) => pinTimeOutDuration, + (PinCodeRequiredDuration pinCodeInterval) => sharedPreferences.setInt( + PreferencesKey.pinTimeOutDuration, pinCodeInterval.value)); + reaction( (_) => balanceDisplayMode, (BalanceDisplayMode mode) => sharedPreferences.setInt( @@ -124,6 +129,7 @@ abstract class SettingsStoreBase with Store { static const defaultPinLength = 4; static const defaultActionsMode = 11; + static const defaultPinCodeTimeOutDuration = 10; @observable FiatCurrency fiatCurrency; @@ -149,6 +155,9 @@ abstract class SettingsStoreBase with Store { @observable int pinCodeLength; + @observable + PinCodeRequiredDuration pinTimeOutDuration; + @computed ThemeData get theme => currentTheme.themeData; @@ -227,13 +236,15 @@ abstract class SettingsStoreBase with Store { : ThemeType.bright.index; final savedTheme = ThemeList.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? - legacyTheme ?? - 0); + legacyTheme); final actionListDisplayMode = ObservableList(); actionListDisplayMode.addAll(deserializeActionlistDisplayModes( sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? defaultActionsMode)); var pinLength = sharedPreferences.getInt(PreferencesKey.currentPinLength); + final pinCodeTimeOutDuration = PinCodeRequiredDuration.deserialize(raw: sharedPreferences.getInt(PreferencesKey.pinTimeOutDuration) + ?? defaultPinCodeTimeOutDuration); + // If no value if (pinLength == null || pinLength == 0) { pinLength = defaultPinLength; @@ -287,6 +298,7 @@ abstract class SettingsStoreBase with Store { initialTheme: savedTheme, actionlistDisplayMode: actionListDisplayMode, initialPinLength: pinLength, + pinTimeOutDuration: pinCodeTimeOutDuration, initialLanguageCode: savedLanguageCode, initialMoneroTransactionPriority: moneroTransactionPriority, initialBitcoinTransactionPriority: bitcoinTransactionPriority, diff --git a/lib/view_model/auth_view_model.dart b/lib/view_model/auth_view_model.dart index 29ef46b47..42201ddab 100644 --- a/lib/view_model/auth_view_model.dart +++ b/lib/view_model/auth_view_model.dart @@ -17,7 +17,9 @@ abstract class AuthViewModelBase with Store { AuthViewModelBase(this._authService, this._sharedPreferences, this._settingsStore, this._biometricAuth) : _failureCounter = 0, - state = InitialExecutionState(); + state = InitialExecutionState(){ + reaction((_) => state, _saveLastAuthTime); + } static const maxFailedLogins = 3; static const banTimeout = 180; // 3 minutes @@ -57,7 +59,7 @@ abstract class AuthViewModelBase with Store { if (isSuccessfulAuthenticated) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - state = ExecutedSuccessfullyState(); + state = ExecutedSuccessfullyState(); _failureCounter = 0; }); } else { @@ -118,4 +120,10 @@ abstract class AuthViewModelBase with Store { state = FailureState(e.toString()); } } + + void _saveLastAuthTime(ExecutionState state){ + if(state is ExecutedSuccessfullyState){ + _authService.saveLastAuthTime(); + } + } } diff --git a/lib/view_model/settings/settings_view_model.dart b/lib/view_model/settings/settings_view_model.dart index 9caacb211..96f11e82e 100644 --- a/lib/view_model/settings/settings_view_model.dart +++ b/lib/view_model/settings/settings_view_model.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/core/auth_service.dart'; +import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:mobx/mobx.dart'; import 'package:package_info/package_info.dart'; @@ -41,6 +43,7 @@ abstract class SettingsViewModelBase with Store { SettingsViewModelBase( this._settingsStore, this._yatStore, + this._authService, WalletBase, TransactionInfo> wallet) @@ -94,6 +97,10 @@ abstract class SettingsViewModelBase with Store { @computed FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency; + @computed + PinCodeRequiredDuration get pinCodeRequiredDuration => + _settingsStore.pinTimeOutDuration; + @computed String get languageCode => _settingsStore.languageCode; @@ -135,6 +142,7 @@ abstract class SettingsViewModelBase with Store { final Map itemHeaders; final SettingsStore _settingsStore; final YatStore _yatStore; + final AuthService _authService; final WalletType walletType; final BiometricAuth _biometricAuth; final WalletBase, @@ -207,19 +215,25 @@ abstract class SettingsViewModelBase with Store { } } + @action + setPinCodeRequiredDuration(PinCodeRequiredDuration duration) => + _settingsStore.pinTimeOutDuration = duration; + String getDisplayPriority(dynamic priority) { - final _priority = priority as TransactionPriority; + final _priority = priority as TransactionPriority; - if (_wallet.type == WalletType.bitcoin - || _wallet.type == WalletType.litecoin) { - final rate = bitcoin!.getFeeRate(_wallet, _priority); - return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); - } + if (_wallet.type == WalletType.bitcoin + || _wallet.type == WalletType.litecoin) { + final rate = bitcoin!.getFeeRate(_wallet, _priority); + return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); + } - return priority.toString(); + return priority.toString(); } void onDisplayPrioritySelected(TransactionPriority priority) => - _settingsStore.priority[_wallet.type] = priority; + _settingsStore.priority[_wallet.type] = priority; + + bool checkPinCodeRiquired() => _authService.requireAuth(); } diff --git a/lib/view_model/wallet_list/wallet_list_view_model.dart b/lib/view_model/wallet_list/wallet_list_view_model.dart index 0bbc68748..50908f24e 100644 --- a/lib/view_model/wallet_list/wallet_list_view_model.dart +++ b/lib/view_model/wallet_list/wallet_list_view_model.dart @@ -1,5 +1,5 @@ +import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/core/wallet_loading_service.dart'; -import 'package:cake_wallet/view_model/wallet_new_vm.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/di.dart'; @@ -55,4 +55,8 @@ abstract class WalletListViewModelBase with Store { info.type == _appStore.wallet!.type, isEnabled: availableWalletTypes.contains(info.type)))); } + + bool checkIfAuthRequired(){ + return getIt.get().requireAuth(); + } } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index cea889b15..eacc8e618 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -655,5 +655,8 @@ "privacy_settings": "Datenschutzeinstellungen", "privacy": "Datenschutz", "display_settings": "Anzeigeeinstellungen", - "other_settings": "Andere Einstellungen" + "other_settings": "Andere Einstellungen", + "require_pin_after": "PIN anfordern nach", + "always": "immer", + "minutes_to_pin_code": "${minute} Minuten" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index e764a0b90..65b72f5c6 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -658,5 +658,8 @@ "privacy_settings": "Privacy settings", "privacy": "Privacy", "display_settings": "Display settings", - "other_settings": "Other settings" + "other_settings": "Other settings", + "require_pin_after": "Require PIN after", + "always": "Always", + "minutes_to_pin_code": "${minute} minutes" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index bd43abe58..903e6c380 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -655,5 +655,8 @@ "privacy_settings": "Configuración de privacidad", "privacy": "Privacidad", "display_settings": "Configuración de pantalla", - "other_settings": "Otras configuraciones" + "other_settings": "Otras configuraciones", + "require_pin_after": "Requerir PIN después de", + "always": "siempre", + "minutes_to_pin_code": "${minute} minutos" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index df43f41a6..d82f1d2de 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -653,5 +653,8 @@ "privacy_settings": "Paramètres de confidentialité", "privacy": "Confidentialité", "display_settings": "Paramètres d'affichage", - "other_settings": "Autres paramètres" + "other_settings": "Autres paramètres", + "require_pin_after": "NIP requis après", + "always": "toujours", + "minutes_to_pin_code": "${minute} minutes" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 06d95d3b2..9175cb17c 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -655,5 +655,8 @@ "privacy_settings": "गोपनीयता सेटिंग्स", "privacy": "गोपनीयता", "display_settings": "प्रदर्शन सेटिंग्स", - "other_settings": "अन्य सेटिंग्स" + "other_settings": "अन्य सेटिंग्स", + "require_pin_after": "इसके बाद पिन आवश्यक है", + "always": "हमेशा", + "minutes_to_pin_code": "${minute} मिनट" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 7c25928e5..e60bedd74 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -655,5 +655,8 @@ "privacy_settings": "Postavke privatnosti", "privacy": "Privatnost", "display_settings": "Postavke zaslona", - "other_settings": "Ostale postavke" + "other_settings": "Ostale postavke", + "require_pin_after": "Zahtijevaj PIN nakon", + "always": "Uvijek", + "minutes_to_pin_code": "${minute} minuta" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 45d9d8164..548c51b22 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -655,5 +655,8 @@ "privacy_settings": "Impostazioni privacy", "privacy": "Privacy", "display_settings": "Impostazioni di visualizzazione", - "other_settings": "Altre impostazioni" + "other_settings": "Altre impostazioni", + "require_pin_after": "Richiedi PIN dopo", + "always": "sempre", + "minutes_to_pin_code": "${minute} minuti" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index ffb2cbb71..7fc1f5105 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -655,5 +655,8 @@ "privacy_settings": "プライバシー設定", "privacy": "プライバシー", "display_settings": "表示設定", - "other_settings": "その他の設定" + "other_settings": "その他の設定", + "require_pin_after": "後に PIN が必要", + "always": "いつも", + "minutes_to_pin_code": "${minute} 分" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 598fe2f56..471d9ed11 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -655,5 +655,8 @@ "privacy_settings": "개인정보 설정", "privacy": "프라이버시", "display_settings": "디스플레이 설정", - "other_settings": "기타 설정" + "other_settings": "기타 설정", + "require_pin_after": "다음 이후에 PIN 필요", + "always": "언제나", + "minutes_to_pin_code": "${minute}분" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 12e2f5569..1eb16e051 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -655,5 +655,8 @@ "privacy_settings": "Privacy-instellingen", "privacy": "Privacy", "display_settings": "Weergave-instellingen", - "other_settings": "Andere instellingen" + "other_settings": "Andere instellingen", + "require_pin_after": "Pincode vereist na", + "always": "altijd", + "minutes_to_pin_code": "${minute} minuten" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index fd092d332..78793c074 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -655,5 +655,8 @@ "privacy_settings": "Ustawienia prywatności", "privacy": "Prywatność", "display_settings": "Ustawienia wyświetlania", - "other_settings": "Inne ustawienia" + "other_settings": "Inne ustawienia", + "require_pin_after": "Wymagaj kodu PIN po", + "always": "zawsze", + "minutes_to_pin_code": "${minute} minut" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index e4d7ef647..e7fc9aa92 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -655,5 +655,8 @@ "privacy_settings": "Configurações de privacidade", "privacy": "Privacidade", "display_settings": "Configurações de exibição", - "other_settings": "Outras configurações" + "other_settings": "Outras configurações", + "require_pin_after": "Exigir PIN após", + "always": "sempre", + "minutes_to_pin_code": "${minute} minutos" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 786f11e36..34fe7a145 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -655,5 +655,8 @@ "privacy_settings": "Настройки конфиденциальности", "privacy": "Конфиденциальность", "display_settings": "Настройки отображения", - "other_settings": "Другие настройки" + "other_settings": "Другие настройки", + "require_pin_after": "Требовать ПИН после", + "always": "всегда", + "minutes_to_pin_code": "${minute} минут" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 48951e806..fab6ed71e 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -654,6 +654,9 @@ "privacy_settings": "Налаштування конфіденційності", "privacy": "Конфіденційність", "display_settings": "Налаштування дисплея", - "other_settings": "Інші налаштування" + "other_settings": "Інші налаштування", + "require_pin_after": "Вимагати PIN після", + "always": "Завжди", + "minutes_to_pin_code": "${minute} хвилин" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 29d7351d5..8f89f7b63 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -653,5 +653,8 @@ "privacy_settings": "隐私设置", "privacy":"隐私", "display_settings": "显示设置", - "other_settings": "其他设置" + "other_settings": "其他设置", + "require_pin_after": "之后需要 PIN", + "always": "总是", + "minutes_to_pin_code": "${minute} 分钟" } From 0fcd72f82136ba3695da14054a750da3a275ed65 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 23 Nov 2022 09:05:47 +0200 Subject: [PATCH 043/203] format indent code --- lib/view_model/settings/settings_view_model.dart | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/view_model/settings/settings_view_model.dart b/lib/view_model/settings/settings_view_model.dart index 9caacb211..7783cd200 100644 --- a/lib/view_model/settings/settings_view_model.dart +++ b/lib/view_model/settings/settings_view_model.dart @@ -208,18 +208,18 @@ abstract class SettingsViewModelBase with Store { } String getDisplayPriority(dynamic priority) { - final _priority = priority as TransactionPriority; + final _priority = priority as TransactionPriority; - if (_wallet.type == WalletType.bitcoin - || _wallet.type == WalletType.litecoin) { - final rate = bitcoin!.getFeeRate(_wallet, _priority); - return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); - } + if (_wallet.type == WalletType.bitcoin + || _wallet.type == WalletType.litecoin) { + final rate = bitcoin!.getFeeRate(_wallet, _priority); + return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); + } - return priority.toString(); + return priority.toString(); } void onDisplayPrioritySelected(TransactionPriority priority) => - _settingsStore.priority[_wallet.type] = priority; + _settingsStore.priority[_wallet.type] = priority; } From d7d3b78905849c9a0ba554940e349ddec7654e5f Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 23 Nov 2022 13:47:02 +0200 Subject: [PATCH 044/203] refactoring mapFomString method --- cw_core/lib/crypto_currency.dart | 218 +++++++----------- .../exchange/widgets/currency_picker.dart | 2 +- ...let_address_edit_or_create_view_model.dart | 2 +- 3 files changed, 82 insertions(+), 140 deletions(-) diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index b483f8aa5..bcefe89f6 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -9,12 +9,14 @@ class CryptoCurrency extends EnumerableItem with Serializable { String title = '', int raw = -1, this.name, + this.fullName, this.iconPath, - this.tag,}) + this.tag}) : super(title: title, raw: raw); - final String? tag; final String? name; + final String? tag; + final String? fullName; final String? iconPath; static const all = [ @@ -70,161 +72,101 @@ class CryptoCurrency extends EnumerableItem with Serializable { CryptoCurrency.stx, ]; - static const xmr = CryptoCurrency(title: 'XMR', iconPath: 'assets/images/monero_icon.png', name: 'Monero', raw: 0); - static const ada = CryptoCurrency(title: 'ADA', iconPath: 'assets/images/ada_icon.png', name: 'Cardano', raw: 1); - static const bch = CryptoCurrency(title: 'BCH', iconPath: 'assets/images/bch_icon.png',name: 'Bitcoin Cash', raw: 2); - static const bnb = CryptoCurrency(title: 'BNB', iconPath: 'assets/images/bnb_icon.png', tag: 'BSC', name: 'Binance Coin', raw: 3); - static const btc = CryptoCurrency(title: 'BTC', iconPath: 'assets/images/btc.png', name: 'Bitcoin', raw: 4); - static const dai = CryptoCurrency(title: 'DAI', iconPath: 'assets/images/dai_icon.png', tag: 'ETH', name: 'Dai', raw: 5); - static const dash = CryptoCurrency(title: 'DASH', iconPath: 'assets/images/dash_icon.png', name: 'Dash', raw: 6); - static const eos = CryptoCurrency(title: 'EOS', iconPath: 'assets/images/eos_icon.png', name: 'EOS', raw: 7); - static const eth = CryptoCurrency(title: 'ETH', iconPath: 'assets/images/eth_icon.png', name: 'Ethereum', raw: 8); - static const ltc = CryptoCurrency(title: 'LTC', iconPath: 'assets/images/litecoin-ltc_icon.png', name: 'Litecoin', raw: 9); - static const nano = CryptoCurrency(title: 'NANO', raw: 10); - static const trx = CryptoCurrency(title: 'TRX', iconPath: 'assets/images/trx_icon.png', name: 'TRON', raw: 11); - static const usdt = CryptoCurrency(title: 'USDT', iconPath: 'assets/images/usdt_icon.png', tag: 'OMNI', name: 'USDT', raw: 12); - static const usdterc20 = CryptoCurrency(title: 'USDT', iconPath: 'assets/images/usdterc20_icon.png', tag: 'ETH', name: 'USDT', raw: 13); - static const xlm = CryptoCurrency(title: 'XLM', iconPath: 'assets/images/xlm_icon.png', name: 'Stellar', raw: 14); - static const xrp = CryptoCurrency(title: 'XRP', iconPath: 'assets/images/xrp_icon.png', name: 'Ripple', raw: 15); - static const xhv = CryptoCurrency(title: 'XHV', iconPath: 'assets/images/xhv_logo.png', name: 'Haven Protocol', raw: 16); + static const xmr = CryptoCurrency(title: 'XMR', iconPath: 'assets/images/monero_icon.png', fullName: 'Monero', raw: 0, name: 'xmr'); + static const ada = CryptoCurrency(title: 'ADA', iconPath: 'assets/images/ada_icon.png', fullName: 'Cardano', raw: 1, name: 'ada'); + static const bch = CryptoCurrency(title: 'BCH', iconPath: 'assets/images/bch_icon.png',fullName: 'Bitcoin Cash', raw: 2, name: 'bch'); + static const bnb = CryptoCurrency(title: 'BNB', iconPath: 'assets/images/bnb_icon.png', tag: 'BSC', fullName: 'Binance Coin', raw: 3, name: 'bnb'); + static const btc = CryptoCurrency(title: 'BTC', iconPath: 'assets/images/btc.png', fullName: 'Bitcoin', raw: 4, name: 'btc'); + static const dai = CryptoCurrency(title: 'DAI', iconPath: 'assets/images/dai_icon.png', tag: 'ETH', fullName: 'Dai', raw: 5, name: 'dai'); + static const dash = CryptoCurrency(title: 'DASH', iconPath: 'assets/images/dash_icon.png', fullName: 'Dash', raw: 6, name: 'dash'); + static const eos = CryptoCurrency(title: 'EOS', iconPath: 'assets/images/eos_icon.png', fullName: 'EOS', raw: 7, name: 'eos'); + static const eth = CryptoCurrency(title: 'ETH', iconPath: 'assets/images/eth_icon.png', fullName: 'Ethereum', raw: 8, name: 'eth'); + static const ltc = CryptoCurrency(title: 'LTC', iconPath: 'assets/images/litecoin-ltc_icon.png', fullName: 'Litecoin', raw: 9, name: 'ltc'); + static const nano = CryptoCurrency(title: 'NANO', raw: 10, name: 'nano'); + static const trx = CryptoCurrency(title: 'TRX', iconPath: 'assets/images/trx_icon.png', fullName: 'TRON', raw: 11, name: 'trx'); + static const usdt = CryptoCurrency(title: 'USDT', iconPath: 'assets/images/usdt_icon.png', tag: 'OMNI', fullName: 'USDT', raw: 12, name: 'usdt'); + static const usdterc20 = CryptoCurrency(title: 'USDT', iconPath: 'assets/images/usdterc20_icon.png', tag: 'ETH', fullName: 'USDT', raw: 13, name: 'usdterc20'); + static const xlm = CryptoCurrency(title: 'XLM', iconPath: 'assets/images/xlm_icon.png', fullName: 'Stellar', raw: 14, name: 'xlm'); + static const xrp = CryptoCurrency(title: 'XRP', iconPath: 'assets/images/xrp_icon.png', fullName: 'Ripple', raw: 15, name: 'xrp'); + static const xhv = CryptoCurrency(title: 'XHV', iconPath: 'assets/images/xhv_logo.png', fullName: 'Haven Protocol', raw: 16, name: 'xhv'); - static const xag = CryptoCurrency(title: 'XAG', tag: 'XHV', raw: 17); - static const xau = CryptoCurrency(title: 'XAU', tag: 'XHV', raw: 18); - static const xaud = CryptoCurrency(title: 'XAUD', tag: 'XHV', raw: 19); - static const xbtc = CryptoCurrency(title: 'XBTC', tag: 'XHV', raw: 20); - static const xcad = CryptoCurrency(title: 'XCAD', tag: 'XHV', raw: 21); - static const xchf = CryptoCurrency(title: 'XCHF', tag: 'XHV', raw: 22); - static const xcny = CryptoCurrency(title: 'XCNY', tag: 'XHV', raw: 23); - static const xeur = CryptoCurrency(title: 'XEUR', tag: 'XHV', raw: 24); - static const xgbp = CryptoCurrency(title: 'XGBP', tag: 'XHV', raw: 25); - static const xjpy = CryptoCurrency(title: 'XJPY', tag: 'XHV', raw: 26); - static const xnok = CryptoCurrency(title: 'XNOK', tag: 'XHV', raw: 27); - static const xnzd = CryptoCurrency(title: 'XNZD', tag: 'XHV', raw: 28); - static const xusd = CryptoCurrency(title: 'XUSD', tag: 'XHV', raw: 29); + static const xag = CryptoCurrency(title: 'XAG', tag: 'XHV', raw: 17, name: 'xag'); + static const xau = CryptoCurrency(title: 'XAU', tag: 'XHV', raw: 18, name: 'xau'); + static const xaud = CryptoCurrency(title: 'XAUD', tag: 'XHV', raw: 19, name: 'xaud'); + static const xbtc = CryptoCurrency(title: 'XBTC', tag: 'XHV', raw: 20, name: 'xbtc'); + static const xcad = CryptoCurrency(title: 'XCAD', tag: 'XHV', raw: 21, name: 'xcad'); + static const xchf = CryptoCurrency(title: 'XCHF', tag: 'XHV', raw: 22, name: 'xchf'); + static const xcny = CryptoCurrency(title: 'XCNY', tag: 'XHV', raw: 23, name: 'xcny'); + static const xeur = CryptoCurrency(title: 'XEUR', tag: 'XHV', raw: 24, name: 'xeur'); + static const xgbp = CryptoCurrency(title: 'XGBP', tag: 'XHV', raw: 25, name: 'xgbp'); + static const xjpy = CryptoCurrency(title: 'XJPY', tag: 'XHV', raw: 26, name: 'xjpy'); + static const xnok = CryptoCurrency(title: 'XNOK', tag: 'XHV', raw: 27, name: 'xnok'); + static const xnzd = CryptoCurrency(title: 'XNZD', tag: 'XHV', raw: 28, name: 'xnzd'); + static const xusd = CryptoCurrency(title: 'XUSD', tag: 'XHV', raw: 29, name: 'xusd'); - static const ape = CryptoCurrency(title: 'APE', iconPath: 'assets/images/ape_icon.png', tag: 'ETH', raw: 30); - static const avaxc = CryptoCurrency(title: 'AVAX', iconPath: 'assets/images/avaxc_icon.png', tag: 'C-CHAIN', raw: 31); - static const btt = CryptoCurrency(title: 'BTT', iconPath: 'assets/images/btt_icon.png', raw: 32); - static const bttbsc = CryptoCurrency(title: 'BTT', iconPath: 'assets/images/bttbsc_icon.png', tag: 'BSC', raw: 33); - static const doge = CryptoCurrency(title: 'DOGE', iconPath: 'assets/images/doge_icon.png', raw: 34); - static const firo = CryptoCurrency(title: 'FIRO', iconPath: 'assets/images/firo_icon.png', raw: 35); - static const usdttrc20 = CryptoCurrency(title: 'USDT', iconPath: 'assets/images/usdttrc20_icon.png', tag: 'TRX', raw: 36); - static const hbar = CryptoCurrency(title: 'HBAR', iconPath: 'assets/images/hbar_icon.png', raw: 37); - static const sc = CryptoCurrency(title: 'SC', iconPath: 'assets/images/sc_icon.png', raw: 38); - static const sol = CryptoCurrency(title: 'SOL', iconPath: 'assets/images/sol_icon.png', raw: 39); - static const usdc = CryptoCurrency(title: 'USDC', iconPath: 'assets/images/usdc_icon.png', tag: 'ETH', raw: 40); - static const usdcsol = CryptoCurrency(title: 'USDC', iconPath: 'assets/images/usdcsol_icon.png', tag: 'SOL', raw: 41); - static const zaddr = CryptoCurrency(title: 'ZZEC', tag: 'ZEC', name: 'Shielded Zcash', iconPath: 'assets/images/zaddr_icon.png', raw: 42); - static const zec = CryptoCurrency(title: 'TZEC', tag: 'ZEC', name: 'Transparent Zcash', iconPath: 'assets/images/zec_icon.png', raw: 43); - static const zen = CryptoCurrency(title: 'ZEN', iconPath: 'assets/images/zen_icon.png', raw: 44); - static const xvg = CryptoCurrency(title: 'XVG', name: 'Verge', iconPath: 'assets/images/xvg_icon.png', raw: 45); + static const ape = CryptoCurrency(title: 'APE', iconPath: 'assets/images/ape_icon.png', tag: 'ETH', raw: 30, name: 'ape'); + static const avaxc = CryptoCurrency(title: 'AVAX', iconPath: 'assets/images/avaxc_icon.png', tag: 'C-CHAIN', raw: 31, name: 'avaxc'); + static const btt = CryptoCurrency(title: 'BTT', iconPath: 'assets/images/btt_icon.png', raw: 32, name: 'btt'); + static const bttbsc = CryptoCurrency(title: 'BTT', iconPath: 'assets/images/bttbsc_icon.png', tag: 'BSC', raw: 33, name: 'bttbsc'); + static const doge = CryptoCurrency(title: 'DOGE', iconPath: 'assets/images/doge_icon.png', raw: 34, name: 'doge'); + static const firo = CryptoCurrency(title: 'FIRO', iconPath: 'assets/images/firo_icon.png', raw: 35, name: 'firo'); + static const usdttrc20 = CryptoCurrency(title: 'USDT', iconPath: 'assets/images/usdttrc20_icon.png', tag: 'TRX', raw: 36, name: 'usdttrc20'); + static const hbar = CryptoCurrency(title: 'HBAR', iconPath: 'assets/images/hbar_icon.png', raw: 37, name: 'hbar'); + static const sc = CryptoCurrency(title: 'SC', iconPath: 'assets/images/sc_icon.png', raw: 38, name: 'sc'); + static const sol = CryptoCurrency(title: 'SOL', iconPath: 'assets/images/sol_icon.png', raw: 39, name: 'sol'); + static const usdc = CryptoCurrency(title: 'USDC', iconPath: 'assets/images/usdc_icon.png', tag: 'ETH', raw: 40, name: 'usdc'); + static const usdcsol = CryptoCurrency(title: 'USDC', iconPath: 'assets/images/usdcsol_icon.png', tag: 'SOL', raw: 41, name: 'usdcsol'); + static const zaddr = CryptoCurrency(title: 'ZZEC', tag: 'ZEC', fullName: 'Shielded Zcash', iconPath: 'assets/images/zaddr_icon.png', raw: 42, name: 'zaddr'); + static const zec = CryptoCurrency(title: 'TZEC', tag: 'ZEC', fullName: 'Transparent Zcash', iconPath: 'assets/images/zec_icon.png', raw: 43, name: 'zec'); + static const zen = CryptoCurrency(title: 'ZEN', iconPath: 'assets/images/zen_icon.png', raw: 44, name: 'zen'); + static const xvg = CryptoCurrency(title: 'XVG', fullName: 'Verge', iconPath: 'assets/images/xvg_icon.png', raw: 45, name: 'xvg'); - static const usdcpoly = CryptoCurrency(title: 'USDC', iconPath: 'assets/images/usdc_icon.png', tag: 'POLY', raw: 46); - static const dcr = CryptoCurrency(title: 'DCR', iconPath: 'assets/images/dcr_icon.png', raw: 47); - static const husd = CryptoCurrency(title: 'HUSD', iconPath: 'assets/images/husd_icon.png', tag: 'ETH', raw: 48); - static const kmd = CryptoCurrency(title: 'KMD', iconPath: 'assets/images/kmd_icon.png', raw: 49); - static const mana = CryptoCurrency(title: 'MANA', iconPath: 'assets/images/mana_icon.png', tag: 'ETH', raw: 50); - static const maticpoly = CryptoCurrency(title: 'MATIC', iconPath: 'assets/images/matic_icon.png', tag: 'POLY', raw: 51); - static const matic = CryptoCurrency(title: 'MATIC', iconPath: 'assets/images/matic_icon.png', tag: 'ETH', raw: 52); - static const mkr = CryptoCurrency(title: 'MKR', iconPath: 'assets/images/mkr_icon.png', tag: 'ETH', raw: 53); - static const near = CryptoCurrency(title: 'NEAR', iconPath: 'assets/images/near_icon.png', raw: 54); - static const oxt = CryptoCurrency(title: 'OXT', iconPath: 'assets/images/oxt_icon.png', tag: 'ETH', raw: 55); - static const paxg = CryptoCurrency(title: 'PAXG', iconPath: 'assets/images/paxg_icon.png', tag: 'ETH', raw: 56); - static const pivx = CryptoCurrency(title: 'PIVX', iconPath: 'assets/images/pivx_icon.png', raw: 57); - static const rune = CryptoCurrency(title: 'RUNE', iconPath: 'assets/images/rune_icon.png', raw: 58); - static const rvn = CryptoCurrency(title: 'RVN', iconPath: 'assets/images/rvn_icon.png', raw: 59); - static const scrt = CryptoCurrency(title: 'SCRT', iconPath: 'assets/images/scrt_icon.png', raw: 60); - static const uni = CryptoCurrency(title: 'UNI', iconPath: 'assets/images/uni_icon.png', tag: 'ETH', raw: 61); - static const stx = CryptoCurrency(title: 'STX', iconPath: 'assets/images/stx_icon.png', raw: 62); + static const usdcpoly = CryptoCurrency(title: 'USDC', iconPath: 'assets/images/usdc_icon.png', tag: 'POLY', raw: 46, name: 'usdcpoly'); + static const dcr = CryptoCurrency(title: 'DCR', iconPath: 'assets/images/dcr_icon.png', raw: 47, name: 'dcr'); + static const husd = CryptoCurrency(title: 'HUSD', iconPath: 'assets/images/husd_icon.png', tag: 'ETH', raw: 48, name: 'husd'); + static const kmd = CryptoCurrency(title: 'KMD', iconPath: 'assets/images/kmd_icon.png', raw: 49, name: 'kmd'); + static const mana = CryptoCurrency(title: 'MANA', iconPath: 'assets/images/mana_icon.png', tag: 'ETH', raw: 50, name: 'mana'); + static const maticpoly = CryptoCurrency(title: 'MATIC', iconPath: 'assets/images/matic_icon.png', tag: 'POLY', raw: 51, name: 'maticpoly'); + static const matic = CryptoCurrency(title: 'MATIC', iconPath: 'assets/images/matic_icon.png', tag: 'ETH', raw: 52, name: 'matic'); + static const mkr = CryptoCurrency(title: 'MKR', iconPath: 'assets/images/mkr_icon.png', tag: 'ETH', raw: 53, name: 'mkr'); + static const near = CryptoCurrency(title: 'NEAR', iconPath: 'assets/images/near_icon.png', raw: 54, name: 'near'); + static const oxt = CryptoCurrency(title: 'OXT', iconPath: 'assets/images/oxt_icon.png', tag: 'ETH', raw: 55, name: 'oxt'); + static const paxg = CryptoCurrency(title: 'PAXG', iconPath: 'assets/images/paxg_icon.png', tag: 'ETH', raw: 56, name: 'paxg'); + static const pivx = CryptoCurrency(title: 'PIVX', iconPath: 'assets/images/pivx_icon.png', raw: 57, name: 'pivx'); + static const rune = CryptoCurrency(title: 'RUNE', iconPath: 'assets/images/rune_icon.png', raw: 58, name: 'rune'); + static const rvn = CryptoCurrency(title: 'RVN', iconPath: 'assets/images/rvn_icon.png', raw: 59, name: 'rvn'); + static const scrt = CryptoCurrency(title: 'SCRT', iconPath: 'assets/images/scrt_icon.png', raw: 60, name: 'scrt'); + static const uni = CryptoCurrency(title: 'UNI', iconPath: 'assets/images/uni_icon.png', tag: 'ETH', raw: 61, name: 'uni'); + static const stx = CryptoCurrency(title: 'STX', iconPath: 'assets/images/stx_icon.png', raw: 62, name: 'stx'); - static Map rawCurrencyMap = + static final Map _rawCurrencyMap = all.fold>({}, (acc, item) { acc.addAll({item.raw: item}); return acc; }); - static const mapFromString = { - 'xmr': CryptoCurrency.xmr, - 'ada': CryptoCurrency.ada, - 'bch': CryptoCurrency.bch, - 'bnb': CryptoCurrency.bnb, - 'btc': CryptoCurrency.btc, - 'dai': CryptoCurrency.dai, - 'dash': CryptoCurrency.dash, - 'eos': CryptoCurrency.eos, - 'eth': CryptoCurrency.eth, - 'ltc': CryptoCurrency.ltc, - 'nano': CryptoCurrency.nano, - 'trx': CryptoCurrency.trx, - 'usdt': CryptoCurrency.usdt, - 'usdterc20': CryptoCurrency.usdterc20, - 'xlm': CryptoCurrency.xlm, - 'xrp': CryptoCurrency.xrp, - 'xhv': CryptoCurrency.xhv, - 'xag': CryptoCurrency.xag, - 'xau': CryptoCurrency.xau, - 'xaud': CryptoCurrency.xaud, - 'xbtc': CryptoCurrency.xbtc, - 'xcad': CryptoCurrency.xcad, - 'xchf': CryptoCurrency.xchf, - 'xcny': CryptoCurrency.xcny, - 'xeur': CryptoCurrency.xeur, - 'xgbp': CryptoCurrency.xgbp, - 'xjpy': CryptoCurrency.xjpy, - 'xnok': CryptoCurrency.xnok, - 'xnzd': CryptoCurrency.xnzd, - 'xusd': CryptoCurrency.xusd, - 'ape': CryptoCurrency.ape, - 'avaxc': CryptoCurrency.avaxc, - 'btt': CryptoCurrency.btt, - 'bttbsc': CryptoCurrency.bttbsc, - 'doge': CryptoCurrency.doge, - 'firo': CryptoCurrency.firo, - 'usdttrc20': CryptoCurrency.usdttrc20, - 'hbar': CryptoCurrency.hbar, - 'sc': CryptoCurrency.sc, - 'sol': CryptoCurrency.sol, - 'usdc': CryptoCurrency.usdc, - 'usdcsol': CryptoCurrency.usdcsol, - 'zaddr': CryptoCurrency.zaddr, - 'zec': CryptoCurrency.zec, - 'zen': CryptoCurrency.zen, - 'xvg': CryptoCurrency.xvg, - 'usdcpoly': CryptoCurrency.usdcpoly, - 'dcr': CryptoCurrency.dcr, - 'husd': CryptoCurrency.husd, - 'kmd': CryptoCurrency.kmd, - 'mana': CryptoCurrency.mana, - 'maticpoly': CryptoCurrency.maticpoly, - 'matic': CryptoCurrency.matic, - 'mkr': CryptoCurrency.mkr, - 'near': CryptoCurrency.near, - 'oxt': CryptoCurrency.oxt, - 'paxg': CryptoCurrency.paxg, - 'pivx': CryptoCurrency.pivx, - 'rune': CryptoCurrency.rune, - 'rvn': CryptoCurrency.rvn, - 'scrt': CryptoCurrency.scrt, - 'uni': CryptoCurrency.uni, - 'stx': CryptoCurrency.stx - }; + static final Map _nameCurrencyMap = + all.fold>({}, (acc, item) { + acc.addAll({item.name: item}); + return acc; + }); static CryptoCurrency deserialize({required int raw}) { - if (CryptoCurrency.rawCurrencyMap[raw] == null) { + if (CryptoCurrency._rawCurrencyMap[raw] == null) { final s = 'Unexpected token: $raw for CryptoCurrency deserialize'; throw ArgumentError.value(raw, 'raw', s); } - return CryptoCurrency.rawCurrencyMap[raw]!; + return CryptoCurrency._rawCurrencyMap[raw]!; } - static CryptoCurrency fromString(String raw) { + static CryptoCurrency fromString(String name) { - if (CryptoCurrency.mapFromString[raw.toLowerCase()] == null) { - final s = 'Unexpected token: $raw for CryptoCurrency fromString'; - throw ArgumentError.value(raw, 'raw', s); + if (CryptoCurrency._nameCurrencyMap[name.toLowerCase()] == null) { + final s = 'Unexpected token: $name for CryptoCurrency fromString'; + throw ArgumentError.value(name, 'name', s); } - return CryptoCurrency.mapFromString[raw.toLowerCase()]!; + return CryptoCurrency._nameCurrencyMap[name.toLowerCase()]!; } @override diff --git a/lib/src/screens/exchange/widgets/currency_picker.dart b/lib/src/screens/exchange/widgets/currency_picker.dart index 9f8b9e493..b785378c5 100644 --- a/lib/src/screens/exchange/widgets/currency_picker.dart +++ b/lib/src/screens/exchange/widgets/currency_picker.dart @@ -56,7 +56,7 @@ class CurrencyPickerState extends State { .where((element) => (element.title != null ? element.title.toLowerCase().contains(subString.toLowerCase()) : false) || (element.tag != null ? element.tag!.toLowerCase().contains(subString.toLowerCase()) : false) || - (element.name != null ? element.name!.toLowerCase().contains(subString.toLowerCase()) : false)) + (element.fullName != null ? element.fullName!.toLowerCase().contains(subString.toLowerCase()) : false)) .toList(); return; } diff --git a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart index c9d2c77f5..43db6099f 100644 --- a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart @@ -30,7 +30,7 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { {required WalletBase wallet, dynamic item}) : isEdit = item != null, state = AddressEditOrCreateStateInitial(), - label = item?.name as String? ?? '', + label = item?.fullName as String? ?? '', _item = item, _wallet = wallet; From 5462836b8d62227c3d1ec00fdaa4a66f42b6a802 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 23 Nov 2022 19:06:41 +0200 Subject: [PATCH 045/203] seperate settings view model --- lib/di.dart | 32 +++++- lib/entities/priority_for_wallet_type.dart | 21 ++++ lib/src/screens/send/widgets/send_card.dart | 3 +- .../settings/display_settings_page.dart | 4 +- .../screens/settings/other_settings_page.dart | 6 +- lib/src/screens/settings/privacy_page.dart | 4 +- .../settings/security_backup_page.dart | 3 +- lib/view_model/send/send_view_model.dart | 2 +- .../settings/display_settings_view_model.dart | 63 +++++++++++ .../settings/other_settings_view_model.dart | 72 +++++++++++++ .../settings/privacy_settings_view_model.dart | 21 ++++ .../security_settings_view_model.dart | 29 +++++ .../settings/settings_view_model.dart | 101 +----------------- 13 files changed, 248 insertions(+), 113 deletions(-) create mode 100644 lib/entities/priority_for_wallet_type.dart create mode 100644 lib/view_model/settings/display_settings_view_model.dart create mode 100644 lib/view_model/settings/other_settings_view_model.dart create mode 100644 lib/view_model/settings/privacy_settings_view_model.dart create mode 100644 lib/view_model/settings/security_settings_view_model.dart diff --git a/lib/di.dart b/lib/di.dart index 815a3740e..2edb9057e 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -31,6 +31,10 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart'; import 'package:cake_wallet/view_model/ionia/ionia_account_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart'; +import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart'; +import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart'; +import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart'; +import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cake_wallet/core/backup_service.dart'; import 'package:cw_core/wallet_service.dart'; @@ -443,6 +447,26 @@ Future setup( return SettingsViewModel(appStore.settingsStore, yatStore, appStore.wallet!); }); + getIt.registerFactory(() { + final appStore = getIt.get(); + return DisplaySettingsViewModel(appStore.settingsStore); + }); + + getIt.registerFactory(() { + final appStore = getIt.get(); + return PrivacySettingsViewModel(appStore.settingsStore); + }); + + getIt.registerFactory(() { + final appStore = getIt.get(); + return OtherSettingsViewModel(appStore.settingsStore, appStore.wallet!); + }); + + getIt.registerFactory(() { + final appStore = getIt.get(); + return SecuritySettingsViewModel(appStore.settingsStore); + }); + getIt .registerFactory(() => WalletSeedViewModel(getIt.get().wallet!)); @@ -481,13 +505,13 @@ Future setup( getIt.registerFactory(() => ConnectionSyncPage(getIt.get(), getIt.get())); - getIt.registerFactory(() => SecurityBackupPage(getIt.get())); + getIt.registerFactory(() => SecurityBackupPage(getIt.get())); - getIt.registerFactory(() => PrivacyPage(getIt.get())); + getIt.registerFactory(() => PrivacyPage(getIt.get())); - getIt.registerFactory(() => DisplaySettingsPage(getIt.get())); + getIt.registerFactory(() => DisplaySettingsPage(getIt.get())); - getIt.registerFactory(() => OtherSettingsPage(getIt.get())); + getIt.registerFactory(() => OtherSettingsPage(getIt.get())); getIt.registerFactory(() => NodeCreateOrEditViewModel(_nodeSource, getIt.get().wallet!)); diff --git a/lib/entities/priority_for_wallet_type.dart b/lib/entities/priority_for_wallet_type.dart new file mode 100644 index 000000000..927ab8803 --- /dev/null +++ b/lib/entities/priority_for_wallet_type.dart @@ -0,0 +1,21 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/haven/haven.dart'; +import 'package:cake_wallet/monero/monero.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_type.dart'; + +List priorityForWalletType(WalletType type) { + switch (type) { + case WalletType.monero: + return monero!.getTransactionPriorities(); + case WalletType.bitcoin: + return bitcoin!.getTransactionPriorities(); + case WalletType.litecoin: + return bitcoin!.getLitecoinTransactionPriorities(); + case WalletType.haven: + return haven!.getTransactionPriorities(); + default: + return []; + } +} + diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index dc589923f..d5775e2b5 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -1,11 +1,10 @@ -import 'dart:ui'; +import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:cake_wallet/view_model/send/output.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; diff --git a/lib/src/screens/settings/display_settings_page.dart b/lib/src/screens/settings/display_settings_page.dart index 0c18ce09a..fd26da1c4 100644 --- a/lib/src/screens/settings/display_settings_page.dart +++ b/lib/src/screens/settings/display_settings_page.dart @@ -8,7 +8,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell. import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; +import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -19,7 +19,7 @@ class DisplaySettingsPage extends BasePage { @override String get title => S.current.display_settings; - final SettingsViewModel settingsViewModel; + final DisplaySettingsViewModel settingsViewModel; @override Widget body(BuildContext context) { diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart index 65d976708..01bd861b1 100644 --- a/lib/src/screens/settings/other_settings_page.dart +++ b/lib/src/screens/settings/other_settings_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -5,8 +6,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arro import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_version_cell.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; -import 'package:cw_core/transaction_priority.dart'; +import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -16,7 +16,7 @@ class OtherSettingsPage extends BasePage { @override String get title => S.current.other_settings; - final SettingsViewModel _settingsViewModel; + final OtherSettingsViewModel _settingsViewModel; @override Widget body(BuildContext context) { diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index d8518ce3b..08ab945cc 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -1,7 +1,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; +import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -11,7 +11,7 @@ class PrivacyPage extends BasePage { @override String get title => S.current.privacy_settings; - final SettingsViewModel settingsViewModel; + final PrivacySettingsViewModel settingsViewModel; @override Widget body(BuildContext context) { diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index d950597f0..633450313 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart'; import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -16,7 +17,7 @@ class SecurityBackupPage extends BasePage { @override String get title => S.current.security_and_backup; - final SettingsViewModel settingsViewModel; + final SecuritySettingsViewModel settingsViewModel; @override Widget body(BuildContext context) { diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index cdef6faba..c673c452d 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -1,10 +1,10 @@ import 'package:cake_wallet/entities/balance_display_mode.dart'; +import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cake_wallet/view_model/send/send_template_view_model.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/entities/template.dart'; diff --git a/lib/view_model/settings/display_settings_view_model.dart b/lib/view_model/settings/display_settings_view_model.dart new file mode 100644 index 000000000..3537dfa6e --- /dev/null +++ b/lib/view_model/settings/display_settings_view_model.dart @@ -0,0 +1,63 @@ +import 'package:cake_wallet/entities/balance_display_mode.dart'; +import 'package:cake_wallet/entities/fiat_currency.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:mobx/mobx.dart'; + +part 'display_settings_view_model.g.dart'; + +class DisplaySettingsViewModel = DisplaySettingsViewModelBase with _$DisplaySettingsViewModel; + + +abstract class DisplaySettingsViewModelBase with Store { + DisplaySettingsViewModelBase( + this._settingsStore, + ); + + final SettingsStore _settingsStore; + + @computed + FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency; + + @computed + String get languageCode => _settingsStore.languageCode; + + + @computed + BalanceDisplayMode get balanceDisplayMode => + _settingsStore.balanceDisplayMode; + + @computed + bool get shouldDisplayBalance => balanceDisplayMode == BalanceDisplayMode.displayableBalance; + + @computed + ThemeBase get theme => _settingsStore.currentTheme; + + @action + void setBalanceDisplayMode(BalanceDisplayMode value) => + _settingsStore.balanceDisplayMode = value; + + @action + void setShouldDisplayBalance(bool value){ + if (value) { + _settingsStore.balanceDisplayMode = BalanceDisplayMode.displayableBalance; + } else { + _settingsStore.balanceDisplayMode = BalanceDisplayMode.hiddenBalance; + } + } + + @action + void onLanguageSelected (String code) { + _settingsStore.languageCode = code; + } + + @action + void setTheme(ThemeBase newTheme){ + _settingsStore.currentTheme = newTheme; + } + + @action + void setFiatCurrency(FiatCurrency value) => + _settingsStore.fiatCurrency = value; + +} \ No newline at end of file diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart new file mode 100644 index 000000000..b0ba4c9b5 --- /dev/null +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -0,0 +1,72 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cw_core/balance.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:mobx/mobx.dart'; +import 'package:package_info/package_info.dart'; + +part 'other_settings_view_model.g.dart'; + +class OtherSettingsViewModel = OtherSettingsViewModelBase + with _$OtherSettingsViewModel; + + +abstract class OtherSettingsViewModelBase with Store { + OtherSettingsViewModelBase(this._settingsStore, WalletBase, + TransactionInfo> + wallet): + walletType = wallet.type, + _wallet = wallet, + currentVersion = ''{ + PackageInfo.fromPlatform().then( + (PackageInfo packageInfo) => currentVersion = packageInfo.version); + + final priority = _settingsStore.priority[wallet.type]; + final priorities = priorityForWalletType(wallet.type); + + if (!priorities.contains(priority)) { + _settingsStore.priority[wallet.type] = priorities.first; + } + + } + + final WalletType walletType; + final WalletBase, + TransactionInfo> _wallet; + + @observable + String currentVersion; + + final SettingsStore _settingsStore; + + @computed + TransactionPriority get transactionPriority { + final priority = _settingsStore.priority[walletType]; + + if (priority == null) { + throw Exception('Unexpected type ${walletType.toString()}'); + } + + return priority; + } + + String getDisplayPriority(dynamic priority) { + final _priority = priority as TransactionPriority; + + if (_wallet.type == WalletType.bitcoin + || _wallet.type == WalletType.litecoin) { + final rate = bitcoin!.getFeeRate(_wallet, _priority); + return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); + } + + return priority.toString(); + } + + void onDisplayPrioritySelected(TransactionPriority priority) => + _settingsStore.priority[_wallet.type] = priority; +} \ No newline at end of file diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart new file mode 100644 index 000000000..2ea816724 --- /dev/null +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -0,0 +1,21 @@ +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:mobx/mobx.dart'; + +part 'privacy_settings_view_model.g.dart'; + +class PrivacySettingsViewModel = PrivacySettingsViewModelBase + with _$PrivacySettingsViewModel; + +abstract class PrivacySettingsViewModelBase with Store { + PrivacySettingsViewModelBase(this._settingsStore); + + final SettingsStore _settingsStore; + + @computed + bool get shouldSaveRecipientAddress => + _settingsStore.shouldSaveRecipientAddress; + + @action + void setShouldSaveRecipientAddress(bool value) => + _settingsStore.shouldSaveRecipientAddress = value; +} \ No newline at end of file diff --git a/lib/view_model/settings/security_settings_view_model.dart b/lib/view_model/settings/security_settings_view_model.dart new file mode 100644 index 000000000..9bf2fb6eb --- /dev/null +++ b/lib/view_model/settings/security_settings_view_model.dart @@ -0,0 +1,29 @@ +import 'package:cake_wallet/entities/biometric_auth.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:mobx/mobx.dart'; + +part 'security_settings_view_model.g.dart'; + +class SecuritySettingsViewModel = SecuritySettingsViewModelBase + with _$SecuritySettingsViewModel; + +abstract class SecuritySettingsViewModelBase with Store { + SecuritySettingsViewModelBase(this._settingsStore): _biometricAuth = BiometricAuth(); + + final BiometricAuth _biometricAuth; + final SettingsStore _settingsStore; + + @computed + bool get allowBiometricalAuthentication => + _settingsStore.allowBiometricalAuthentication; + + @action + Future biometricAuthenticated()async{ + return await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated(); + } + + @action + void setAllowBiometricalAuthentication(bool value) => + _settingsStore.allowBiometricalAuthentication = value; + +} \ No newline at end of file diff --git a/lib/view_model/settings/settings_view_model.dart b/lib/view_model/settings/settings_view_model.dart index 7783cd200..1f34d5374 100644 --- a/lib/view_model/settings/settings_view_model.dart +++ b/lib/view_model/settings/settings_view_model.dart @@ -1,6 +1,6 @@ +import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:mobx/mobx.dart'; -import 'package:package_info/package_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/entities/biometric_auth.dart'; @@ -22,21 +22,6 @@ part 'settings_view_model.g.dart'; class SettingsViewModel = SettingsViewModelBase with _$SettingsViewModel; -List priorityForWalletType(WalletType type) { - switch (type) { - case WalletType.monero: - return monero!.getTransactionPriorities(); - case WalletType.bitcoin: - return bitcoin!.getTransactionPriorities(); - case WalletType.litecoin: - return bitcoin!.getLitecoinTransactionPriorities(); - case WalletType.haven: - return haven!.getTransactionPriorities(); - default: - return []; - } -} - abstract class SettingsViewModelBase with Store { SettingsViewModelBase( this._settingsStore, @@ -46,12 +31,8 @@ abstract class SettingsViewModelBase with Store { wallet) : itemHeaders = {}, walletType = wallet.type, - _wallet = wallet, - _biometricAuth = BiometricAuth(), - currentVersion = '' { - PackageInfo.fromPlatform().then( - (PackageInfo packageInfo) => currentVersion = packageInfo.version); - + _wallet = wallet{ + final priority = _settingsStore.priority[wallet.type]; final priorities = priorityForWalletType(wallet.type); @@ -85,18 +66,9 @@ abstract class SettingsViewModelBase with Store { } - @observable - String currentVersion; - - @computed - Node get node => _settingsStore.getCurrentNode(walletType); - @computed FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency; - @computed - String get languageCode => _settingsStore.languageCode; - @computed ObservableList get actionlistDisplayMode => _settingsStore.actionlistDisplayMode; @@ -112,21 +84,6 @@ abstract class SettingsViewModelBase with Store { return priority; } - @computed - BalanceDisplayMode get balanceDisplayMode => - _settingsStore.balanceDisplayMode; - - @computed - bool get shouldDisplayBalance => balanceDisplayMode == BalanceDisplayMode.displayableBalance; - - @computed - bool get shouldSaveRecipientAddress => - _settingsStore.shouldSaveRecipientAddress; - - @computed - bool get allowBiometricalAuthentication => - _settingsStore.allowBiometricalAuthentication; - @computed ThemeBase get theme => _settingsStore.currentTheme; @@ -136,26 +93,13 @@ abstract class SettingsViewModelBase with Store { final SettingsStore _settingsStore; final YatStore _yatStore; final WalletType walletType; - final BiometricAuth _biometricAuth; final WalletBase, TransactionInfo> _wallet; - @action - void setBalanceDisplayMode(BalanceDisplayMode value) => - _settingsStore.balanceDisplayMode = value; - @action void setFiatCurrency(FiatCurrency value) => _settingsStore.fiatCurrency = value; - @action - void setShouldSaveRecipientAddress(bool value) => - _settingsStore.shouldSaveRecipientAddress = value; - - @action - void setAllowBiometricalAuthentication(bool value) => - _settingsStore.allowBiometricalAuthentication = value; - @action void toggleTransactionsDisplay() => actionlistDisplayMode.contains(ActionListDisplayMode.transactions) @@ -183,43 +127,4 @@ abstract class SettingsViewModelBase with Store { @action void _showTrades() => actionlistDisplayMode.add(ActionListDisplayMode.trades); - @action - Future biometricAuthenticated()async{ - return await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated(); - } - - @action - void onLanguageSelected (String code) { - _settingsStore.languageCode = code; - } - - @action - void setTheme(ThemeBase newTheme){ - _settingsStore.currentTheme = newTheme; - } - - @action - void setShouldDisplayBalance(bool value){ - if (value) { - _settingsStore.balanceDisplayMode = BalanceDisplayMode.displayableBalance; - } else { - _settingsStore.balanceDisplayMode = BalanceDisplayMode.hiddenBalance; - } - } - - String getDisplayPriority(dynamic priority) { - final _priority = priority as TransactionPriority; - - if (_wallet.type == WalletType.bitcoin - || _wallet.type == WalletType.litecoin) { - final rate = bitcoin!.getFeeRate(_wallet, _priority); - return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); - } - - return priority.toString(); - } - - void onDisplayPrioritySelected(TransactionPriority priority) => - _settingsStore.priority[_wallet.type] = priority; - } From 7874009854a53fdbd8db3f099e826b27d6f725db Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Thu, 24 Nov 2022 16:34:29 +0200 Subject: [PATCH 046/203] Fix restore from backup using 6 digit-pin --- lib/core/backup_service.dart | 6 +++++- lib/di.dart | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 999b67120..780185a66 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; @@ -20,7 +21,7 @@ import 'package:cake_backup/backup.dart' as cake_backup; class BackupService { BackupService(this._flutterSecureStorage, this._walletInfoSource, - this._keyService, this._sharedPreferences) + this._keyService, this._sharedPreferences, this._settingsStore) : _cipher = Cryptography.instance.chacha20Poly1305Aead(), _correctWallets = []; @@ -33,6 +34,7 @@ class BackupService { final FlutterSecureStorage _flutterSecureStorage; final SharedPreferences _sharedPreferences; final Box _walletInfoSource; + final SettingsStore _settingsStore; final KeyService _keyService; List _correctWallets; @@ -301,6 +303,7 @@ class BackupService { as Map; final keychainWalletsInfo = keychainJSON['wallets'] as List; final decodedPin = keychainJSON['pin'] as String; + _settingsStore.pinCodeLength = decodedPin.length; final pinCodeKey = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); @@ -331,6 +334,7 @@ class BackupService { final keychainWalletsInfo = keychainJSON['wallets'] as List; final decodedPin = keychainJSON['pin'] as String; final pinCodeKey = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); + _settingsStore.pinCodeLength = decodedPin.length; final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPassword = keychainJSON[backupPasswordKey] as String; diff --git a/lib/di.dart b/lib/di.dart index 90549cf6f..b06931cd6 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -586,7 +586,9 @@ Future setup( getIt.get(), _walletInfoSource, getIt.get(), - getIt.get())); + getIt.get(), + getIt.get(), + )); getIt.registerFactory(() => BackupViewModel(getIt.get(), getIt.get(), getIt.get())); From 3acbfbae796e16aa5a613a55f19dfe4815277665 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Fri, 25 Nov 2022 22:51:07 +0200 Subject: [PATCH 047/203] Fix issues from code review --- lib/di.dart | 23 +--- lib/src/screens/send/send_page.dart | 11 +- .../settings/display_settings_page.dart | 20 +-- .../screens/settings/other_settings_page.dart | 14 +- lib/src/screens/settings/privacy_page.dart | 25 +++- .../settings/security_backup_page.dart | 15 +-- .../exchange/exchange_view_model.dart | 25 +++- lib/view_model/send/send_view_model.dart | 22 +++- .../settings/privacy_settings_view_model.dart | 7 + .../settings/settings_view_model.dart | 124 ------------------ 10 files changed, 94 insertions(+), 192 deletions(-) delete mode 100644 lib/view_model/settings/settings_view_model.dart diff --git a/lib/di.dart b/lib/di.dart index 2edb9057e..ce2e2a7d8 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -123,7 +123,6 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_v import 'package:cake_wallet/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/monero_account_list_view_model.dart'; import 'package:cake_wallet/view_model/send/send_view_model.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:cake_wallet/view_model/wallet_keys_view_model.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart'; import 'package:cake_wallet/view_model/wallet_restore_view_model.dart'; @@ -385,8 +384,7 @@ Future setup( _transactionDescriptionBox)); getIt.registerFactory( - () => SendPage(sendViewModel: getIt.get(), - settingsViewModel: getIt.get())); + () => SendPage(sendViewModel: getIt.get())); getIt.registerFactory(() => SendTemplatePage( sendTemplateViewModel: getIt.get())); @@ -442,29 +440,19 @@ Future setup( getIt.get(param1: account))); getIt.registerFactory(() { - final appStore = getIt.get(); - final yatStore = getIt.get(); - return SettingsViewModel(appStore.settingsStore, yatStore, appStore.wallet!); + return DisplaySettingsViewModel(getIt.get()); }); getIt.registerFactory(() { - final appStore = getIt.get(); - return DisplaySettingsViewModel(appStore.settingsStore); + return PrivacySettingsViewModel(getIt.get()); }); getIt.registerFactory(() { - final appStore = getIt.get(); - return PrivacySettingsViewModel(appStore.settingsStore); + return OtherSettingsViewModel(getIt(), getIt()); }); getIt.registerFactory(() { - final appStore = getIt.get(); - return OtherSettingsViewModel(appStore.settingsStore, appStore.wallet!); - }); - - getIt.registerFactory(() { - final appStore = getIt.get(); - return SecuritySettingsViewModel(appStore.settingsStore); + return SecuritySettingsViewModel(getIt.get()); }); getIt @@ -530,7 +518,6 @@ Future setup( getIt.get(), getIt.get().settingsStore, getIt.get(), - getIt.get(), )); getIt.registerFactory(() => ExchangeTradeViewModel( diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index e0cfff517..b051a3afb 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,4 +1,3 @@ -import 'dart:ui'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart'; import 'package:cake_wallet/src/screens/send/widgets/send_card.dart'; @@ -6,8 +5,6 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:cake_wallet/src/widgets/template_tile.dart'; import 'package:cake_wallet/view_model/send/output.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; @@ -28,13 +25,11 @@ import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'package:cw_core/crypto_currency.dart'; class SendPage extends BasePage { - SendPage({required this.sendViewModel,required this.settingsViewModel }) : _formKey = GlobalKey(),fiatFromSettings = settingsViewModel.fiatCurrency; + SendPage({required this.sendViewModel}) : _formKey = GlobalKey(); final SendViewModel sendViewModel; - final SettingsViewModel settingsViewModel; final GlobalKey _formKey; final controller = PageController(initialPage: 0); - final FiatCurrency fiatFromSettings ; bool _effectsInstalled = false; @@ -55,7 +50,7 @@ class SendPage extends BasePage { @override void onClose(BuildContext context) { - settingsViewModel.setFiatCurrency(fiatFromSettings); + sendViewModel.onClose(); Navigator.of(context).pop(); } @@ -236,7 +231,7 @@ class SendPage extends BasePage { if(template.isCurrencySelected){ output.setCryptoAmount(template.amount); }else{ - settingsViewModel.setFiatCurrency(fiatFromTemplate); + sendViewModel.setFiatCurrency(fiatFromTemplate); output.setFiatAmount(template.amountFiat); } output.resetParsedAddress(); diff --git a/lib/src/screens/settings/display_settings_page.dart b/lib/src/screens/settings/display_settings_page.dart index fd26da1c4..cd413ff45 100644 --- a/lib/src/screens/settings/display_settings_page.dart +++ b/lib/src/screens/settings/display_settings_page.dart @@ -14,12 +14,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; class DisplaySettingsPage extends BasePage { - DisplaySettingsPage(this.settingsViewModel); + DisplaySettingsPage(this._displaySettingsViewModel); @override String get title => S.current.display_settings; - final DisplaySettingsViewModel settingsViewModel; + final DisplaySettingsViewModel _displaySettingsViewModel; @override Widget body(BuildContext context) { @@ -30,17 +30,17 @@ class DisplaySettingsPage extends BasePage { children: [ SettingsSwitcherCell( title: S.current.settings_display_balance, - value: settingsViewModel.shouldDisplayBalance, + value: _displaySettingsViewModel.shouldDisplayBalance, onValueChange: (_, bool value) { - settingsViewModel.setShouldDisplayBalance(value); + _displaySettingsViewModel.setShouldDisplayBalance(value); }), if (!isHaven) SettingsPickerCell( title: S.current.settings_currency, searchHintText: S.current.search_currency, items: FiatCurrency.all, - selectedItem: settingsViewModel.fiatCurrency, - onItemSelected: (FiatCurrency currency) => settingsViewModel.setFiatCurrency(currency), + selectedItem: _displaySettingsViewModel.fiatCurrency, + onItemSelected: (FiatCurrency currency) => _displaySettingsViewModel.setFiatCurrency(currency), images: FiatCurrency.all.map((e) => Image.asset("assets/images/flags/${e.countryCode}.png")).toList(), isGridView: true, matchingCriteria: (FiatCurrency currency, String searchText) { @@ -55,8 +55,8 @@ class DisplaySettingsPage extends BasePage { displayItem: (dynamic code) { return LanguageService.list[code] ?? ''; }, - selectedItem: settingsViewModel.languageCode, - onItemSelected: settingsViewModel.onLanguageSelected, + selectedItem: _displaySettingsViewModel.languageCode, + onItemSelected: _displaySettingsViewModel.onLanguageSelected, images: LanguageService.list.keys .map((e) => Image.asset("assets/images/flags/${LanguageService.localeCountryCode[e]}.png")) .toList(), @@ -68,8 +68,8 @@ class DisplaySettingsPage extends BasePage { ChoicesListItem( title: S.current.color_theme, items: ThemeList.all, - selectedItem: settingsViewModel.theme, - onItemSelected: (ThemeBase theme) => settingsViewModel.setTheme(theme), + selectedItem: _displaySettingsViewModel.theme, + onItemSelected: (ThemeBase theme) => _displaySettingsViewModel.setTheme(theme), ), ), ], diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart index 01bd861b1..e055e2e8e 100644 --- a/lib/src/screens/settings/other_settings_page.dart +++ b/lib/src/screens/settings/other_settings_page.dart @@ -11,12 +11,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; class OtherSettingsPage extends BasePage { - OtherSettingsPage(this._settingsViewModel); + OtherSettingsPage(this._otherSettingsViewModel); @override String get title => S.current.other_settings; - final OtherSettingsViewModel _settingsViewModel; + final OtherSettingsViewModel _otherSettingsViewModel; @override Widget body(BuildContext context) { @@ -26,10 +26,10 @@ class OtherSettingsPage extends BasePage { child: Column(children: [ SettingsPickerCell( title: S.current.settings_fee_priority, - items: priorityForWalletType(_settingsViewModel.walletType), - displayItem: _settingsViewModel.getDisplayPriority, - selectedItem: _settingsViewModel.transactionPriority, - onItemSelected: _settingsViewModel.onDisplayPrioritySelected, + items: priorityForWalletType(_otherSettingsViewModel.walletType), + displayItem: _otherSettingsViewModel.getDisplayPriority, + selectedItem: _otherSettingsViewModel.transactionPriority, + onItemSelected: _otherSettingsViewModel.onDisplayPrioritySelected, ), SettingsCellWithArrow( title: S.current.settings_terms_and_conditions, @@ -37,7 +37,7 @@ class OtherSettingsPage extends BasePage { ), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), Spacer(), - SettingsVersionCell(title: S.of(context).version(_settingsViewModel.currentVersion)) + SettingsVersionCell(title: S.of(context).version(_otherSettingsViewModel.currentVersion)) ]), ); }); diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index 08ab945cc..47041b4fb 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -6,24 +6,37 @@ import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; class PrivacyPage extends BasePage { - PrivacyPage(this.settingsViewModel); + PrivacyPage(this._privacySettingsViewModel); @override String get title => S.current.privacy_settings; - final PrivacySettingsViewModel settingsViewModel; + final PrivacySettingsViewModel _privacySettingsViewModel; @override Widget body(BuildContext context) { return Container( padding: EdgeInsets.only(top: 10), child: Observer(builder: (_) { - return SettingsSwitcherCell( + return Observer(builder: (_) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SettingsSwitcherCell( + title: S.current.disable_exchange, + value: _privacySettingsViewModel.disableExchange, + onValueChange: (BuildContext context, bool value) { + _privacySettingsViewModel.setEnableExchange(value); + }), + SettingsSwitcherCell( title: S.current.settings_save_recipient_address, - value: settingsViewModel.shouldSaveRecipientAddress, + value: _privacySettingsViewModel.shouldSaveRecipientAddress, onValueChange: (BuildContext _, bool value) { - settingsViewModel.setShouldSaveRecipientAddress(value); - }); + _privacySettingsViewModel.setShouldSaveRecipientAddress(value); + }) + ], + ); + }); }), ); } diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index 633450313..224c941ee 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -7,17 +7,16 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arro import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; class SecurityBackupPage extends BasePage { - SecurityBackupPage(this.settingsViewModel); + SecurityBackupPage(this._securitySettingsViewModel); @override String get title => S.current.security_and_backup; - final SecuritySettingsViewModel settingsViewModel; + final SecuritySettingsViewModel _securitySettingsViewModel; @override Widget body(BuildContext context) { @@ -59,23 +58,23 @@ class SecurityBackupPage extends BasePage { Observer(builder: (_) { return SettingsSwitcherCell( title: S.current.settings_allow_biometrical_authentication, - value: settingsViewModel.allowBiometricalAuthentication, + value: _securitySettingsViewModel.allowBiometricalAuthentication, onValueChange: (BuildContext context, bool value) { if (value) { Navigator.of(context).pushNamed(Routes.auth, arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { if (isAuthenticatedSuccessfully) { - if (await settingsViewModel.biometricAuthenticated()) { - settingsViewModel.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); + if (await _securitySettingsViewModel.biometricAuthenticated()) { + _securitySettingsViewModel.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); } } else { - settingsViewModel.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); + _securitySettingsViewModel.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); } auth.close(); }); } else { - settingsViewModel.setAllowBiometricalAuthentication(value); + _securitySettingsViewModel.setAllowBiometricalAuthentication(value); } }); }), diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 725208324..68947d170 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -6,8 +6,8 @@ import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart'; import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:cake_wallet/exchange/simpleswap/simpleswap_request.dart'; +import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/sync_status.dart'; @@ -42,7 +42,7 @@ class ExchangeViewModel = ExchangeViewModelBase with _$ExchangeViewModel; abstract class ExchangeViewModelBase with Store { ExchangeViewModelBase(this.wallet, this.trades, this._exchangeTemplateStore, - this.tradesStore, this._settingsStore, this.sharedPreferences, this._settingsViewModel) + this.tradesStore, this._settingsStore, this.sharedPreferences) : _cryptoNumberFormat = NumberFormat(), isReverse = false, isFixedRateMode = false, @@ -189,6 +189,19 @@ abstract class ExchangeViewModelBase with Store { ObservableList get templates => _exchangeTemplateStore.templates; + + @computed + TransactionPriority get transactionPriority { + final priority = _settingsStore.priority[wallet.type]; + + if (priority == null) { + throw Exception('Unexpected type ${wallet.type.toString()}'); + } + + return priority; + } + + bool get hasAllAmount => wallet.type == WalletType.bitcoin && depositCurrency == wallet.currency; @@ -198,11 +211,11 @@ abstract class ExchangeViewModelBase with Store { switch (wallet.type) { case WalletType.monero: case WalletType.haven: - return _settingsViewModel.transactionPriority == monero!.getMoneroTransactionPrioritySlow(); + return transactionPriority == monero!.getMoneroTransactionPrioritySlow(); case WalletType.bitcoin: - return _settingsViewModel.transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow(); + return transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow(); case WalletType.litecoin: - return _settingsViewModel.transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow(); + return transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow(); default: return false; } @@ -220,8 +233,6 @@ abstract class ExchangeViewModelBase with Store { final SettingsStore _settingsStore; - final SettingsViewModel _settingsViewModel; - double _bestRate = 0.0; late Timer bestRateSync; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index c673c452d..25a5cc7ee 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -42,7 +42,8 @@ abstract class SendViewModelBase with Store { : state = InitialExecutionState(), currencies = _wallet.balance.keys.toList(), selectedCryptoCurrency = _wallet.currency, - outputs = ObservableList() { + outputs = ObservableList(), + fiatFromSettings = _settingsStore.fiatCurrency { final priority = _settingsStore.priority[_wallet.type]; final priorities = priorityForWalletType(_wallet.type); @@ -52,7 +53,7 @@ abstract class SendViewModelBase with Store { outputs.add(Output(_wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency)); } - + @observable ExecutionState state; @@ -133,11 +134,13 @@ abstract class SendViewModelBase with Store { Validator get textValidator => TextValidator(); + final FiatCurrency fiatFromSettings; + @observable PendingTransaction? pendingTransaction; @computed - String get balance => balanceViewModel.availableBalance ?? '0.0'; + String get balance => balanceViewModel.availableBalance; @computed bool get isReadyForSend => _wallet.syncStatus is SyncedSyncStatus; @@ -166,6 +169,9 @@ abstract class SendViewModelBase with Store { bool get hasCurrecyChanger => walletType == WalletType.haven; + @computed + FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency; + final WalletBase _wallet; final SettingsStore _settingsStore; final SendTemplateViewModel sendTemplateViewModel; @@ -208,7 +214,7 @@ abstract class SendViewModelBase with Store { state = TransactionCommitting(); await pendingTransaction!.commit(); - if (pendingTransaction!.id?.isNotEmpty ?? false) { + if (pendingTransaction!.id.isNotEmpty) { _settingsStore.shouldSaveRecipientAddress ? await transactionDescriptionBox.add(TransactionDescription( id: pendingTransaction!.id, @@ -283,4 +289,12 @@ abstract class SendViewModelBase with Store { bool _isEqualCurrency(String currency) => currency.toLowerCase() == _wallet.currency.title.toLowerCase(); + + @action + void onClose() => + _settingsStore.fiatCurrency = fiatFromSettings; + + @action + void setFiatCurrency(FiatCurrency fiat) => + _settingsStore.fiatCurrency = fiat; } diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index 2ea816724..8433e673a 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -11,6 +11,9 @@ abstract class PrivacySettingsViewModelBase with Store { final SettingsStore _settingsStore; + @computed + bool get disableExchange => _settingsStore.disableExchange; + @computed bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress; @@ -18,4 +21,8 @@ abstract class PrivacySettingsViewModelBase with Store { @action void setShouldSaveRecipientAddress(bool value) => _settingsStore.shouldSaveRecipientAddress = value; + + @action + void setEnableExchange(bool value) => + _settingsStore.disableExchange = value; } \ No newline at end of file diff --git a/lib/view_model/settings/settings_view_model.dart b/lib/view_model/settings/settings_view_model.dart deleted file mode 100644 index d5de8be67..000000000 --- a/lib/view_model/settings/settings_view_model.dart +++ /dev/null @@ -1,124 +0,0 @@ -import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; -import 'package:cake_wallet/store/yat/yat_store.dart'; -import 'package:mobx/mobx.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/entities/fiat_currency.dart'; -import 'package:cake_wallet/entities/action_list_display_mode.dart'; -import 'package:cw_core/transaction_history.dart'; -import 'package:cw_core/balance.dart'; -import 'package:cw_core/transaction_info.dart'; -import 'package:cw_core/transaction_priority.dart'; -import 'package:cake_wallet/themes/theme_base.dart'; - -part 'settings_view_model.g.dart'; - -class SettingsViewModel = SettingsViewModelBase with _$SettingsViewModel; - -abstract class SettingsViewModelBase with Store { - SettingsViewModelBase( - this._settingsStore, - this._yatStore, - WalletBase, - TransactionInfo> - wallet) - : itemHeaders = {}, - walletType = wallet.type, - _wallet = wallet{ - - final priority = _settingsStore.priority[wallet.type]; - final priorities = priorityForWalletType(wallet.type); - - if (!priorities.contains(priority)) { - _settingsStore.priority[wallet.type] = priorities.first; - } - - //var connectYatUrl = YatLink.baseUrl + YatLink.signInSuffix; - //final connectYatUrlParameters = - // _yatStore.defineQueryParameters(); - - //if (connectYatUrlParameters.isNotEmpty) { - // connectYatUrl += YatLink.queryParameter + connectYatUrlParameters; - //} - - //var manageYatUrl = YatLink.baseUrl + YatLink.managePath; - //final manageYatUrlParameters = - // _yatStore.defineQueryParameters(); - - //if (manageYatUrlParameters.isNotEmpty) { - // manageYatUrl += YatLink.queryParameter + manageYatUrlParameters; - //} - - //var createNewYatUrl = YatLink.startFlowUrl; - //final createNewYatUrlParameters = - // _yatStore.defineQueryParameters(); - - //if (createNewYatUrlParameters.isNotEmpty) { - // createNewYatUrl += '?sub1=' + createNewYatUrlParameters; - //} - - } - - @computed - FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency; - - @computed - ObservableList get actionlistDisplayMode => - _settingsStore.actionlistDisplayMode; - - @computed - TransactionPriority get transactionPriority { - final priority = _settingsStore.priority[walletType]; - - if (priority == null) { - throw Exception('Unexpected type ${walletType.toString()}'); - } - - return priority; - } - - @computed - ThemeBase get theme => _settingsStore.currentTheme; - - bool get isBitcoinBuyEnabled => _settingsStore.isBitcoinBuyEnabled; - - final Map itemHeaders; - final SettingsStore _settingsStore; - final YatStore _yatStore; - final WalletType walletType; - final WalletBase, - TransactionInfo> _wallet; - - @action - void setFiatCurrency(FiatCurrency value) => - _settingsStore.fiatCurrency = value; - - @action - void toggleTransactionsDisplay() => - actionlistDisplayMode.contains(ActionListDisplayMode.transactions) - ? _hideTransaction() - : _showTransaction(); - - @action - void toggleTradesDisplay() => - actionlistDisplayMode.contains(ActionListDisplayMode.trades) - ? _hideTrades() - : _showTrades(); - - @action - void _hideTransaction() => - actionlistDisplayMode.remove(ActionListDisplayMode.transactions); - - @action - void _hideTrades() => - actionlistDisplayMode.remove(ActionListDisplayMode.trades); - - @action - void _showTransaction() => - actionlistDisplayMode.add(ActionListDisplayMode.transactions); - - @action - void _showTrades() => actionlistDisplayMode.add(ActionListDisplayMode.trades); - -} From 08edd4d8fff65ba368317f78109d68fbd94f4c8a Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 26 Nov 2022 02:33:37 +0200 Subject: [PATCH 048/203] Add types for OtherSettingsViewModel dependencies --- lib/di.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/di.dart b/lib/di.dart index ce2e2a7d8..6248a2c1a 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -448,7 +448,7 @@ Future setup( }); getIt.registerFactory(() { - return OtherSettingsViewModel(getIt(), getIt()); + return OtherSettingsViewModel(getIt.get(), getIt.get().wallet!); }); getIt.registerFactory(() { From 0188089bd8d3656ea262200681dfbc404fee6851 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 26 Nov 2022 14:07:01 +0200 Subject: [PATCH 049/203] Remove unused nodes list page route --- lib/di.dart | 2 -- lib/router.dart | 4 ---- lib/routes.dart | 1 - lib/src/screens/nodes/nodes_list_page.dart | 2 ++ 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index 6248a2c1a..9245e58ca 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -489,8 +489,6 @@ Future setup( _nodeSource, appStore.wallet!, appStore.settingsStore); }); - getIt.registerFactory(() => NodeListPage(getIt.get())); - getIt.registerFactory(() => ConnectionSyncPage(getIt.get(), getIt.get())); getIt.registerFactory(() => SecurityBackupPage(getIt.get())); diff --git a/lib/router.dart b/lib/router.dart index 7818cc52f..f9aa37a02 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -278,10 +278,6 @@ Route createRoute(RouteSettings settings) { param2: false), onWillPop: () async => false)); - case Routes.nodeList: - return CupertinoPageRoute( - builder: (_) => getIt.get()); - case Routes.connectionSync: return CupertinoPageRoute( builder: (_) => getIt.get()); diff --git a/lib/routes.dart b/lib/routes.dart index 04642ba34..d738b13e8 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -21,7 +21,6 @@ class Routes { static const seedLanguage = '/seed_language'; static const walletList = '/view_model.wallet_list'; static const auth = '/auth'; - static const nodeList = '/node_list'; static const newNode = '/new_node_list'; static const login = '/login'; static const splash = '/splash'; diff --git a/lib/src/screens/nodes/nodes_list_page.dart b/lib/src/screens/nodes/nodes_list_page.dart index 556a0fd06..4e72c511e 100644 --- a/lib/src/screens/nodes/nodes_list_page.dart +++ b/lib/src/screens/nodes/nodes_list_page.dart @@ -23,6 +23,8 @@ class NodeListPage extends BasePage { @override Widget trailing(context) { + // TODO: check if this will be used in the new design and then delete the whole page + // as it's not used anymore return Container( height: 32, decoration: BoxDecoration( From 79fb1b91d4b661cba9e1e668f59c9fcf152dc76b Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 26 Nov 2022 16:13:54 +0200 Subject: [PATCH 050/203] Check for Nodes if exists before adding them in nodes Fix nullability issue due to early access Fix Nodes_list,yml file structure --- assets/node_list.yml | 4 ++-- lib/entities/default_settings_migration.dart | 22 +++++++++++++++---- .../on_authentication_state_change.dart | 4 ++-- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/assets/node_list.yml b/assets/node_list.yml index 09fb72383..7962ea18c 100644 --- a/assets/node_list.yml +++ b/assets/node_list.yml @@ -22,10 +22,10 @@ - uri: node.imonero.org:18081 is_default: false - +- uri: node.c3pool.com:18081 is_default: false - +- uri: xmr.prprpr.icu:18081 is_default: false diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index b2036c3f6..fb404cd88 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -69,6 +69,8 @@ Future defaultSettingsMigration( sharedPreferences: sharedPreferences, nodes: nodes); await changeLitecoinCurrentElectrumServerToDefault( sharedPreferences: sharedPreferences, nodes: nodes); + await changeHavenCurrentNodeToDefault( + sharedPreferences: sharedPreferences, nodes: nodes); break; case 2: @@ -277,17 +279,29 @@ Future updateNodeTypes({required Box nodes}) async { Future addBitcoinElectrumServerList({required Box nodes}) async { final serverList = await loadBitcoinElectrumServerList(); - await nodes.addAll(serverList); + for (var node in serverList) { + if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) { + await nodes.add(node); + } + } } Future addLitecoinElectrumServerList({required Box nodes}) async { final serverList = await loadLitecoinElectrumServerList(); - await nodes.addAll(serverList); + for (var node in serverList) { + if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) { + await nodes.add(node); + } + } } Future addHavenNodeList({required Box nodes}) async { final nodeList = await loadDefaultHavenNodes(); - await nodes.addAll(nodeList); + for (var node in nodeList) { + if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) { + await nodes.add(node); + } + } } Future addAddressesForMoneroWallets( @@ -431,7 +445,7 @@ Future resetBitcoinElectrumServer( final oldElectrumServer = nodeSource.values.firstWhereOrNull( (node) => node.uri.toString().contains('electrumx.cakewallet.com')); var cakeWalletNode = nodeSource.values.firstWhereOrNull( - (node) => node.uri.toString() == cakeWalletBitcoinElectrumUri); + (node) => node.uriRaw.toString() == cakeWalletBitcoinElectrumUri); if (cakeWalletNode == null) { cakeWalletNode = diff --git a/lib/reactions/on_authentication_state_change.dart b/lib/reactions/on_authentication_state_change.dart index c91f5277e..560326cb5 100644 --- a/lib/reactions/on_authentication_state_change.dart +++ b/lib/reactions/on_authentication_state_change.dart @@ -23,12 +23,12 @@ void startAuthenticationStateChange(AuthenticationStore authenticationStore, } if (state == AuthenticationState.allowed) { - await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false); + await navigatorKey.currentState?.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false); return; } if (state == AuthenticationState.denied) { - await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.welcome, (_) => false); + await navigatorKey.currentState?.pushNamedAndRemoveUntil(Routes.welcome, (_) => false); return; } }); From 4d91ef6af8b554f66f68239b8fde46a7be59d7f2 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sun, 27 Nov 2022 22:10:21 +0200 Subject: [PATCH 051/203] App Center Integration with CI/CD workflow (#644) Add Ionia client id to secrets Update how to build android instructions Change devicelocale version as it caused issues when building Add trigger for send test build to transfer.sh and notify slack channel --- .github/workflows/pr_test_build.yml | 116 ++++++++++++++++++++++++++++ howto-build-android.md | 8 +- pubspec_base.yaml | 2 +- tool/utils/secret_key.dart | 1 + 4 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/pr_test_build.yml diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml new file mode 100644 index 000000000..dd2f1edeb --- /dev/null +++ b/.github/workflows/pr_test_build.yml @@ -0,0 +1,116 @@ +name: PR Test Build + +on: + pull_request: + branches: [ main ] + +jobs: + test: + + runs-on: ubuntu-18.04 + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: '8.x' + + - name: Flutter action + uses: subosito/flutter-action@v1 + with: + flutter-version: '3.3.x' + channel: stable + + - name: Install package dependencies + run: sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang + + - name: Execute Build and Setup Commands + run: | + sudo mkdir -p /opt/android + sudo chown $USER /opt/android + cd /opt/android + git clone https://github.com/cake-tech/cake_wallet.git --branch $GITHUB_HEAD_REF + cd cake_wallet/scripts/android/ + ./install_ndk.sh + source ./app_env.sh cakewallet + ./app_config.sh + ./build_all.sh + ./copy_monero_deps.sh + + - name: Install Flutter dependencies + run: | + cd /opt/android/cake_wallet + flutter pub get + + - name: Generate KeyStore + run: | + cd /opt/android/cake_wallet/android/app + keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass ${{ secrets.STORE_PASS }} -keypass ${{ secrets.KEY_PASS }} + + - name: Generate key properties + run: | + cd /opt/android/cake_wallet + flutter packages pub run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=${{ secrets.STORE_PASS }} keyPassword=${{ secrets.KEY_PASS }} + + - name: Generate localization + run: | + cd /opt/android/cake_wallet + flutter packages pub run tool/generate_localization.dart + + - name: Build generated code + run: | + cd /opt/android/cake_wallet + cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + flutter packages pub run build_runner build --delete-conflicting-outputs + + - name: Add secrets + run: | + cd /opt/android/cake_wallet + touch lib/.secrets.g.dart + echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart + echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart + echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart + echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart + echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart + echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart + echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart + echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart + echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart + echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart + echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart + echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart + echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart + echo "const sideShiftAffiliateId = '${{ secrets.SIDE_SHIFT_AFFILIATE_ID }}';" >> lib/.secrets.g.dart + echo "const sideShiftApiKey = '${{ secrets.SIDE_SHIFT_API_KEY }}';" >> lib/.secrets.g.dart + echo "const simpleSwapApiKey = '${{ secrets.SIMPLE_SWAP_API_KEY }}';" >> lib/.secrets.g.dart + echo "const onramperApiKey = '${{ secrets.ONRAMPER_API_KEY }}';" >> lib/.secrets.g.dart + echo "const anypayToken = '${{ secrets.ANY_PAY_TOKEN }}';" >> lib/.secrets.g.dart + echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart + + - name: Build + run: | + cd /opt/android/cake_wallet + flutter build apk --release + +# - name: Push to App Center +# run: | +# echo 'Installing App Center CLI tools' +# npm install -g appcenter-cli +# echo "Publishing test to App Center" +# appcenter distribute release \ +# --group "Testers" \ +# --file "/opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk" \ +# --release-notes ${GITHUB_HEAD_REF} \ +# --app Cake-Labs/Cake-Wallet \ +# --token ${{ secrets.APP_CENTER_TOKEN }} \ +# --quiet + + - name: Send Test APK + run: | + cd /opt/android/cake_wallet + var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/app-release.apk) + curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' + diff --git a/howto-build-android.md b/howto-build-android.md index 28478cdd1..4ef385b9f 100644 --- a/howto-build-android.md +++ b/howto-build-android.md @@ -55,7 +55,7 @@ You may download and install the latest version of Android Studio [here](https:/ ### 3. Installing Flutter -Need to install flutter with version `2.0.4`. For this please check section [Install Flutter manually](https://docs.flutter.dev/get-started/install/linux#install-flutter-manually). When flutter repository is downloaded please open it with `cd ` and checkout version 2.0.4 by `git checkout 2.0.4`. +Need to install flutter with version `3.x.x`. For this please check section [Install Flutter manually](https://docs.flutter.dev/get-started/install/linux#install-flutter-manually). ### 4. Verify Installations @@ -66,7 +66,7 @@ Verify that the Android toolchain, Flutter, and Android Studio have been correct The output of this command will appear like this, indicating successful installations. If there are problems with your installation, they **must** be corrected before proceeding. ``` Doctor summary (to see all details, run flutter doctor -v): -[✓] Flutter (Channel stable, 2.0.4, on Linux, locale en_US.UTF-8) +[✓] Flutter (Channel stable, 3.x.x, on Linux, locale en_US.UTF-8) [✓] Android toolchain - develop for Android devices (Android SDK version 28) [✓] Android Studio (version 4.0) ``` @@ -156,6 +156,10 @@ Generate mobx models for `cw_bitcoin`: `cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..` +Generate mobx models for `cw_haven`: + +`cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..` + Finally build mobx models for the app: `$ flutter packages pub run build_runner build --delete-conflicting-outputs` diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 248a06de0..00e1a39b1 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -34,7 +34,7 @@ dependencies: local_auth: ^2.1.0 package_info: ^2.0.0 #package_info_plus: ^1.4.2 - devicelocale: ^0.5.4 + devicelocale: ^0.4.3 auto_size_text: ^3.0.0 dotted_border: ^2.0.0+2 smooth_page_indicator: ^1.0.0+2 diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 64c7beefd..e5202a829 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -28,6 +28,7 @@ class SecretKey { SecretKey('simpleSwapApiKey', () => ''), SecretKey('anypayToken', () => ''), SecretKey('onramperApiKey', () => ''), + SecretKey('ioniaClientId', () => ''), ]; final String name; From ec15a9b229a8029d61f7d7ac3945a33182d1aa1a Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 28 Nov 2022 00:53:20 +0200 Subject: [PATCH 052/203] fix updateTradeList bug --- lib/store/dashboard/trades_store.dart | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/store/dashboard/trades_store.dart b/lib/store/dashboard/trades_store.dart index 6e763196b..72442b46f 100644 --- a/lib/store/dashboard/trades_store.dart +++ b/lib/store/dashboard/trades_store.dart @@ -31,13 +31,8 @@ abstract class TradesStoreBase with Store { void setTrade(Trade trade) => this.trade = trade; @action - Future updateTradeList() async { - if (trade == null) { - return; - } - - trades = tradesSource.values.map((trade) => TradeListItem( - trade: trade!, - settingsStore: settingsStore)).toList(); - } + Future updateTradeList() async => trades = + tradesSource.values.map((trade) => TradeListItem( + trade: trade, + settingsStore: settingsStore)).toList(); } \ No newline at end of file From a51384bd067fb4ab17aa469782f38fc044ad00af Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Mon, 28 Nov 2022 14:04:03 +0200 Subject: [PATCH 053/203] Remove unused nodes_list_page.dart --- lib/di.dart | 1 - lib/router.dart | 1 - lib/src/screens/nodes/nodes_list_page.dart | 168 --------------------- 3 files changed, 170 deletions(-) delete mode 100644 lib/src/screens/nodes/nodes_list_page.dart diff --git a/lib/di.dart b/lib/di.dart index 9245e58ca..c62dc9790 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -58,7 +58,6 @@ import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart' import 'package:cake_wallet/src/screens/faq/faq_page.dart'; import 'package:cake_wallet/src/screens/new_wallet/new_wallet_type_page.dart'; import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart'; -import 'package:cake_wallet/src/screens/nodes/nodes_list_page.dart'; import 'package:cake_wallet/src/screens/order_details/order_details_page.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/rescan/rescan_page.dart'; diff --git a/lib/router.dart b/lib/router.dart index f9aa37a02..4d3d61f5f 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -41,7 +41,6 @@ import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart'; import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart'; -import 'package:cake_wallet/src/screens/nodes/nodes_list_page.dart'; import 'package:cake_wallet/src/screens/receive/receive_page.dart'; import 'package:cake_wallet/src/screens/subaddress/address_edit_or_create_page.dart'; import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart'; diff --git a/lib/src/screens/nodes/nodes_list_page.dart b/lib/src/screens/nodes/nodes_list_page.dart deleted file mode 100644 index 4e72c511e..000000000 --- a/lib/src/screens/nodes/nodes_list_page.dart +++ /dev/null @@ -1,168 +0,0 @@ -import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:cw_core/node.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/palette.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/screens/nodes/widgets/node_list_row.dart'; -import 'package:cake_wallet/src/widgets/standard_list.dart'; -import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; -import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart'; -import 'package:flutter_slidable/flutter_slidable.dart'; - -class NodeListPage extends BasePage { - NodeListPage(this.nodeListViewModel); - - @override - String get title => S.current.nodes; - - final NodeListViewModel nodeListViewModel; - - @override - Widget trailing(context) { - // TODO: check if this will be used in the new design and then delete the whole page - // as it's not used anymore - return Container( - height: 32, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(16)), - color: Theme.of(context).accentTextTheme.caption!.color!), - child: ButtonTheme( - minWidth: double.minPositive, - child: TextButton( - onPressed: () async { - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: S.of(context).node_reset_settings_title, - alertContent: - S.of(context).nodes_list_reset_to_default_message, - rightButtonText: S.of(context).reset, - leftButtonText: S.of(context).cancel, - actionRightButton: () async { - Navigator.of(context).pop(); - await nodeListViewModel.reset(); - }, - actionLeftButton: () => Navigator.of(context).pop()); - }); - }, - child: Text( - S.of(context).reset, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14.0, - fontWeight: FontWeight.w600, - color: Palette.blueCraiola), - )), - ), - ); - } - - @override - Widget body(BuildContext context) { - return Container( - padding: EdgeInsets.only(top: 10), - child: Observer( - builder: (BuildContext context) { - return SectionStandardList( - sectionCount: 2, - context: context, - itemCounter: (int sectionIndex) { - if (sectionIndex == 0) { - return 1; - } - - return nodeListViewModel.nodes.length; - }, - itemBuilder: (_, sectionIndex, index) { - if (sectionIndex == 0) { - return NodeHeaderListRow( - title: S.of(context).add_new_node, - onTap: (_) async => await Navigator.of(context) - .pushNamed(Routes.newNode)); - } - - final node = nodeListViewModel.nodes[index]; - final isSelected = - node.keyIndex == nodeListViewModel.currentNode.keyIndex; - final nodeListRow = NodeListRow( - title: node.uriRaw, - isSelected: isSelected, - isAlive: node.requestNode(), - onTap: (_) async { - if (isSelected) { - return; - } - - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: - S.of(context).change_current_node_title, - alertContent: S - .of(context) - .change_current_node(node.uriRaw), - leftButtonText: S.of(context).cancel, - rightButtonText: S.of(context).change, - actionLeftButton: () => - Navigator.of(context).pop(), - actionRightButton: () async { - await nodeListViewModel.setAsCurrent(node); - Navigator.of(context).pop(); - }); - }); - }); - - final dismissibleRow = Slidable( - key: Key('${node.keyIndex}'), - startActionPane: _actionPane(context, node), - endActionPane: _actionPane(context, node), - child: nodeListRow, - ); - - return isSelected ? nodeListRow : dismissibleRow; - }); - }, - ), - ); - } - - ActionPane _actionPane(BuildContext context, Node node) => ActionPane( - motion: const ScrollMotion(), - extentRatio: 0.3, - children: [ - SlidableAction( - onPressed: (context) async { - final confirmed = await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: S.of(context).remove_node, - alertContent: - S.of(context).remove_node_message, - rightButtonText: S.of(context).remove, - leftButtonText: S.of(context).cancel, - actionRightButton: () => - Navigator.pop(context, true), - actionLeftButton: () => - Navigator.pop(context, false)); - }) ?? - false; - - if (confirmed) { - await nodeListViewModel.delete(node); - } - }, - backgroundColor: Colors.red, - foregroundColor: Colors.white, - icon: CupertinoIcons.delete, - label: S.of(context).delete, - ), - ], - ); -} From c8a9c1f53f1a60c93e557f7a10462d2f490d298c Mon Sep 17 00:00:00 2001 From: Justin Ehrenhofer Date: Mon, 28 Nov 2022 09:45:18 -0600 Subject: [PATCH 054/203] Update Monero nodes --- assets/node_list.yml | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/assets/node_list.yml b/assets/node_list.yml index 7962ea18c..39b440c9f 100644 --- a/assets/node_list.yml +++ b/assets/node_list.yml @@ -1,31 +1,21 @@ - - uri: xmr-node-uk.cakewallet.com:18081 + uri: xmr-node.cakewallet.com:18081 is_default: true - - uri: xmr-node-eu.cakewallet.com:18081 + uri: node.sethforprivacy.com:18089 is_default: false - - uri: xmr-node-usa-east.cakewallet.com:18081 - is_default: false -- - uri: node.moneroworld.com:18089 - is_default: false -- - uri: node.xmr.pt:18081 - is_default: false -- - uri: node.monero.net:18081 - is_default: false -- - uri: opennode.xmr-tw.org:18089 - is_default: false -- - uri: node.imonero.org:18081 + uri: nodes.hashvault.pro:18081 is_default: false - uri: node.c3pool.com:18081 is_default: false - - uri: xmr.prprpr.icu:18081 + uri: node.supportxmr.com:18081 + is_default: false +- + uri: node.community.rino.io:18081 + is_default: false +- + uri: node.moneroworld.com:18089 is_default: false - From 1dd94c96058cdd153a748b9e6cbad430adc0f75f Mon Sep 17 00:00:00 2001 From: Justin Ehrenhofer Date: Mon, 28 Nov 2022 10:11:52 -0600 Subject: [PATCH 055/203] Add onion node Apologies for forgetting this a few minutes ago, despite me adding this to the guides.cakewallet.com website this morning! Related to CW-252 (no notice is added in this commit) --- assets/node_list.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/assets/node_list.yml b/assets/node_list.yml index 39b440c9f..fccc968cf 100644 --- a/assets/node_list.yml +++ b/assets/node_list.yml @@ -1,6 +1,9 @@ - uri: xmr-node.cakewallet.com:18081 is_default: true +- + uri: cakexmrl7bonq7ovjka5kuwuyd3f7qnkz6z6s6dmsy3uckwra7bvggyd.onion:18081 + is_default: false - uri: node.sethforprivacy.com:18089 is_default: false From bd65fd8782fede5e01d1399b449448eb06edaba9 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:14:31 +0200 Subject: [PATCH 056/203] Upload APK to github artifacts Rename apk --- .github/workflows/pr_test_build.yml | 187 +++++++++++++++------------- 1 file changed, 102 insertions(+), 85 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index dd2f1edeb..398f1edd5 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -11,89 +11,89 @@ jobs: steps: - uses: actions/checkout@v2 - - uses: actions/setup-java@v1 - with: - java-version: '8.x' - - - name: Flutter action - uses: subosito/flutter-action@v1 - with: - flutter-version: '3.3.x' - channel: stable - - - name: Install package dependencies - run: sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang - - - name: Execute Build and Setup Commands - run: | - sudo mkdir -p /opt/android - sudo chown $USER /opt/android - cd /opt/android - git clone https://github.com/cake-tech/cake_wallet.git --branch $GITHUB_HEAD_REF - cd cake_wallet/scripts/android/ - ./install_ndk.sh - source ./app_env.sh cakewallet - ./app_config.sh - ./build_all.sh - ./copy_monero_deps.sh - - - name: Install Flutter dependencies - run: | - cd /opt/android/cake_wallet - flutter pub get - - - name: Generate KeyStore - run: | - cd /opt/android/cake_wallet/android/app - keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass ${{ secrets.STORE_PASS }} -keypass ${{ secrets.KEY_PASS }} - - - name: Generate key properties - run: | - cd /opt/android/cake_wallet - flutter packages pub run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=${{ secrets.STORE_PASS }} keyPassword=${{ secrets.KEY_PASS }} - - - name: Generate localization - run: | - cd /opt/android/cake_wallet - flutter packages pub run tool/generate_localization.dart - - - name: Build generated code - run: | - cd /opt/android/cake_wallet - cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - flutter packages pub run build_runner build --delete-conflicting-outputs - - - name: Add secrets - run: | - cd /opt/android/cake_wallet - touch lib/.secrets.g.dart - echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart - echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart - echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart - echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart - echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart - echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart - echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart - echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart - echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart - echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart - echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart - echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart - echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart - echo "const sideShiftAffiliateId = '${{ secrets.SIDE_SHIFT_AFFILIATE_ID }}';" >> lib/.secrets.g.dart - echo "const sideShiftApiKey = '${{ secrets.SIDE_SHIFT_API_KEY }}';" >> lib/.secrets.g.dart - echo "const simpleSwapApiKey = '${{ secrets.SIMPLE_SWAP_API_KEY }}';" >> lib/.secrets.g.dart - echo "const onramperApiKey = '${{ secrets.ONRAMPER_API_KEY }}';" >> lib/.secrets.g.dart - echo "const anypayToken = '${{ secrets.ANY_PAY_TOKEN }}';" >> lib/.secrets.g.dart - echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart - - - name: Build - run: | - cd /opt/android/cake_wallet - flutter build apk --release +# - uses: actions/setup-java@v1 +# with: +# java-version: '8.x' +# +# - name: Flutter action +# uses: subosito/flutter-action@v1 +# with: +# flutter-version: '3.3.x' +# channel: stable +# +# - name: Install package dependencies +# run: sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang +# +# - name: Execute Build and Setup Commands +# run: | +# sudo mkdir -p /opt/android +# sudo chown $USER /opt/android +# cd /opt/android +# git clone https://github.com/cake-tech/cake_wallet.git --branch $GITHUB_HEAD_REF +# cd cake_wallet/scripts/android/ +# ./install_ndk.sh +# source ./app_env.sh cakewallet +# ./app_config.sh +# ./build_all.sh +# ./copy_monero_deps.sh +# +# - name: Install Flutter dependencies +# run: | +# cd /opt/android/cake_wallet +# flutter pub get +# +# - name: Generate KeyStore +# run: | +# cd /opt/android/cake_wallet/android/app +# keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass ${{ secrets.STORE_PASS }} -keypass ${{ secrets.KEY_PASS }} +# +# - name: Generate key properties +# run: | +# cd /opt/android/cake_wallet +# flutter packages pub run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=${{ secrets.STORE_PASS }} keyPassword=${{ secrets.KEY_PASS }} +# +# - name: Generate localization +# run: | +# cd /opt/android/cake_wallet +# flutter packages pub run tool/generate_localization.dart +# +# - name: Build generated code +# run: | +# cd /opt/android/cake_wallet +# cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +# cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +# cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +# cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +# flutter packages pub run build_runner build --delete-conflicting-outputs +# +# - name: Add secrets +# run: | +# cd /opt/android/cake_wallet +# touch lib/.secrets.g.dart +# echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart +# echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart +# echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart +# echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart +# echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart +# echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart +# echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart +# echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart +# echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart +# echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart +# echo "const sideShiftAffiliateId = '${{ secrets.SIDE_SHIFT_AFFILIATE_ID }}';" >> lib/.secrets.g.dart +# echo "const sideShiftApiKey = '${{ secrets.SIDE_SHIFT_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const simpleSwapApiKey = '${{ secrets.SIMPLE_SWAP_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const onramperApiKey = '${{ secrets.ONRAMPER_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const anypayToken = '${{ secrets.ANY_PAY_TOKEN }}';" >> lib/.secrets.g.dart +# echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart +# +# - name: Build +# run: | +# cd /opt/android/cake_wallet +# flutter build apk --release # - name: Push to App Center # run: | @@ -108,9 +108,26 @@ jobs: # --token ${{ secrets.APP_CENTER_TOKEN }} \ # --quiet +# - name: Send Test APK +# run: | +# cd /opt/android/cake_wallet +# var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/app-release.apk) +# curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' + + - name: Send Test APK run: | - cd /opt/android/cake_wallet - var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/app-release.apk) + var=$(curl --upload-file pubspec_base.yaml https://transfer.sh/$GITHUB_HEAD_REF.apk) curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' + - name: Rename apk + - run: | + mv pubspec_base.yaml $GITHUB_HEAD_REF.apk + ls + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: test-apks-artifacts + path: $GITHUB_HEAD_REF.apk + From b70838a308d7f3c9ef209ef7a1f3cc2245737297 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:16:04 +0200 Subject: [PATCH 057/203] Upload APK to github artifacts Rename apk --- .github/workflows/pr_test_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 398f1edd5..cdab77afb 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -121,7 +121,7 @@ jobs: curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' - name: Rename apk - - run: | + run: | mv pubspec_base.yaml $GITHUB_HEAD_REF.apk ls From b62e4cb0648a0014b5fbd339f52c06d03cae1ea8 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:19:43 +0200 Subject: [PATCH 058/203] fix artifact path --- .github/workflows/pr_test_build.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index cdab77afb..e016cbf8f 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -111,15 +111,9 @@ jobs: # - name: Send Test APK # run: | # cd /opt/android/cake_wallet -# var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/app-release.apk) +# var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/$GITHUB_HEAD_REF.apk) # curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' - - - name: Send Test APK - run: | - var=$(curl --upload-file pubspec_base.yaml https://transfer.sh/$GITHUB_HEAD_REF.apk) - curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' - - name: Rename apk run: | mv pubspec_base.yaml $GITHUB_HEAD_REF.apk @@ -129,5 +123,5 @@ jobs: uses: actions/upload-artifact@v3 with: name: test-apks-artifacts - path: $GITHUB_HEAD_REF.apk + path: "\${{GITHUB_HEAD_REF}}.apk" From fb2e7306ad5949497e286f829297796d3f7deb5c Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:23:58 +0200 Subject: [PATCH 059/203] fix artifact path --- .github/workflows/pr_test_build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index e016cbf8f..d09b938b3 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -116,12 +116,13 @@ jobs: - name: Rename apk run: | - mv pubspec_base.yaml $GITHUB_HEAD_REF.apk + mkdir test-apk + mv pubspec_base.yaml test-apk/$GITHUB_HEAD_REF.apk ls - name: Upload Artifact uses: actions/upload-artifact@v3 with: name: test-apks-artifacts - path: "\${{GITHUB_HEAD_REF}}.apk" + path: test-apk/* From 28f1afd972b1dcab96a5ff76ffdbafe91f2ec17d Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:26:39 +0200 Subject: [PATCH 060/203] try different file --- .github/workflows/pr_test_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index d09b938b3..71c8a6d0e 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -117,7 +117,7 @@ jobs: - name: Rename apk run: | mkdir test-apk - mv pubspec_base.yaml test-apk/$GITHUB_HEAD_REF.apk + mv pubspec_base.yaml test-apk/second-test.apk ls - name: Upload Artifact From 9b20af929204cb6cb0913ccfa101ef14c59cb4ca Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:33:09 +0200 Subject: [PATCH 061/203] try different file --- .github/workflows/pr_test_build.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 71c8a6d0e..b2639e5e7 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -114,15 +114,22 @@ jobs: # var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/$GITHUB_HEAD_REF.apk) # curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' +# - name: Rename apk +# run: | +# cd /opt/android/cake_wallet/build/app/outputs/apk/release +# mkdir test-apk +# mv app-release.apk test-apk/$GITHUB_HEAD_REF.apk + - name: Rename apk run: | mkdir test-apk - mv pubspec_base.yaml test-apk/second-test.apk + mv pubspec_base.yaml test-apk/$GITHUB_HEAD_REF.apk + cd test-apk ls - name: Upload Artifact uses: actions/upload-artifact@v3 with: name: test-apks-artifacts - path: test-apk/* + path: test-apk/"$GITHUB_HEAD_REF".apk From 1198b164556380c8b63e1f011d2afc61ecbf877d Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:37:56 +0200 Subject: [PATCH 062/203] Try uploading single apk file --- .github/workflows/pr_test_build.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index b2639e5e7..595ff3def 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -126,10 +126,22 @@ jobs: mv pubspec_base.yaml test-apk/$GITHUB_HEAD_REF.apk cd test-apk ls + apkPath=pwd/$GITHUB_HEAD_REF.apk + echo "====================" + echo apkPath + echo "====================" - name: Upload Artifact + continue-on-error: true uses: actions/upload-artifact@v3 with: name: test-apks-artifacts - path: test-apk/"$GITHUB_HEAD_REF".apk + path: apkPath + + - name: Upload Artifact + continue-on-error: true + uses: actions/upload-artifact@v3 + with: + name: test-apks-artifacts + path: $apkPath From 0c8636a77856f93b2c901abcce7367c6b452a691 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:46:03 +0200 Subject: [PATCH 063/203] Try uploading renamed apk file --- .github/workflows/pr_test_build.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 595ff3def..01895c1fb 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -128,20 +128,30 @@ jobs: ls apkPath=pwd/$GITHUB_HEAD_REF.apk echo "====================" - echo apkPath + echo $apkPath echo "====================" + echo "artifactPath=test-apk/${{ GITHUB_HEAD_REF.apk }}" >> $GITHUB_ENV + echo ${{ env.artifactPath }} - name: Upload Artifact continue-on-error: true uses: actions/upload-artifact@v3 with: name: test-apks-artifacts - path: apkPath + path: test-apk/${{ GITHUB_HEAD_REF }}.apk - name: Upload Artifact continue-on-error: true uses: actions/upload-artifact@v3 with: name: test-apks-artifacts - path: $apkPath + path: ${{ apkPath }} + + - name: Upload Artifact + continue-on-error: true + uses: actions/upload-artifact@v3 + with: + name: test-apks-artifacts + path: ${{ env.artifactPath }} + retention-days: 30 From e78ef3c201a385b0fb40e478cf9444b74e93bfda Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:48:01 +0200 Subject: [PATCH 064/203] Try uploading renamed apk file --- .github/workflows/pr_test_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 01895c1fb..8a8760aad 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -126,7 +126,7 @@ jobs: mv pubspec_base.yaml test-apk/$GITHUB_HEAD_REF.apk cd test-apk ls - apkPath=pwd/$GITHUB_HEAD_REF.apk + apkPath=pwd/${{ GITHUB_HEAD_REF }}.apk echo "====================" echo $apkPath echo "====================" From 12f4b9339c1659711137e9b2a4b59757a7b63f82 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:50:46 +0200 Subject: [PATCH 065/203] Try uploading renamed apk file --- .github/workflows/pr_test_build.yml | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 8a8760aad..818b0b8c9 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -126,12 +126,16 @@ jobs: mv pubspec_base.yaml test-apk/$GITHUB_HEAD_REF.apk cd test-apk ls - apkPath=pwd/${{ GITHUB_HEAD_REF }}.apk + apkPath=pwd/$GITHUB_HEAD_REF.apk echo "====================" echo $apkPath echo "====================" - echo "artifactPath=test-apk/${{ GITHUB_HEAD_REF.apk }}" >> $GITHUB_ENV + echo "artifactPath=test-apk/$GITHUB_HEAD_REF.apk" >> $GITHUB_ENV + echo "artifactPath2=test-apk/\$GITHUB_HEAD_REF.apk" >> $GITHUB_ENV + echo "artifactPath3=test-apk/\${{ GITHUB_HEAD_REF.apk }}" >> $GITHUB_ENV echo ${{ env.artifactPath }} + echo ${{ env.artifactPath2 }} + echo ${{ env.artifactPath3 }} - name: Upload Artifact continue-on-error: true @@ -153,5 +157,21 @@ jobs: with: name: test-apks-artifacts path: ${{ env.artifactPath }} - retention-days: 30 + retention-days: 1 + + - name: Upload Artifact + continue-on-error: true + uses: actions/upload-artifact@v3 + with: + name: test-apks-artifacts + path: ${{ env.artifactPath2 }} + retention-days: 1 + + - name: Upload Artifact + continue-on-error: true + uses: actions/upload-artifact@v3 + with: + name: test-apks-artifacts + path: ${{ env.artifactPath3 }} + retention-days: 1 From 71989cf6d79e977d772d55b8b5c232db824ef83b Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:52:04 +0200 Subject: [PATCH 066/203] Try uploading renamed apk file --- .github/workflows/pr_test_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 818b0b8c9..f1dae682b 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -142,7 +142,7 @@ jobs: uses: actions/upload-artifact@v3 with: name: test-apks-artifacts - path: test-apk/${{ GITHUB_HEAD_REF }}.apk + path: test-apk/${{ $GITHUB_HEAD_REF }}.apk - name: Upload Artifact continue-on-error: true From 8daf20753bd9ad9ff60bb70addb494188d29620c Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:52:33 +0200 Subject: [PATCH 067/203] Try uploading renamed apk file --- .github/workflows/pr_test_build.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index f1dae682b..523f70725 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -137,13 +137,6 @@ jobs: echo ${{ env.artifactPath2 }} echo ${{ env.artifactPath3 }} - - name: Upload Artifact - continue-on-error: true - uses: actions/upload-artifact@v3 - with: - name: test-apks-artifacts - path: test-apk/${{ $GITHUB_HEAD_REF }}.apk - - name: Upload Artifact continue-on-error: true uses: actions/upload-artifact@v3 From 903cd7bf6f10c922765b42f29cd961500b6aef04 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:53:15 +0200 Subject: [PATCH 068/203] Try uploading renamed apk file --- .github/workflows/pr_test_build.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 523f70725..d9509e813 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -137,13 +137,6 @@ jobs: echo ${{ env.artifactPath2 }} echo ${{ env.artifactPath3 }} - - name: Upload Artifact - continue-on-error: true - uses: actions/upload-artifact@v3 - with: - name: test-apks-artifacts - path: ${{ apkPath }} - - name: Upload Artifact continue-on-error: true uses: actions/upload-artifact@v3 From e516bd7a07e6b55ad389cede51dafcb0ce842912 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:55:29 +0200 Subject: [PATCH 069/203] Try uploading renamed apk file --- .github/workflows/pr_test_build.yml | 38 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index d9509e813..9e9393ed9 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -131,11 +131,11 @@ jobs: echo $apkPath echo "====================" echo "artifactPath=test-apk/$GITHUB_HEAD_REF.apk" >> $GITHUB_ENV - echo "artifactPath2=test-apk/\$GITHUB_HEAD_REF.apk" >> $GITHUB_ENV - echo "artifactPath3=test-apk/\${{ GITHUB_HEAD_REF.apk }}" >> $GITHUB_ENV +# echo "artifactPath2=test-apk/\$GITHUB_HEAD_REF.apk" >> $GITHUB_ENV +# echo "artifactPath3=test-apk/\${{ GITHUB_HEAD_REF.apk }}" >> $GITHUB_ENV echo ${{ env.artifactPath }} - echo ${{ env.artifactPath2 }} - echo ${{ env.artifactPath3 }} +# echo ${{ env.artifactPath2 }} +# echo ${{ env.artifactPath3 }} - name: Upload Artifact continue-on-error: true @@ -145,19 +145,19 @@ jobs: path: ${{ env.artifactPath }} retention-days: 1 - - name: Upload Artifact - continue-on-error: true - uses: actions/upload-artifact@v3 - with: - name: test-apks-artifacts - path: ${{ env.artifactPath2 }} - retention-days: 1 - - - name: Upload Artifact - continue-on-error: true - uses: actions/upload-artifact@v3 - with: - name: test-apks-artifacts - path: ${{ env.artifactPath3 }} - retention-days: 1 +# - name: Upload Artifact +# continue-on-error: true +# uses: actions/upload-artifact@v3 +# with: +# name: test-apks-artifacts +# path: ${{ env.artifactPath2 }} +# retention-days: 1 +# +# - name: Upload Artifact +# continue-on-error: true +# uses: actions/upload-artifact@v3 +# with: +# name: test-apks-artifacts +# path: ${{ env.artifactPath3 }} +# retention-days: 1 From bd1a5cf3f7733a1cf426f40364346d213a2e3ef7 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 14:56:27 +0200 Subject: [PATCH 070/203] Try uploading renamed apk file --- .github/workflows/pr_test_build.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 9e9393ed9..0304171b8 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -131,11 +131,7 @@ jobs: echo $apkPath echo "====================" echo "artifactPath=test-apk/$GITHUB_HEAD_REF.apk" >> $GITHUB_ENV -# echo "artifactPath2=test-apk/\$GITHUB_HEAD_REF.apk" >> $GITHUB_ENV -# echo "artifactPath3=test-apk/\${{ GITHUB_HEAD_REF.apk }}" >> $GITHUB_ENV echo ${{ env.artifactPath }} -# echo ${{ env.artifactPath2 }} -# echo ${{ env.artifactPath3 }} - name: Upload Artifact continue-on-error: true From 5364dd87107c8699690a25bd394a171bedb550de Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 15:01:20 +0200 Subject: [PATCH 071/203] Try uploading renamed apk file --- .github/workflows/pr_test_build.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 0304171b8..5121be130 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -135,11 +135,9 @@ jobs: - name: Upload Artifact continue-on-error: true - uses: actions/upload-artifact@v3 + uses: kittaakos/upload-artifact-as-is@v0 with: - name: test-apks-artifacts - path: ${{ env.artifactPath }} - retention-days: 1 + path: test-apk/ # - name: Upload Artifact # continue-on-error: true From e264cb326db4f75dbd764d8fcd2c5978ca270592 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 15:15:56 +0200 Subject: [PATCH 072/203] Try uploading renamed apk file --- .github/workflows/pr_test_build.yml | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 5121be130..8b038687b 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -124,34 +124,8 @@ jobs: run: | mkdir test-apk mv pubspec_base.yaml test-apk/$GITHUB_HEAD_REF.apk - cd test-apk - ls - apkPath=pwd/$GITHUB_HEAD_REF.apk - echo "====================" - echo $apkPath - echo "====================" - echo "artifactPath=test-apk/$GITHUB_HEAD_REF.apk" >> $GITHUB_ENV - echo ${{ env.artifactPath }} - name: Upload Artifact - continue-on-error: true uses: kittaakos/upload-artifact-as-is@v0 with: path: test-apk/ - -# - name: Upload Artifact -# continue-on-error: true -# uses: actions/upload-artifact@v3 -# with: -# name: test-apks-artifacts -# path: ${{ env.artifactPath2 }} -# retention-days: 1 -# -# - name: Upload Artifact -# continue-on-error: true -# uses: actions/upload-artifact@v3 -# with: -# name: test-apks-artifacts -# path: ${{ env.artifactPath3 }} -# retention-days: 1 - From d38b3b0e0675a8c3e1dadef067981298c111c283 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 15:19:51 +0200 Subject: [PATCH 073/203] Finalize upload to artifacts and renaming --- .github/workflows/pr_test_build.yml | 187 ++++++++++++++-------------- 1 file changed, 91 insertions(+), 96 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 8b038687b..5611fe578 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -11,89 +11,89 @@ jobs: steps: - uses: actions/checkout@v2 -# - uses: actions/setup-java@v1 -# with: -# java-version: '8.x' -# -# - name: Flutter action -# uses: subosito/flutter-action@v1 -# with: -# flutter-version: '3.3.x' -# channel: stable -# -# - name: Install package dependencies -# run: sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang -# -# - name: Execute Build and Setup Commands -# run: | -# sudo mkdir -p /opt/android -# sudo chown $USER /opt/android -# cd /opt/android -# git clone https://github.com/cake-tech/cake_wallet.git --branch $GITHUB_HEAD_REF -# cd cake_wallet/scripts/android/ -# ./install_ndk.sh -# source ./app_env.sh cakewallet -# ./app_config.sh -# ./build_all.sh -# ./copy_monero_deps.sh -# -# - name: Install Flutter dependencies -# run: | -# cd /opt/android/cake_wallet -# flutter pub get -# -# - name: Generate KeyStore -# run: | -# cd /opt/android/cake_wallet/android/app -# keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass ${{ secrets.STORE_PASS }} -keypass ${{ secrets.KEY_PASS }} -# -# - name: Generate key properties -# run: | -# cd /opt/android/cake_wallet -# flutter packages pub run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=${{ secrets.STORE_PASS }} keyPassword=${{ secrets.KEY_PASS }} -# -# - name: Generate localization -# run: | -# cd /opt/android/cake_wallet -# flutter packages pub run tool/generate_localization.dart -# -# - name: Build generated code -# run: | -# cd /opt/android/cake_wallet -# cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -# cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -# cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -# cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -# flutter packages pub run build_runner build --delete-conflicting-outputs -# -# - name: Add secrets -# run: | -# cd /opt/android/cake_wallet -# touch lib/.secrets.g.dart -# echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart -# echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart -# echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart -# echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart -# echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart -# echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart -# echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart -# echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart -# echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart -# echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart -# echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart -# echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart -# echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart -# echo "const sideShiftAffiliateId = '${{ secrets.SIDE_SHIFT_AFFILIATE_ID }}';" >> lib/.secrets.g.dart -# echo "const sideShiftApiKey = '${{ secrets.SIDE_SHIFT_API_KEY }}';" >> lib/.secrets.g.dart -# echo "const simpleSwapApiKey = '${{ secrets.SIMPLE_SWAP_API_KEY }}';" >> lib/.secrets.g.dart -# echo "const onramperApiKey = '${{ secrets.ONRAMPER_API_KEY }}';" >> lib/.secrets.g.dart -# echo "const anypayToken = '${{ secrets.ANY_PAY_TOKEN }}';" >> lib/.secrets.g.dart -# echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart -# -# - name: Build -# run: | -# cd /opt/android/cake_wallet -# flutter build apk --release + - uses: actions/setup-java@v1 + with: + java-version: '8.x' + + - name: Flutter action + uses: subosito/flutter-action@v1 + with: + flutter-version: '3.3.x' + channel: stable + + - name: Install package dependencies + run: sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang + + - name: Execute Build and Setup Commands + run: | + sudo mkdir -p /opt/android + sudo chown $USER /opt/android + cd /opt/android + git clone https://github.com/cake-tech/cake_wallet.git --branch $GITHUB_HEAD_REF + cd cake_wallet/scripts/android/ + ./install_ndk.sh + source ./app_env.sh cakewallet + ./app_config.sh + ./build_all.sh + ./copy_monero_deps.sh + + - name: Install Flutter dependencies + run: | + cd /opt/android/cake_wallet + flutter pub get + + - name: Generate KeyStore + run: | + cd /opt/android/cake_wallet/android/app + keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass ${{ secrets.STORE_PASS }} -keypass ${{ secrets.KEY_PASS }} + + - name: Generate key properties + run: | + cd /opt/android/cake_wallet + flutter packages pub run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=${{ secrets.STORE_PASS }} keyPassword=${{ secrets.KEY_PASS }} + + - name: Generate localization + run: | + cd /opt/android/cake_wallet + flutter packages pub run tool/generate_localization.dart + + - name: Build generated code + run: | + cd /opt/android/cake_wallet + cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + flutter packages pub run build_runner build --delete-conflicting-outputs + + - name: Add secrets + run: | + cd /opt/android/cake_wallet + touch lib/.secrets.g.dart + echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart + echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart + echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart + echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart + echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart + echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart + echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart + echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart + echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart + echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart + echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart + echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart + echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart + echo "const sideShiftAffiliateId = '${{ secrets.SIDE_SHIFT_AFFILIATE_ID }}';" >> lib/.secrets.g.dart + echo "const sideShiftApiKey = '${{ secrets.SIDE_SHIFT_API_KEY }}';" >> lib/.secrets.g.dart + echo "const simpleSwapApiKey = '${{ secrets.SIMPLE_SWAP_API_KEY }}';" >> lib/.secrets.g.dart + echo "const onramperApiKey = '${{ secrets.ONRAMPER_API_KEY }}';" >> lib/.secrets.g.dart + echo "const anypayToken = '${{ secrets.ANY_PAY_TOKEN }}';" >> lib/.secrets.g.dart + echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart + + - name: Build + run: | + cd /opt/android/cake_wallet + flutter build apk --release # - name: Push to App Center # run: | @@ -108,24 +108,19 @@ jobs: # --token ${{ secrets.APP_CENTER_TOKEN }} \ # --quiet -# - name: Send Test APK -# run: | -# cd /opt/android/cake_wallet -# var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/$GITHUB_HEAD_REF.apk) -# curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' - -# - name: Rename apk -# run: | -# cd /opt/android/cake_wallet/build/app/outputs/apk/release -# mkdir test-apk -# mv app-release.apk test-apk/$GITHUB_HEAD_REF.apk + - name: Send Test APK + run: | + cd /opt/android/cake_wallet + var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/$GITHUB_HEAD_REF.apk) + curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' - name: Rename apk run: | + cd /opt/android/cake_wallet/build/app/outputs/apk/release mkdir test-apk - mv pubspec_base.yaml test-apk/$GITHUB_HEAD_REF.apk + mv app-release.apk test-apk/$GITHUB_HEAD_REF.apk - name: Upload Artifact uses: kittaakos/upload-artifact-as-is@v0 with: - path: test-apk/ + path: /opt/android/cake_wallet/build/app/outputs/apk/release/test-apk/ From 03a64b16859eb8951de25f66eed9b98787457c61 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 29 Nov 2022 15:49:24 +0200 Subject: [PATCH 074/203] Rename app and apk to ease testing process --- .github/workflows/pr_test_build.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 5611fe578..190b891e1 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -90,6 +90,9 @@ jobs: echo "const anypayToken = '${{ secrets.ANY_PAY_TOKEN }}';" >> lib/.secrets.g.dart echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart + - name: Rename app + run: sed -i -e "s/\${APP_NAME}/$GITHUB_HEAD_REF/g" /opt/android/cake_wallet/android/app/src/main/AndroidManifest.xml + - name: Build run: | cd /opt/android/cake_wallet @@ -111,10 +114,10 @@ jobs: - name: Send Test APK run: | cd /opt/android/cake_wallet - var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/$GITHUB_HEAD_REF.apk) + var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/$GITHUB_HEAD_REF.apk -H "Max-Days: 10") curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' - - name: Rename apk + - name: Rename apk file run: | cd /opt/android/cake_wallet/build/app/outputs/apk/release mkdir test-apk From 6685fb580485eda3b7e1f77e24b43b3f79cdc28a Mon Sep 17 00:00:00 2001 From: Justin Ehrenhofer Date: Tue, 29 Nov 2022 11:05:38 -0600 Subject: [PATCH 075/203] [CW-257] Change Bitcoin block explorer to mempool.space --- lib/view_model/transaction_details_view_model.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index 8992071fd..f8729715b 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -184,7 +184,7 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.monero: return 'https://monero.com/tx/${txId}'; case WalletType.bitcoin: - return 'https://www.blockchain.com/btc/tx/${txId}'; + return 'https://mempool.space/tx/${txId}'; case WalletType.litecoin: return 'https://blockchair.com/litecoin/transaction/${txId}'; case WalletType.haven: @@ -199,7 +199,7 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.monero: return S.current.view_transaction_on + 'Monero.com'; case WalletType.bitcoin: - return S.current.view_transaction_on + 'Blockchain.com'; + return S.current.view_transaction_on + 'mempool.space'; case WalletType.litecoin: return S.current.view_transaction_on + 'Blockchair.com'; case WalletType.haven: From 0fda0531507073286afa7a21c64163aefab87cb8 Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 29 Nov 2022 21:53:07 +0200 Subject: [PATCH 076/203] remove Hive from CryptoCurrency --- cw_core/lib/crypto_currency.dart | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index bcefe89f6..686064f09 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -1,20 +1,16 @@ import 'package:cw_core/enumerable_item.dart'; -import 'package:hive/hive.dart'; -part 'crypto_currency.g.dart'; - -@HiveType(typeId: 0) class CryptoCurrency extends EnumerableItem with Serializable { const CryptoCurrency({ String title = '', int raw = -1, - this.name, + required this.name, this.fullName, this.iconPath, this.tag}) : super(title: title, raw: raw); - final String? name; + final String name; final String? tag; final String? fullName; final String? iconPath; From 59ee7aa975750ba17071916d4bd71c2a8cb19543 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 30 Nov 2022 01:37:56 +0200 Subject: [PATCH 077/203] Add onion node to already existing users --- lib/entities/default_settings_migration.dart | 22 ++++++++++++++------ lib/main.dart | 2 +- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index fb404cd88..27ada0b0c 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -135,19 +135,29 @@ Future defaultSettingsMigration( await changeDefaultHavenNode(nodes); break; + case 18: + await addOnionNode(nodes); + break; + default: break; } await sharedPreferences.setInt( - 'current_default_settings_migration_version', version); + PreferencesKey.currentDefaultSettingsMigrationVersion, version); } catch (e) { print('Migration error: ${e.toString()}'); } }); await sharedPreferences.setInt( - 'current_default_settings_migration_version', version); + PreferencesKey.currentDefaultSettingsMigrationVersion, version); +} + +Future addOnionNode(Box nodes) async { + final onionNodeUri = "cakexmrl7bonq7ovjka5kuwuyd3f7qnkz6z6s6dmsy3uckwra7bvggyd.onion:18081"; + + await nodes.add(Node(uri: onionNodeUri, type: WalletType.monero)); } Future replaceNodesMigration({required Box nodes}) async { @@ -178,7 +188,7 @@ Future changeMoneroCurrentNodeToDefault( final node = getMoneroDefaultNode(nodes: nodes); final nodeId = node?.key as int ?? 0; // 0 - England - await sharedPreferences.setInt('current_node_id', nodeId); + await sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, nodeId); } Node? getBitcoinDefaultElectrumServer({required Box nodes}) { @@ -225,7 +235,7 @@ Future changeBitcoinCurrentElectrumServerToDefault( final server = getBitcoinDefaultElectrumServer(nodes: nodes); final serverId = server?.key as int ?? 0; - await sharedPreferences.setInt('current_node_id_btc', serverId); + await sharedPreferences.setInt(PreferencesKey.currentBitcoinElectrumSererIdKey, serverId); } Future changeLitecoinCurrentElectrumServerToDefault( @@ -234,7 +244,7 @@ Future changeLitecoinCurrentElectrumServerToDefault( final server = getLitecoinDefaultElectrumServer(nodes: nodes); final serverId = server?.key as int ?? 0; - await sharedPreferences.setInt('current_node_id_ltc', serverId); + await sharedPreferences.setInt(PreferencesKey.currentLitecoinElectrumSererIdKey, serverId); } Future changeHavenCurrentNodeToDefault( @@ -254,7 +264,7 @@ Future replaceDefaultNode( 'eu-node.cakewallet.io:18081', 'node.cakewallet.io:18081' ]; - final currentNodeId = sharedPreferences.getInt('current_node_id'); + final currentNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final currentNode = nodes.values.firstWhereOrNull((Node node) => node.key == currentNodeId); final needToReplace = diff --git a/lib/main.dart b/lib/main.dart index 3cd5679b3..e1fade7b4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -128,7 +128,7 @@ Future main() async { exchangeTemplates: exchangeTemplates, transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, - initialMigrationVersion: 17); + initialMigrationVersion: 18); runApp(App()); } catch (e, stacktrace) { runApp(MaterialApp( From 8511805ee35fca9ddbf5818fb50622dc305c180b Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 30 Nov 2022 10:00:05 +0200 Subject: [PATCH 078/203] Fix correct adjusted amount for custom redeem --- lib/ionia/ionia_gift_card.dart | 2 +- lib/ionia/ionia_service.dart | 4 +-- .../ionia/cards/ionia_custom_redeem_page.dart | 2 +- .../cards/ionia_gift_card_detail_page.dart | 28 +++++++++---------- .../ionia/cards/ionia_more_options_page.dart | 6 ++-- .../ionia/widgets/ionia_filter_modal.dart | 2 +- .../ionia_gift_card_details_view_model.dart | 10 +++++-- 7 files changed, 29 insertions(+), 25 deletions(-) diff --git a/lib/ionia/ionia_gift_card.dart b/lib/ionia/ionia_gift_card.dart index b729e261f..04b45b907 100644 --- a/lib/ionia/ionia_gift_card.dart +++ b/lib/ionia/ionia_gift_card.dart @@ -37,7 +37,7 @@ class IoniaGiftCard { purchaseAmount: element['PurchaseAmount'] as double, actualAmount: element['ActualAmount'] as double, totalTransactionAmount: element['TotalTransactionAmount'] as double, - totalDashTransactionAmount: element['TotalDashTransactionAmount'] as double, + totalDashTransactionAmount: element['TotalDashTransactionAmount'] != null ? element['TotalDashTransactionAmount'] as double : 0.0, remainingAmount: element['RemainingAmount'] as double, isActive: element['IsActive'] as bool, isEmpty: element['IsEmpty'] as bool, diff --git a/lib/ionia/ionia_service.dart b/lib/ionia/ionia_service.dart index 942bc25b5..51e23ad28 100644 --- a/lib/ionia/ionia_service.dart +++ b/lib/ionia/ionia_service.dart @@ -148,8 +148,8 @@ class IoniaService { // Redeem - Future redeem(IoniaGiftCard giftCard) async { - await chargeGiftCard(giftCardId: giftCard.id, amount: giftCard.remainingAmount); + Future redeem({required int giftCardId, required double amount}) async { + await chargeGiftCard(giftCardId: giftCardId, amount: amount); } // Get Gift Card diff --git a/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart b/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart index 53e41ff22..f9ce0ae88 100644 --- a/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart +++ b/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart @@ -149,7 +149,7 @@ class IoniaCustomRedeemPage extends BasePage { padding: EdgeInsets.only(bottom: 12), child: PrimaryButton( onPressed: () { - Navigator.of(context).pop(ioniaCustomRedeemViewModel.remaining.toString()); + Navigator.of(context).pop([ioniaCustomRedeemViewModel.remaining.toString(), ioniaCustomRedeemViewModel.amount.toString()]); }, isDisabled: ioniaCustomRedeemViewModel.disableRedeem, text: S.of(context).add_custom_redemption, diff --git a/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart b/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart index 1c768fa17..2e7162e40 100644 --- a/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart +++ b/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart @@ -130,19 +130,19 @@ class IoniaGiftCardDetailPage extends BasePage { if (!viewModel.giftCard.isEmpty) { return Column( children: [ - //PrimaryButton( - // onPressed: () async { - // final amount = await Navigator.of(context) - // .pushNamed(Routes.ioniaMoreOptionsPage, arguments: [viewModel.giftCard]) as String; - // if (amount != null) { - // viewModel.updateRemaining(double.parse(amount)); - // } - // }, - // text: S.of(context).more_options, - // color: Theme.of(context).accentTextTheme!.caption!.color!, - // textColor: Theme.of(context).primaryTextTheme!.headline6!.color!, - //), - //SizedBox(height: 12), + PrimaryButton( + onPressed: () async { + final amount = await Navigator.of(context) + .pushNamed(Routes.ioniaMoreOptionsPage, arguments: [viewModel.giftCard]) as List?; + if (amount != null) { + viewModel.updateRemaining( balance: double.parse(amount.first), customAmount: double.parse(amount.last)); + } + }, + text: S.of(context).more_options, + color: Theme.of(context).accentTextTheme.caption!.color!, + textColor: Theme.of(context).primaryTextTheme.headline6!.color!, + ), + SizedBox(height: 12), LoadingPrimaryButton( isLoading: viewModel.redeemState is IsExecutingState, onPressed: () => viewModel.redeem().then( @@ -152,7 +152,7 @@ class IoniaGiftCardDetailPage extends BasePage { }, ), text: S.of(context).mark_as_redeemed, - color: Theme.of(context).accentTextTheme!.bodyText1!.color!, + color: Theme.of(context).accentTextTheme.bodyText1!.color!, textColor: Colors.white, ), ], diff --git a/lib/src/screens/ionia/cards/ionia_more_options_page.dart b/lib/src/screens/ionia/cards/ionia_more_options_page.dart index 84f0bed30..d4e378f84 100644 --- a/lib/src/screens/ionia/cards/ionia_more_options_page.dart +++ b/lib/src/screens/ionia/cards/ionia_more_options_page.dart @@ -35,9 +35,9 @@ class IoniaMoreOptionsPage extends BasePage { SizedBox(height: 40,), InkWell( onTap: () async { - final amount = await Navigator.of(context).pushNamed(Routes.ioniaCustomRedeemPage, arguments: [giftCard]) as String; - if(amount.isNotEmpty){ - Navigator.pop(context, amount); + final amounts = await Navigator.of(context).pushNamed(Routes.ioniaCustomRedeemPage, arguments: [giftCard]) as List; + if(amounts.first.isNotEmpty){ + Navigator.pop(context, amounts); } }, child: _GradiantContainer( diff --git a/lib/src/screens/ionia/widgets/ionia_filter_modal.dart b/lib/src/screens/ionia/widgets/ionia_filter_modal.dart index ec6e84cc0..b6bcac070 100644 --- a/lib/src/screens/ionia/widgets/ionia_filter_modal.dart +++ b/lib/src/screens/ionia/widgets/ionia_filter_modal.dart @@ -53,7 +53,7 @@ class IoniaFilterModal extends StatelessWidget { prefixIcon: searchIcon, hintText: S.of(context).search_category, contentPadding: EdgeInsets.only(bottom: 5), - fillColor: Theme.of(context).textTheme!.subtitle1!.backgroundColor!, + fillColor: Theme.of(context).textTheme.subtitle1?.backgroundColor, border: OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.circular(8), diff --git a/lib/view_model/ionia/ionia_gift_card_details_view_model.dart b/lib/view_model/ionia/ionia_gift_card_details_view_model.dart index 8e0a2795b..745f2d530 100644 --- a/lib/view_model/ionia/ionia_gift_card_details_view_model.dart +++ b/lib/view_model/ionia/ionia_gift_card_details_view_model.dart @@ -15,6 +15,7 @@ abstract class IoniaGiftCardDetailsViewModelBase with Store { required this.giftCard}) : redeemState = InitialExecutionState(), remainingAmount = giftCard.remainingAmount, + adjustedAmount = 0, brightness = 0; final IoniaService ioniaService; @@ -27,6 +28,8 @@ abstract class IoniaGiftCardDetailsViewModelBase with Store { @observable double remainingAmount; + double adjustedAmount; + @observable ExecutionState redeemState; @@ -35,7 +38,7 @@ abstract class IoniaGiftCardDetailsViewModelBase with Store { giftCard.remainingAmount = remainingAmount; try { redeemState = IsExecutingState(); - await ioniaService.redeem(giftCard); + await ioniaService.redeem(giftCardId: giftCard.id, amount : adjustedAmount > 0 ? adjustedAmount : giftCard.remainingAmount); giftCard = await ioniaService.getGiftCard(id: giftCard.id); redeemState = ExecutedSuccessfullyState(); } catch(e) { @@ -44,8 +47,9 @@ abstract class IoniaGiftCardDetailsViewModelBase with Store { } @action - void updateRemaining(double amount){ - remainingAmount = amount; + void updateRemaining({required double balance, required double customAmount}) { + remainingAmount = balance; + adjustedAmount = customAmount; } void increaseBrightness() async { From 28abb4ded0589915444f2d7a46653ae70b455848 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 30 Nov 2022 15:28:27 +0200 Subject: [PATCH 079/203] Add localization strings --- res/values/strings_de.arb | 3 +++ res/values/strings_es.arb | 3 +++ res/values/strings_fr.arb | 3 +++ res/values/strings_hi.arb | 3 +++ res/values/strings_hr.arb | 3 +++ res/values/strings_it.arb | 3 +++ res/values/strings_ja.arb | 3 +++ res/values/strings_ko.arb | 3 +++ res/values/strings_nl.arb | 3 +++ res/values/strings_pl.arb | 3 +++ res/values/strings_pt.arb | 3 +++ res/values/strings_ru.arb | 3 +++ res/values/strings_uk.arb | 3 +++ res/values/strings_zh.arb | 3 +++ 14 files changed, 42 insertions(+) diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index e4854066b..ca09f67d5 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -652,6 +652,9 @@ "use_suggested": "Vorgeschlagen verwenden", "do_not_share_warning_text" : "Teilen Sie diese nicht mit anderen, einschließlich des Supports.\n\nSie werden Ihr Geld stehlen!", "help": "hilfe", + "connection_sync": "Verbindung und Synchronisierung", + "security_and_backup": "Sicherheit und Datensicherung", + "create_backup": "Backup erstellen", "privacy_settings": "Datenschutzeinstellungen", "privacy": "Datenschutz", "display_settings": "Anzeigeeinstellungen", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 456f23dec..84b39e5b7 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -652,6 +652,9 @@ "use_suggested": "Usar sugerido", "do_not_share_warning_text" : "No comparta estos con nadie más, incluido el soporte.\n\n¡Te robarán tu dinero!", "help": "ayuda", + "connection_sync": "Conexión y sincronización", + "security_and_backup": "Seguridad y respaldo", + "create_backup": "Crear copia de seguridad", "privacy_settings": "Configuración de privacidad", "privacy": "Privacidad", "display_settings": "Configuración de pantalla", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index daae787b9..215b58245 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -650,6 +650,9 @@ "use_suggested": "Utilisation suggérée", "do_not_share_warning_text" : "Ne les partagez avec personne d'autre, y compris avec l'assistance.\n\nIls vont voler votre argent!", "help": "aider", + "connection_sync": "Connexion et synchronisation", + "security_and_backup": "Sécurité et sauvegarde", + "create_backup": "Créer une sauvegarde", "privacy_settings": "Paramètres de confidentialité", "privacy": "Confidentialité", "display_settings": "Paramètres d'affichage", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 532e8ede4..133432391 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -652,6 +652,9 @@ "use_suggested": "सुझाए गए का प्रयोग करें", "do_not_share_warning_text" : "इन्हें समर्थन सहित किसी और के साथ साझा न करें।\n\nवे आपका पैसा चुरा लेंगे!", "help": "मदद करना", + "connection_sync": "कनेक्शन और सिंक", + "security_and_backup": "सुरक्षा और बैकअप", + "create_backup": "बैकअप बनाएँ", "privacy_settings": "गोपनीयता सेटिंग्स", "privacy": "गोपनीयता", "display_settings": "प्रदर्शन सेटिंग्स", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index e5c8598e1..1e8820130 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -652,6 +652,9 @@ "use_suggested": "Koristite predloženo", "do_not_share_warning_text" : "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nUkrast će vam novac!", "help": "pomozite", + "connection_sync": "Povezivanje i sinkronizacija", + "security_and_backup": "Sigurnost i sigurnosna kopija", + "create_backup": "Stvori sigurnosnu kopiju", "privacy_settings": "Postavke privatnosti", "privacy": "Privatnost", "display_settings": "Postavke zaslona", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 0a557ebb1..d16a6ce83 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -652,6 +652,9 @@ "use_suggested": "Usa suggerito", "do_not_share_warning_text" : "Non condividerli con nessun altro, incluso il supporto.\n\nTi ruberanno i soldi!", "help": "aiuto", + "connection_sync": "Connessione e sincronizzazione", + "security_and_backup": "Sicurezza e backup", + "create_backup": "Crea backup", "privacy_settings": "Impostazioni privacy", "privacy": "Privacy", "display_settings": "Impostazioni di visualizzazione", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 16d88db49..c6a3f486c 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -652,6 +652,9 @@ "use_suggested": "推奨を使用", "do_not_share_warning_text" : "サポートを含め、これらを他の誰とも共有しないでください。\n\n彼らはあなたのお金を盗みます!", "help": "ヘルプ", + "connection_sync": "接続と同期", + "security_and_backup": "セキュリティとバックアップ", + "create_backup": "バックアップを作成", "privacy_settings": "プライバシー設定", "privacy": "プライバシー", "display_settings": "表示設定", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 99fe560ed..8aa917572 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -652,6 +652,9 @@ "use_suggested": "추천 사용", "do_not_share_warning_text" : "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n그들은 당신의 돈을 훔칠 것입니다!", "help": "돕다", + "connection_sync": "연결 및 동기화", + "security_and_backup": "보안 및 백업", + "create_backup": "백업 생성", "privacy_settings": "개인정보 설정", "privacy": "프라이버시", "display_settings": "디스플레이 설정", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index cc4c6bbb1..61382db9e 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -652,6 +652,9 @@ "use_suggested": "Gebruik aanbevolen", "do_not_share_warning_text" : "Deel deze met niemand anders, ook niet met support.\n\nZe zullen je geld stelen!", "help": "helpen", + "connection_sync": "Verbinding en synchronisatie", + "security_and_backup": "Beveiliging en back-up", + "create_backup": "Maak een back-up", "privacy_settings": "Privacy-instellingen", "privacy": "Privacy", "display_settings": "Weergave-instellingen", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 0d0159f7a..dbf43ccc0 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -652,6 +652,9 @@ "use_suggested": "Użyj sugerowane", "do_not_share_warning_text" : "Nie udostępniaj ich nikomu innemu, w tym wsparcia.\n\nUkradną twoje pieniądze!", "help": "pomoc", + "connection_sync": "Połączenie i synchronizacja", + "security_and_backup": "Bezpieczeństwo i kopia zapasowa", + "create_backup": "Utwórz kopię zapasową", "privacy_settings": "Ustawienia prywatności", "privacy": "Prywatność", "display_settings": "Ustawienia wyświetlania", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 6d87183ee..f5ecbf64e 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -652,6 +652,9 @@ "use_suggested": "Uso sugerido", "do_not_share_warning_text" : "Não os compartilhe com mais ninguém, incluindo suporte.\n\nEles vão roubar seu dinheiro!", "help": "ajuda", + "connection_sync": "Conexão e sincronização", + "security_and_backup": "Segurança e backup", + "create_backup": "Criar backup", "privacy_settings": "Configurações de privacidade", "privacy": "Privacidade", "display_settings": "Configurações de exibição", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index d2ec428c8..9be18510f 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -652,6 +652,9 @@ "use_suggested": "Использовать предложенный", "do_not_share_warning_text" : "Не делитесь ими с кем-либо еще, в том числе со службой поддержки.\n\nОни украдут ваши деньги!", "help": "помощь", + "connection_sync": "Подключение и синхронизация", + "security_and_backup": "Безопасность и резервное копирование", + "create_backup": "Создать резервную копию", "privacy_settings": "Настройки конфиденциальности", "privacy": "Конфиденциальность", "display_settings": "Настройки отображения", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 42170382e..6012c8289 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -651,6 +651,9 @@ "use_suggested": "Використати запропоноване", "do_not_share_warning_text" : "Не повідомляйте їх нікому, включно зі службою підтримки.\n\nВони вкрадуть ваші гроші!", "help": "допомога", + "connection_sync": "Підключення та синхронізація", + "security_and_backup": "Безпека та резервне копіювання", + "create_backup": "Створити резервну копію", "privacy_settings": "Налаштування конфіденційності", "privacy": "Конфіденційність", "display_settings": "Налаштування дисплея", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 8ffa37def..6d45f6d01 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -650,6 +650,9 @@ "use_suggested": "使用建议", "do_not_share_warning_text" : "不要與其他任何人分享這些內容,包括支持。\n\n他們會偷你的錢!", "help": "帮助", + "connection_sync": "连接和同步", + "security_and_backup": "安全和备份", + "create_backup": "创建备份", "privacy_settings": "隐私设置", "privacy":"隐私", "display_settings": "显示设置", From 0c28d83cbcb17a20053e6787732c0c291a292c23 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 30 Nov 2022 22:50:42 +0200 Subject: [PATCH 080/203] Fix authentication required when minimize app --- android/.project | 11 ++++++ .../org.eclipse.buildship.core.prefs | 13 ++++++- cw_monero/android/.project | 11 ++++++ ios/Podfile | 2 +- ios/Podfile.lock | 34 +++++++++---------- lib/src/screens/root/root.dart | 11 +++++- 6 files changed, 62 insertions(+), 20 deletions(-) diff --git a/android/.project b/android/.project index 17c95d4b1..93e645b27 100644 --- a/android/.project +++ b/android/.project @@ -14,4 +14,15 @@ org.eclipse.buildship.core.gradleprojectnature + + + 1668366526072 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs index 9d2efc8e7..52768efe3 100644 --- a/android/.settings/org.eclipse.buildship.core.prefs +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -1,2 +1,13 @@ +arguments=--init-script /var/folders/_g/6xnbffg10l741qh63jr5cds80000gp/T/d146c9752a26f79b52047fb6dc6ed385d064e120494f96f08ca63a317c41f94c.gradle --init-script /var/folders/_g/6xnbffg10l741qh63jr5cds80000gp/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle +auto.sync=false +build.scans.enabled=false +connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) connection.project.dir= -eclipse.preferences.version=1 \ No newline at end of file +eclipse.preferences.version=1 +gradle.user.home= +java.home=/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home +jvm.arguments= +offline.mode=false +override.workspace.settings=true +show.console.view=true +show.executions.view=true diff --git a/cw_monero/android/.project b/cw_monero/android/.project index e0799208f..15eb18708 100644 --- a/cw_monero/android/.project +++ b/cw_monero/android/.project @@ -20,4 +20,15 @@ org.eclipse.jdt.core.javanature org.eclipse.buildship.core.gradleprojectnature + + + 1668366526081 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/ios/Podfile b/ios/Podfile index b29d40484..d02ce2d3f 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '11.0' +platform :ios, '14.0' source 'https://github.com/CocoaPods/Specs.git' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 3a810430d..28ee07db9 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -7,7 +7,7 @@ PODS: - connectivity (0.0.1): - Flutter - Reachability - - CryptoSwift (1.3.2) + - CryptoSwift (1.6.0) - cw_haven (0.0.1): - cw_haven/Boost (= 0.0.1) - cw_haven/Haven (= 0.0.1) @@ -67,14 +67,14 @@ PODS: - Flutter - devicelocale (0.0.1): - Flutter - - DKImagePickerController/Core (4.3.2): + - DKImagePickerController/Core (4.3.4): - DKImagePickerController/ImageDataManager - DKImagePickerController/Resource - - DKImagePickerController/ImageDataManager (4.3.2) - - DKImagePickerController/PhotoGallery (4.3.2): + - DKImagePickerController/ImageDataManager (4.3.4) + - DKImagePickerController/PhotoGallery (4.3.4): - DKImagePickerController/Core - DKPhotoGallery - - DKImagePickerController/Resource (4.3.2) + - DKImagePickerController/Resource (4.3.4) - DKPhotoGallery (0.0.17): - DKPhotoGallery/Core (= 0.0.17) - DKPhotoGallery/Model (= 0.0.17) @@ -116,15 +116,15 @@ PODS: - platform_device_id (0.0.1): - Flutter - Reachability (3.2) - - SDWebImage (5.9.1): - - SDWebImage/Core (= 5.9.1) - - SDWebImage/Core (5.9.1) + - SDWebImage (5.13.5): + - SDWebImage/Core (= 5.13.5) + - SDWebImage/Core (5.13.5) - share_plus (0.0.1): - Flutter - shared_preferences_ios (0.0.1): - Flutter - - SwiftProtobuf (1.18.0) - - SwiftyGif (5.3.0) + - SwiftProtobuf (1.20.2) + - SwiftyGif (5.4.3) - uni_links (0.0.1): - Flutter - UnstoppableDomainsResolution (4.0.0): @@ -221,14 +221,14 @@ SPEC CHECKSUMS: barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0 BigInt: f668a80089607f521586bbe29513d708491ef2f7 connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467 - CryptoSwift: 093499be1a94b0cae36e6c26b70870668cb56060 + CryptoSwift: 562f8eceb40e80796fffc668b0cad9313284cfa6 cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a cw_monero: 4cf3b96f2da8e95e2ef7d6703dd4d2c509127b7d cw_shared_external: 2972d872b8917603478117c9957dfca611845a92 device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7 device_info: d7d233b645a32c40dfdc212de5cf646ca482f175 devicelocale: b22617f40038496deffba44747101255cee005b0 - DKImagePickerController: b5eb7f7a388e4643264105d648d01f727110fc3d + DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 file_picker: 817ab1d8cd2da9d2da412a417162deee3500fc95 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 @@ -240,16 +240,16 @@ SPEC CHECKSUMS: permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce platform_device_id: 81b3e2993881f87d0c82ef151dc274df4869aef5 Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 - SDWebImage: a990c053fff71e388a10f3357edb0be17929c9c5 + SDWebImage: 23d714cd599354ee7906dbae26dff89b421c4370 share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad - SwiftProtobuf: c3c12645230d9b09c72267e0de89468c5543bd86 - SwiftyGif: e466e86c660d343357ab944a819a101c4127cb40 + SwiftProtobuf: 9f458aaa7844a2fc0b910053e66578bc4e2da9c1 + SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780 uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f -PODFILE CHECKSUM: ae71bdf0eb731a1ffc399c122f6aa4dea0cb5f6f +PODFILE CHECKSUM: f2068ffd90d0bcc7e39f94a818dbbbbdbe8cda3e -COCOAPODS: 1.11.3 +COCOAPODS: 1.11.2 diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index c507f6e1f..8d2b61a65 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -1,4 +1,6 @@ import 'dart:async'; +import 'package:cake_wallet/core/auth_service.dart'; +import 'package:cake_wallet/di.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; @@ -28,15 +30,18 @@ class RootState extends State with WidgetsBindingObserver { RootState() : _isInactiveController = StreamController.broadcast(), _isInactive = false, + _requestAuth = getIt.get().requireAuth(), _postFrameCallback = false; Stream get isInactive => _isInactiveController.stream; StreamController _isInactiveController; bool _isInactive; bool _postFrameCallback; + bool _requestAuth; @override void initState() { + _isInactiveController = StreamController.broadcast(); _isInactive = false; _postFrameCallback = false; @@ -52,6 +57,10 @@ class RootState extends State with WidgetsBindingObserver { return; } + setState(() { + _requestAuth = getIt.get().requireAuth(); + }); + if (!_isInactive && widget.authenticationStore.state == AuthenticationState.allowed) { setState(() => _setInactive(true)); @@ -65,7 +74,7 @@ class RootState extends State with WidgetsBindingObserver { @override Widget build(BuildContext context) { - if (_isInactive && !_postFrameCallback) { + if (_isInactive && !_postFrameCallback && _requestAuth) { _postFrameCallback = true; WidgetsBinding.instance.addPostFrameCallback((_) { widget.navigatorKey.currentState?.pushNamed(Routes.unlock, From 34cfe7591f7917150c0191af92cf9412f75fe561 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 30 Nov 2022 22:57:48 +0200 Subject: [PATCH 081/203] Fix authentication required when minimize app --- lib/src/screens/root/root.dart | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index c507f6e1f..8d2b61a65 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -1,4 +1,6 @@ import 'dart:async'; +import 'package:cake_wallet/core/auth_service.dart'; +import 'package:cake_wallet/di.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; @@ -28,15 +30,18 @@ class RootState extends State with WidgetsBindingObserver { RootState() : _isInactiveController = StreamController.broadcast(), _isInactive = false, + _requestAuth = getIt.get().requireAuth(), _postFrameCallback = false; Stream get isInactive => _isInactiveController.stream; StreamController _isInactiveController; bool _isInactive; bool _postFrameCallback; + bool _requestAuth; @override void initState() { + _isInactiveController = StreamController.broadcast(); _isInactive = false; _postFrameCallback = false; @@ -52,6 +57,10 @@ class RootState extends State with WidgetsBindingObserver { return; } + setState(() { + _requestAuth = getIt.get().requireAuth(); + }); + if (!_isInactive && widget.authenticationStore.state == AuthenticationState.allowed) { setState(() => _setInactive(true)); @@ -65,7 +74,7 @@ class RootState extends State with WidgetsBindingObserver { @override Widget build(BuildContext context) { - if (_isInactive && !_postFrameCallback) { + if (_isInactive && !_postFrameCallback && _requestAuth) { _postFrameCallback = true; WidgetsBinding.instance.addPostFrameCallback((_) { widget.navigatorKey.currentState?.pushNamed(Routes.unlock, From 23d2e54c464569742c70b9498137ba265621f344 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 30 Nov 2022 23:08:31 +0200 Subject: [PATCH 082/203] Revert commit --- android/.project | 11 ------ .../org.eclipse.buildship.core.prefs | 13 +------ cw_monero/android/.project | 11 ------ ios/Podfile | 2 +- ios/Podfile.lock | 34 +++++++++---------- 5 files changed, 19 insertions(+), 52 deletions(-) diff --git a/android/.project b/android/.project index 93e645b27..17c95d4b1 100644 --- a/android/.project +++ b/android/.project @@ -14,15 +14,4 @@ org.eclipse.buildship.core.gradleprojectnature - - - 1668366526072 - - 30 - - org.eclipse.core.resources.regexFilterMatcher - node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ - - - diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs index 52768efe3..9d2efc8e7 100644 --- a/android/.settings/org.eclipse.buildship.core.prefs +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -1,13 +1,2 @@ -arguments=--init-script /var/folders/_g/6xnbffg10l741qh63jr5cds80000gp/T/d146c9752a26f79b52047fb6dc6ed385d064e120494f96f08ca63a317c41f94c.gradle --init-script /var/folders/_g/6xnbffg10l741qh63jr5cds80000gp/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle -auto.sync=false -build.scans.enabled=false -connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) connection.project.dir= -eclipse.preferences.version=1 -gradle.user.home= -java.home=/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home -jvm.arguments= -offline.mode=false -override.workspace.settings=true -show.console.view=true -show.executions.view=true +eclipse.preferences.version=1 \ No newline at end of file diff --git a/cw_monero/android/.project b/cw_monero/android/.project index 15eb18708..e0799208f 100644 --- a/cw_monero/android/.project +++ b/cw_monero/android/.project @@ -20,15 +20,4 @@ org.eclipse.jdt.core.javanature org.eclipse.buildship.core.gradleprojectnature - - - 1668366526081 - - 30 - - org.eclipse.core.resources.regexFilterMatcher - node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ - - - diff --git a/ios/Podfile b/ios/Podfile index d02ce2d3f..b29d40484 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '14.0' +platform :ios, '11.0' source 'https://github.com/CocoaPods/Specs.git' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 28ee07db9..3a810430d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -7,7 +7,7 @@ PODS: - connectivity (0.0.1): - Flutter - Reachability - - CryptoSwift (1.6.0) + - CryptoSwift (1.3.2) - cw_haven (0.0.1): - cw_haven/Boost (= 0.0.1) - cw_haven/Haven (= 0.0.1) @@ -67,14 +67,14 @@ PODS: - Flutter - devicelocale (0.0.1): - Flutter - - DKImagePickerController/Core (4.3.4): + - DKImagePickerController/Core (4.3.2): - DKImagePickerController/ImageDataManager - DKImagePickerController/Resource - - DKImagePickerController/ImageDataManager (4.3.4) - - DKImagePickerController/PhotoGallery (4.3.4): + - DKImagePickerController/ImageDataManager (4.3.2) + - DKImagePickerController/PhotoGallery (4.3.2): - DKImagePickerController/Core - DKPhotoGallery - - DKImagePickerController/Resource (4.3.4) + - DKImagePickerController/Resource (4.3.2) - DKPhotoGallery (0.0.17): - DKPhotoGallery/Core (= 0.0.17) - DKPhotoGallery/Model (= 0.0.17) @@ -116,15 +116,15 @@ PODS: - platform_device_id (0.0.1): - Flutter - Reachability (3.2) - - SDWebImage (5.13.5): - - SDWebImage/Core (= 5.13.5) - - SDWebImage/Core (5.13.5) + - SDWebImage (5.9.1): + - SDWebImage/Core (= 5.9.1) + - SDWebImage/Core (5.9.1) - share_plus (0.0.1): - Flutter - shared_preferences_ios (0.0.1): - Flutter - - SwiftProtobuf (1.20.2) - - SwiftyGif (5.4.3) + - SwiftProtobuf (1.18.0) + - SwiftyGif (5.3.0) - uni_links (0.0.1): - Flutter - UnstoppableDomainsResolution (4.0.0): @@ -221,14 +221,14 @@ SPEC CHECKSUMS: barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0 BigInt: f668a80089607f521586bbe29513d708491ef2f7 connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467 - CryptoSwift: 562f8eceb40e80796fffc668b0cad9313284cfa6 + CryptoSwift: 093499be1a94b0cae36e6c26b70870668cb56060 cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a cw_monero: 4cf3b96f2da8e95e2ef7d6703dd4d2c509127b7d cw_shared_external: 2972d872b8917603478117c9957dfca611845a92 device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7 device_info: d7d233b645a32c40dfdc212de5cf646ca482f175 devicelocale: b22617f40038496deffba44747101255cee005b0 - DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac + DKImagePickerController: b5eb7f7a388e4643264105d648d01f727110fc3d DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 file_picker: 817ab1d8cd2da9d2da412a417162deee3500fc95 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 @@ -240,16 +240,16 @@ SPEC CHECKSUMS: permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce platform_device_id: 81b3e2993881f87d0c82ef151dc274df4869aef5 Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 - SDWebImage: 23d714cd599354ee7906dbae26dff89b421c4370 + SDWebImage: a990c053fff71e388a10f3357edb0be17929c9c5 share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad - SwiftProtobuf: 9f458aaa7844a2fc0b910053e66578bc4e2da9c1 - SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780 + SwiftProtobuf: c3c12645230d9b09c72267e0de89468c5543bd86 + SwiftyGif: e466e86c660d343357ab944a819a101c4127cb40 uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f -PODFILE CHECKSUM: f2068ffd90d0bcc7e39f94a818dbbbbdbe8cda3e +PODFILE CHECKSUM: ae71bdf0eb731a1ffc399c122f6aa4dea0cb5f6f -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 From dd9e48558e63d0af448654439609600ff03ebc5d Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 30 Nov 2022 23:21:56 +0200 Subject: [PATCH 083/203] Attempt to fix test by upgrading ubuntu version --- .github/workflows/pr_test_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 190b891e1..c98e9604a 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -7,7 +7,7 @@ on: jobs: test: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04(ubuntu-latest) steps: - uses: actions/checkout@v2 From 57382ef7dc1f0bde5a2e009bfb70c4b5560cf4fb Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 30 Nov 2022 23:34:32 +0200 Subject: [PATCH 084/203] revert ubuntu version --- .github/workflows/pr_test_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index c98e9604a..190b891e1 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -7,7 +7,7 @@ on: jobs: test: - runs-on: ubuntu-20.04(ubuntu-latest) + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 From 292c4c396cc2a313d3b3a352c10bb8caebbe39d1 Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 30 Nov 2022 21:18:12 +0200 Subject: [PATCH 085/203] remove HUSD and rename BTTBSC --- assets/images/husd_icon.png | Bin 69161 -> 0 bytes cw_core/lib/crypto_currency.dart | 34 +++++++++--------- lib/core/address_validator.dart | 4 +-- .../sideshift_exchange_provider.dart | 2 +- 4 files changed, 18 insertions(+), 22 deletions(-) delete mode 100644 assets/images/husd_icon.png diff --git a/assets/images/husd_icon.png b/assets/images/husd_icon.png deleted file mode 100644 index 07102709970f5fc88213eec72059a81f5220634b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69161 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 i+(ZGhrYBPZw8~94mZae_=sZY!cAl8* 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 with Serializable { CryptoCurrency.ape, CryptoCurrency.avaxc, CryptoCurrency.btt, - CryptoCurrency.bttbsc, + CryptoCurrency.bttc, CryptoCurrency.doge, CryptoCurrency.firo, CryptoCurrency.usdttrc20, @@ -51,7 +51,6 @@ class CryptoCurrency extends EnumerableItem with Serializable { CryptoCurrency.xvg, CryptoCurrency.usdcpoly, CryptoCurrency.dcr, - CryptoCurrency.husd, CryptoCurrency.kmd, CryptoCurrency.mana, CryptoCurrency.maticpoly, @@ -103,7 +102,7 @@ class CryptoCurrency extends EnumerableItem with Serializable { static const ape = CryptoCurrency(title: 'APE', iconPath: 'assets/images/ape_icon.png', tag: 'ETH', raw: 30, name: 'ape'); static const avaxc = CryptoCurrency(title: 'AVAX', iconPath: 'assets/images/avaxc_icon.png', tag: 'C-CHAIN', raw: 31, name: 'avaxc'); static const btt = CryptoCurrency(title: 'BTT', iconPath: 'assets/images/btt_icon.png', raw: 32, name: 'btt'); - static const bttbsc = CryptoCurrency(title: 'BTT', iconPath: 'assets/images/bttbsc_icon.png', tag: 'BSC', raw: 33, name: 'bttbsc'); + static const bttc = CryptoCurrency(title: 'BTTC', iconPath: 'assets/images/bttbsc_icon.png',fullName: 'BitTorrent-NEW (Binance Smart Chain)', tag: 'BSC', raw: 33, name: 'bttc'); static const doge = CryptoCurrency(title: 'DOGE', iconPath: 'assets/images/doge_icon.png', raw: 34, name: 'doge'); static const firo = CryptoCurrency(title: 'FIRO', iconPath: 'assets/images/firo_icon.png', raw: 35, name: 'firo'); static const usdttrc20 = CryptoCurrency(title: 'USDT', iconPath: 'assets/images/usdttrc20_icon.png', tag: 'TRX', raw: 36, name: 'usdttrc20'); @@ -119,21 +118,20 @@ class CryptoCurrency extends EnumerableItem with Serializable { static const usdcpoly = CryptoCurrency(title: 'USDC', iconPath: 'assets/images/usdc_icon.png', tag: 'POLY', raw: 46, name: 'usdcpoly'); static const dcr = CryptoCurrency(title: 'DCR', iconPath: 'assets/images/dcr_icon.png', raw: 47, name: 'dcr'); - static const husd = CryptoCurrency(title: 'HUSD', iconPath: 'assets/images/husd_icon.png', tag: 'ETH', raw: 48, name: 'husd'); - static const kmd = CryptoCurrency(title: 'KMD', iconPath: 'assets/images/kmd_icon.png', raw: 49, name: 'kmd'); - static const mana = CryptoCurrency(title: 'MANA', iconPath: 'assets/images/mana_icon.png', tag: 'ETH', raw: 50, name: 'mana'); - static const maticpoly = CryptoCurrency(title: 'MATIC', iconPath: 'assets/images/matic_icon.png', tag: 'POLY', raw: 51, name: 'maticpoly'); - static const matic = CryptoCurrency(title: 'MATIC', iconPath: 'assets/images/matic_icon.png', tag: 'ETH', raw: 52, name: 'matic'); - static const mkr = CryptoCurrency(title: 'MKR', iconPath: 'assets/images/mkr_icon.png', tag: 'ETH', raw: 53, name: 'mkr'); - static const near = CryptoCurrency(title: 'NEAR', iconPath: 'assets/images/near_icon.png', raw: 54, name: 'near'); - static const oxt = CryptoCurrency(title: 'OXT', iconPath: 'assets/images/oxt_icon.png', tag: 'ETH', raw: 55, name: 'oxt'); - static const paxg = CryptoCurrency(title: 'PAXG', iconPath: 'assets/images/paxg_icon.png', tag: 'ETH', raw: 56, name: 'paxg'); - static const pivx = CryptoCurrency(title: 'PIVX', iconPath: 'assets/images/pivx_icon.png', raw: 57, name: 'pivx'); - static const rune = CryptoCurrency(title: 'RUNE', iconPath: 'assets/images/rune_icon.png', raw: 58, name: 'rune'); - static const rvn = CryptoCurrency(title: 'RVN', iconPath: 'assets/images/rvn_icon.png', raw: 59, name: 'rvn'); - static const scrt = CryptoCurrency(title: 'SCRT', iconPath: 'assets/images/scrt_icon.png', raw: 60, name: 'scrt'); - static const uni = CryptoCurrency(title: 'UNI', iconPath: 'assets/images/uni_icon.png', tag: 'ETH', raw: 61, name: 'uni'); - static const stx = CryptoCurrency(title: 'STX', iconPath: 'assets/images/stx_icon.png', raw: 62, name: 'stx'); + static const kmd = CryptoCurrency(title: 'KMD', iconPath: 'assets/images/kmd_icon.png', raw: 48, name: 'kmd'); + static const mana = CryptoCurrency(title: 'MANA', iconPath: 'assets/images/mana_icon.png', tag: 'ETH', raw: 49, name: 'mana'); + static const maticpoly = CryptoCurrency(title: 'MATIC', iconPath: 'assets/images/matic_icon.png', tag: 'POLY', raw: 50, name: 'maticpoly'); + static const matic = CryptoCurrency(title: 'MATIC', iconPath: 'assets/images/matic_icon.png', tag: 'ETH', raw: 51, name: 'matic'); + static const mkr = CryptoCurrency(title: 'MKR', iconPath: 'assets/images/mkr_icon.png', tag: 'ETH', raw: 52, name: 'mkr'); + static const near = CryptoCurrency(title: 'NEAR', iconPath: 'assets/images/near_icon.png', raw: 53, name: 'near'); + static const oxt = CryptoCurrency(title: 'OXT', iconPath: 'assets/images/oxt_icon.png', tag: 'ETH', raw: 54, name: 'oxt'); + static const paxg = CryptoCurrency(title: 'PAXG', iconPath: 'assets/images/paxg_icon.png', tag: 'ETH', raw: 55, name: 'paxg'); + static const pivx = CryptoCurrency(title: 'PIVX', iconPath: 'assets/images/pivx_icon.png', raw: 56, name: 'pivx'); + static const rune = CryptoCurrency(title: 'RUNE', iconPath: 'assets/images/rune_icon.png', raw: 57, name: 'rune'); + static const rvn = CryptoCurrency(title: 'RVN', iconPath: 'assets/images/rvn_icon.png', raw: 58, name: 'rvn'); + static const scrt = CryptoCurrency(title: 'SCRT', iconPath: 'assets/images/scrt_icon.png', raw: 59, name: 'scrt'); + static const uni = CryptoCurrency(title: 'UNI', iconPath: 'assets/images/uni_icon.png', tag: 'ETH', raw: 60, name: 'uni'); + static const stx = CryptoCurrency(title: 'STX', iconPath: 'assets/images/stx_icon.png', raw: 61, name: 'stx'); static final Map _rawCurrencyMap = all.fold>({}, (acc, item) { diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 9d7b0e3b5..519cd92a3 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -24,7 +24,6 @@ class AddressValidator extends TextValidator { return '[0-9a-zA-Z_]'; case CryptoCurrency.usdc: case CryptoCurrency.usdcpoly: - case CryptoCurrency.husd: case CryptoCurrency.ape: case CryptoCurrency.avaxc: case CryptoCurrency.eth: @@ -156,7 +155,7 @@ class AddressValidator extends TextValidator { return [98, 99, 106]; case CryptoCurrency.btt: return [34]; - case CryptoCurrency.bttbsc: + case CryptoCurrency.bttc: return [34]; case CryptoCurrency.doge: return [34]; @@ -181,7 +180,6 @@ class AddressValidator extends TextValidator { case CryptoCurrency.stx: return [40, 41, 42]; case CryptoCurrency.usdcpoly: - case CryptoCurrency.husd: case CryptoCurrency.mana: case CryptoCurrency.matic: case CryptoCurrency.maticpoly: diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/sideshift/sideshift_exchange_provider.dart index a732f7ef2..cbe9375db 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/sideshift/sideshift_exchange_provider.dart @@ -28,7 +28,6 @@ class SideShiftExchangeProvider extends ExchangeProvider { static const List _notSupported = [ CryptoCurrency.xhv, CryptoCurrency.dcr, - CryptoCurrency.husd, CryptoCurrency.kmd, CryptoCurrency.mkr, CryptoCurrency.near, @@ -39,6 +38,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { CryptoCurrency.rvn, CryptoCurrency.scrt, CryptoCurrency.stx, + CryptoCurrency.bttc, ]; static List _supportedPairs() { From ffd0079e1d231180d52f52ec51dba975fcfbbdc3 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 1 Dec 2022 14:29:03 +0200 Subject: [PATCH 086/203] Check if user already has onion node before adding it --- lib/entities/default_settings_migration.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 27ada0b0c..9aff05500 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -157,7 +157,10 @@ Future defaultSettingsMigration( Future addOnionNode(Box nodes) async { final onionNodeUri = "cakexmrl7bonq7ovjka5kuwuyd3f7qnkz6z6s6dmsy3uckwra7bvggyd.onion:18081"; - await nodes.add(Node(uri: onionNodeUri, type: WalletType.monero)); + // check if the user has this node before (added it manually) + if (nodes.values.firstWhereOrNull((element) => element.uriRaw == onionNodeUri) == null) { + await nodes.add(Node(uri: onionNodeUri, type: WalletType.monero)); + } } Future replaceNodesMigration({required Box nodes}) async { From 47764835c36680125e409f54f97646ed83034736 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 1 Dec 2022 18:09:21 +0200 Subject: [PATCH 087/203] Fix nullability issue in create trade response --- lib/exchange/changenow/changenow_exchange_provider.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/exchange/changenow/changenow_exchange_provider.dart b/lib/exchange/changenow/changenow_exchange_provider.dart index 20f529733..9910c7b9a 100644 --- a/lib/exchange/changenow/changenow_exchange_provider.dart +++ b/lib/exchange/changenow/changenow_exchange_provider.dart @@ -114,7 +114,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { final uri = Uri.https(apiAuthority, createTradePath); final response = await post(uri, headers: headers, body: json.encode(body)); - + if (response.statusCode == 400) { final responseJSON = json.decode(response.body) as Map; final error = responseJSON['error'] as String; @@ -128,9 +128,9 @@ class ChangeNowExchangeProvider extends ExchangeProvider { final responseJSON = json.decode(response.body) as Map; final id = responseJSON['id'] as String; - final inputAddress = responseJSON['payinAddress'] as String; - final refundAddress = responseJSON['refundAddress'] as String; - final extraId = responseJSON['payinExtraId'] as String; + final inputAddress = responseJSON['payinAddress'] as String?; + final refundAddress = responseJSON['refundAddress'] as String?; + final extraId = responseJSON['payinExtraId'] as String?; return Trade( id: id, From cbe31aa5aa60c269139f1c3e44be126337a274b2 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 1 Dec 2022 18:21:19 +0200 Subject: [PATCH 088/203] Revert allowing nullable values for input and refund addresses --- lib/exchange/changenow/changenow_exchange_provider.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/exchange/changenow/changenow_exchange_provider.dart b/lib/exchange/changenow/changenow_exchange_provider.dart index 9910c7b9a..96b6142e6 100644 --- a/lib/exchange/changenow/changenow_exchange_provider.dart +++ b/lib/exchange/changenow/changenow_exchange_provider.dart @@ -128,8 +128,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider { final responseJSON = json.decode(response.body) as Map; final id = responseJSON['id'] as String; - final inputAddress = responseJSON['payinAddress'] as String?; - final refundAddress = responseJSON['refundAddress'] as String?; + final inputAddress = responseJSON['payinAddress'] as String; + final refundAddress = responseJSON['refundAddress'] as String; final extraId = responseJSON['payinExtraId'] as String?; return Trade( From 8d9c0f2a4670be9f163f4e3d614f786e4bd0cd73 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 1 Dec 2022 20:47:13 +0200 Subject: [PATCH 089/203] Add bash script to run all generation commands in one time --- model_generator.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 model_generator.sh diff --git a/model_generator.sh b/model_generator.sh new file mode 100644 index 000000000..f4ef8bdad --- /dev/null +++ b/model_generator.sh @@ -0,0 +1,5 @@ +cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +flutter packages pub run build_runner build --delete-conflicting-outputs \ No newline at end of file From 03748d680ad7eedce158962581cfd17cd57bed8b Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Thu, 1 Dec 2022 21:21:51 +0200 Subject: [PATCH 090/203] [skip ci] format files --- lib/src/screens/settings/privacy_page.dart | 36 +++++++++---------- .../settings/display_settings_view_model.dart | 30 +++++++--------- .../settings/other_settings_view_model.dart | 36 ++++++++----------- .../settings/privacy_settings_view_model.dart | 16 ++++----- .../security_settings_view_model.dart | 20 +++++------ 5 files changed, 58 insertions(+), 80 deletions(-) diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index 47041b4fb..128d864f4 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -19,24 +19,24 @@ class PrivacyPage extends BasePage { padding: EdgeInsets.only(top: 10), child: Observer(builder: (_) { return Observer(builder: (_) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - SettingsSwitcherCell( - title: S.current.disable_exchange, - value: _privacySettingsViewModel.disableExchange, - onValueChange: (BuildContext context, bool value) { - _privacySettingsViewModel.setEnableExchange(value); - }), - SettingsSwitcherCell( - title: S.current.settings_save_recipient_address, - value: _privacySettingsViewModel.shouldSaveRecipientAddress, - onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setShouldSaveRecipientAddress(value); - }) - ], - ); - }); + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SettingsSwitcherCell( + title: S.current.disable_exchange, + value: _privacySettingsViewModel.disableExchange, + onValueChange: (BuildContext context, bool value) { + _privacySettingsViewModel.setEnableExchange(value); + }), + SettingsSwitcherCell( + title: S.current.settings_save_recipient_address, + value: _privacySettingsViewModel.shouldSaveRecipientAddress, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setShouldSaveRecipientAddress(value); + }) + ], + ); + }); }), ); } diff --git a/lib/view_model/settings/display_settings_view_model.dart b/lib/view_model/settings/display_settings_view_model.dart index 3537dfa6e..4e73b3399 100644 --- a/lib/view_model/settings/display_settings_view_model.dart +++ b/lib/view_model/settings/display_settings_view_model.dart @@ -8,10 +8,9 @@ part 'display_settings_view_model.g.dart'; class DisplaySettingsViewModel = DisplaySettingsViewModelBase with _$DisplaySettingsViewModel; - abstract class DisplaySettingsViewModelBase with Store { DisplaySettingsViewModelBase( - this._settingsStore, + this._settingsStore, ); final SettingsStore _settingsStore; @@ -22,10 +21,8 @@ abstract class DisplaySettingsViewModelBase with Store { @computed String get languageCode => _settingsStore.languageCode; - @computed - BalanceDisplayMode get balanceDisplayMode => - _settingsStore.balanceDisplayMode; + BalanceDisplayMode get balanceDisplayMode => _settingsStore.balanceDisplayMode; @computed bool get shouldDisplayBalance => balanceDisplayMode == BalanceDisplayMode.displayableBalance; @@ -34,30 +31,27 @@ abstract class DisplaySettingsViewModelBase with Store { ThemeBase get theme => _settingsStore.currentTheme; @action - void setBalanceDisplayMode(BalanceDisplayMode value) => - _settingsStore.balanceDisplayMode = value; + void setBalanceDisplayMode(BalanceDisplayMode value) => _settingsStore.balanceDisplayMode = value; @action - void setShouldDisplayBalance(bool value){ - if (value) { - _settingsStore.balanceDisplayMode = BalanceDisplayMode.displayableBalance; + void setShouldDisplayBalance(bool value) { + if (value) { + _settingsStore.balanceDisplayMode = BalanceDisplayMode.displayableBalance; } else { - _settingsStore.balanceDisplayMode = BalanceDisplayMode.hiddenBalance; + _settingsStore.balanceDisplayMode = BalanceDisplayMode.hiddenBalance; } } @action - void onLanguageSelected (String code) { + void onLanguageSelected(String code) { _settingsStore.languageCode = code; } @action - void setTheme(ThemeBase newTheme){ - _settingsStore.currentTheme = newTheme; + void setTheme(ThemeBase newTheme) { + _settingsStore.currentTheme = newTheme; } @action - void setFiatCurrency(FiatCurrency value) => - _settingsStore.fiatCurrency = value; - -} \ No newline at end of file + void setFiatCurrency(FiatCurrency value) => _settingsStore.fiatCurrency = value; +} diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index b0ba4c9b5..b964adc6e 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -12,32 +12,26 @@ import 'package:package_info/package_info.dart'; part 'other_settings_view_model.g.dart'; -class OtherSettingsViewModel = OtherSettingsViewModelBase - with _$OtherSettingsViewModel; - +class OtherSettingsViewModel = OtherSettingsViewModelBase with _$OtherSettingsViewModel; abstract class OtherSettingsViewModelBase with Store { - OtherSettingsViewModelBase(this._settingsStore, WalletBase, - TransactionInfo> - wallet): - walletType = wallet.type, - _wallet = wallet, - currentVersion = ''{ - PackageInfo.fromPlatform().then( - (PackageInfo packageInfo) => currentVersion = packageInfo.version); + OtherSettingsViewModelBase( + this._settingsStore, WalletBase, TransactionInfo> wallet) + : walletType = wallet.type, + _wallet = wallet, + currentVersion = '' { + PackageInfo.fromPlatform().then((PackageInfo packageInfo) => currentVersion = packageInfo.version); final priority = _settingsStore.priority[wallet.type]; final priorities = priorityForWalletType(wallet.type); if (!priorities.contains(priority)) { _settingsStore.priority[wallet.type] = priorities.first; + } } - } - - final WalletType walletType; - final WalletBase, - TransactionInfo> _wallet; + final WalletType walletType; + final WalletBase, TransactionInfo> _wallet; @observable String currentVersion; @@ -55,11 +49,10 @@ abstract class OtherSettingsViewModelBase with Store { return priority; } - String getDisplayPriority(dynamic priority) { + String getDisplayPriority(dynamic priority) { final _priority = priority as TransactionPriority; - if (_wallet.type == WalletType.bitcoin - || _wallet.type == WalletType.litecoin) { + if (_wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin) { final rate = bitcoin!.getFeeRate(_wallet, _priority); return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); } @@ -67,6 +60,5 @@ abstract class OtherSettingsViewModelBase with Store { return priority.toString(); } - void onDisplayPrioritySelected(TransactionPriority priority) => - _settingsStore.priority[_wallet.type] = priority; -} \ No newline at end of file + void onDisplayPrioritySelected(TransactionPriority priority) => _settingsStore.priority[_wallet.type] = priority; +} diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index 8433e673a..88311bf1f 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -3,8 +3,7 @@ import 'package:mobx/mobx.dart'; part 'privacy_settings_view_model.g.dart'; -class PrivacySettingsViewModel = PrivacySettingsViewModelBase - with _$PrivacySettingsViewModel; +class PrivacySettingsViewModel = PrivacySettingsViewModelBase with _$PrivacySettingsViewModel; abstract class PrivacySettingsViewModelBase with Store { PrivacySettingsViewModelBase(this._settingsStore); @@ -15,14 +14,11 @@ abstract class PrivacySettingsViewModelBase with Store { bool get disableExchange => _settingsStore.disableExchange; @computed - bool get shouldSaveRecipientAddress => - _settingsStore.shouldSaveRecipientAddress; + bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress; @action - void setShouldSaveRecipientAddress(bool value) => - _settingsStore.shouldSaveRecipientAddress = value; - + void setShouldSaveRecipientAddress(bool value) => _settingsStore.shouldSaveRecipientAddress = value; + @action - void setEnableExchange(bool value) => - _settingsStore.disableExchange = value; -} \ No newline at end of file + void setEnableExchange(bool value) => _settingsStore.disableExchange = value; +} diff --git a/lib/view_model/settings/security_settings_view_model.dart b/lib/view_model/settings/security_settings_view_model.dart index 9bf2fb6eb..4a88b633f 100644 --- a/lib/view_model/settings/security_settings_view_model.dart +++ b/lib/view_model/settings/security_settings_view_model.dart @@ -4,26 +4,22 @@ import 'package:mobx/mobx.dart'; part 'security_settings_view_model.g.dart'; -class SecuritySettingsViewModel = SecuritySettingsViewModelBase - with _$SecuritySettingsViewModel; +class SecuritySettingsViewModel = SecuritySettingsViewModelBase with _$SecuritySettingsViewModel; abstract class SecuritySettingsViewModelBase with Store { - SecuritySettingsViewModelBase(this._settingsStore): _biometricAuth = BiometricAuth(); + SecuritySettingsViewModelBase(this._settingsStore) : _biometricAuth = BiometricAuth(); final BiometricAuth _biometricAuth; final SettingsStore _settingsStore; - + @computed - bool get allowBiometricalAuthentication => - _settingsStore.allowBiometricalAuthentication; + bool get allowBiometricalAuthentication => _settingsStore.allowBiometricalAuthentication; @action - Future biometricAuthenticated()async{ - return await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated(); + Future biometricAuthenticated() async { + return await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated(); } @action - void setAllowBiometricalAuthentication(bool value) => - _settingsStore.allowBiometricalAuthentication = value; - -} \ No newline at end of file + void setAllowBiometricalAuthentication(bool value) => _settingsStore.allowBiometricalAuthentication = value; +} From 914fffe51cdec4ba880032dd53cfe925328daefa Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 1 Dec 2022 21:33:17 +0200 Subject: [PATCH 091/203] Initialize wallet directly from constructor argument [skip ci] --- .../settings/other_settings_view_model.dart | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index b964adc6e..c57af50d9 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -15,18 +15,17 @@ part 'other_settings_view_model.g.dart'; class OtherSettingsViewModel = OtherSettingsViewModelBase with _$OtherSettingsViewModel; abstract class OtherSettingsViewModelBase with Store { - OtherSettingsViewModelBase( - this._settingsStore, WalletBase, TransactionInfo> wallet) - : walletType = wallet.type, - _wallet = wallet, + OtherSettingsViewModelBase(this._settingsStore, this._wallet) + : walletType = _wallet.type, currentVersion = '' { - PackageInfo.fromPlatform().then((PackageInfo packageInfo) => currentVersion = packageInfo.version); + PackageInfo.fromPlatform() + .then((PackageInfo packageInfo) => currentVersion = packageInfo.version); - final priority = _settingsStore.priority[wallet.type]; - final priorities = priorityForWalletType(wallet.type); + final priority = _settingsStore.priority[_wallet.type]; + final priorities = priorityForWalletType(_wallet.type); if (!priorities.contains(priority)) { - _settingsStore.priority[wallet.type] = priorities.first; + _settingsStore.priority[_wallet.type] = priorities.first; } } @@ -60,5 +59,6 @@ abstract class OtherSettingsViewModelBase with Store { return priority.toString(); } - void onDisplayPrioritySelected(TransactionPriority priority) => _settingsStore.priority[_wallet.type] = priority; + void onDisplayPrioritySelected(TransactionPriority priority) => + _settingsStore.priority[_wallet.type] = priority; } From dd99508d3e3d894987dc2f5d1616f310c1586fb7 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 1 Dec 2022 22:11:51 +0200 Subject: [PATCH 092/203] Fix static amount value for determining best rate and replace it with the input the user types --- lib/view_model/exchange/exchange_view_model.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 725208324..ff3b66f73 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -296,12 +296,14 @@ abstract class ExchangeViewModelBase with Store { } Future _calculateBestRate() async { + final amount = double.tryParse(depositAmount) ?? double.tryParse(receiveAmount) ?? 1; + final result = await Future.wait( _tradeAvailableProviders .map((element) => element.calculateAmount( from: depositCurrency, to: receiveCurrency, - amount: 1, + amount: amount, isFixedRateMode: isFixedRateMode, isReceiveAmount: false)) ); @@ -311,7 +313,7 @@ abstract class ExchangeViewModelBase with Store { for (int i=0;i Date: Thu, 1 Dec 2022 22:37:13 +0200 Subject: [PATCH 093/203] allow null minimum amount in limits --- lib/view_model/exchange/exchange_view_model.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index ff3b66f73..fd66a4254 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -336,7 +336,7 @@ abstract class ExchangeViewModelBase with Store { ? depositCurrency : receiveCurrency; - double lowestMin = double.maxFinite; + double? lowestMin = double.maxFinite; double? highestMax = 0.0; for (var provider in selectedProviders) { @@ -351,8 +351,8 @@ abstract class ExchangeViewModelBase with Store { to: to, isFixedRateMode: isFixedRateMode); - if (tempLimits.min != null && tempLimits.min! < lowestMin) { - lowestMin = tempLimits.min!; + if (lowestMin != null && (tempLimits.min ?? -1) < lowestMin) { + lowestMin = tempLimits.min; } if (highestMax != null && (tempLimits.max ?? double.maxFinite) > highestMax) { highestMax = tempLimits.max; @@ -362,7 +362,7 @@ abstract class ExchangeViewModelBase with Store { } } - if (lowestMin < double.maxFinite) { + if (lowestMin != double.maxFinite) { limits = Limits(min: lowestMin, max: highestMax); limitsState = LimitsLoadedSuccessfully(limits: limits); From 3bcd31ac44d95235bfb03a46497b71919c3ba28e Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 2 Dec 2022 20:38:16 +0200 Subject: [PATCH 094/203] calculate best rate based on min/max amount --- lib/view_model/exchange/exchange_view_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index fd66a4254..f9d832843 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -296,7 +296,7 @@ abstract class ExchangeViewModelBase with Store { } Future _calculateBestRate() async { - final amount = double.tryParse(depositAmount) ?? double.tryParse(receiveAmount) ?? 1; + final amount = limits.min ?? limits.max ?? 1; final result = await Future.wait( _tradeAvailableProviders From 116e468581cf862584a640f41a07d77e0879f4f9 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 2 Dec 2022 23:20:06 +0200 Subject: [PATCH 095/203] calculate best rate based on deposit/receive amount --- lib/view_model/exchange/exchange_view_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index f9d832843..b03415f4a 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -296,7 +296,7 @@ abstract class ExchangeViewModelBase with Store { } Future _calculateBestRate() async { - final amount = limits.min ?? limits.max ?? 1; + final amount = double.tryParse(isFixedRateMode ? receiveAmount : depositAmount) ?? 1; final result = await Future.wait( _tradeAvailableProviders From 5f1e8e9d33fa04bac655e870820620f059ffd4e7 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 2 Dec 2022 23:36:22 +0200 Subject: [PATCH 096/203] remove isEditable parameter --- lib/di.dart | 3 +-- lib/router.dart | 5 ++--- lib/src/screens/contact/contact_list_page.dart | 13 ++++++------- .../contact_list/contact_list_view_model.dart | 8 ++++---- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index b84f98ad9..539681036 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -462,10 +462,9 @@ Future setup( getIt.registerFactory( () => ContactListViewModel(_contactSource, _walletInfoSource)); - getIt.registerFactoryParam((bool isEditable, CryptoCurrency? cur) + getIt.registerFactoryParam((CryptoCurrency? cur, _) => ContactListPage( getIt.get(), - isEditable: isEditable, selectedCurrency: cur)); getIt.registerFactoryParam( diff --git a/lib/router.dart b/lib/router.dart index 9fe22e22d..07e500544 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -300,13 +300,12 @@ Route createRoute(RouteSettings settings) { case Routes.addressBook: return MaterialPageRoute( builder: (_) => - getIt.get(param1: true)); + getIt.get()); case Routes.pickerAddressBook: final selectedCurrency = settings.arguments as CryptoCurrency; return MaterialPageRoute( - builder: (_) => getIt.get(param1: false, - param2: selectedCurrency)); + builder: (_) => getIt.get(param1: selectedCurrency)); case Routes.addressBookAddContact: return CupertinoPageRoute( diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 7895a1df3..8fcaf31a2 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -17,10 +17,9 @@ import 'package:cake_wallet/src/widgets/collapsible_standart_list.dart'; class ContactListPage extends BasePage { ContactListPage(this.contactListViewModel, - {this.isEditable = true, required this.selectedCurrency}); + {this.selectedCurrency}); final ContactListViewModel contactListViewModel; - final bool isEditable; final CryptoCurrency? selectedCurrency; @override @@ -28,7 +27,7 @@ class ContactListPage extends BasePage { @override Widget? trailing(BuildContext context) { - if (!isEditable) { + if (selectedCurrency != null) { return null; } @@ -68,9 +67,9 @@ class ContactListPage extends BasePage { child: Observer( builder: (_) { final contacts = - contactListViewModel.getContacts(isEditable, selectedCurrency); + contactListViewModel.getContacts(selectedCurrency); final walletContacts = - contactListViewModel.getWallets(isEditable, selectedCurrency); + contactListViewModel.getWallets(selectedCurrency); return CollapsibleSectionList( context: context, sectionCount: 2, @@ -99,7 +98,7 @@ class ContactListPage extends BasePage { final contact = contacts[index]; final content = generateRaw(context, contact); - return !isEditable + return selectedCurrency != null ? content : Slidable( key: Key('${contact.key}'), @@ -116,7 +115,7 @@ class ContactListPage extends BasePage { return GestureDetector( onTap: () async { - if (!isEditable) { + if (selectedCurrency != null) { Navigator.of(context).pop(contact); return; } diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart index 0f67245af..3fa9a73a4 100644 --- a/lib/view_model/contact_list/contact_list_view_model.dart +++ b/lib/view_model/contact_list/contact_list_view_model.dart @@ -46,16 +46,16 @@ abstract class ContactListViewModelBase with Store { Future delete(ContactRecord contact) async => contact.original.delete(); - List getContacts(bool isEditable, CryptoCurrency? cur) { - if (!isEditable) { + List getContacts(CryptoCurrency? cur) { + if (cur != null) { return contacts.where((element) => element.type == cur).toList(); } return contacts; } - List getWallets(bool isEditable, CryptoCurrency? cur) { - if (!isEditable) { + List getWallets(CryptoCurrency? cur) { + if (cur != null) { return walletContacts.where((element) => element.type == cur).toList(); } From 4c7a0a8cb97a4e1af58127bd52e185a3ae60a4e5 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 3 Dec 2022 00:34:34 +0200 Subject: [PATCH 097/203] rework _getCurrencyImage func --- .../screens/contact/contact_list_page.dart | 74 ++----------------- 1 file changed, 6 insertions(+), 68 deletions(-) diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 8fcaf31a2..9d0d1ab5a 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -111,7 +111,10 @@ class ContactListPage extends BasePage { } Widget generateRaw(BuildContext context, ContactBase contact) { - final image = _getCurrencyImage(contact.type); + final image = contact.type.iconPath; + final currencyIcon = image != null ? Image.asset(image, height: 24, width: 24) + : const SizedBox(height: 24, width: 24); + return GestureDetector( onTap: () async { @@ -136,12 +139,10 @@ class ContactListPage extends BasePage { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, children: [ - image ?? Offstage(), + currencyIcon, Expanded( child: Padding( - padding: image != null - ? EdgeInsets.only(left: 12) - : EdgeInsets.only(left: 0), + padding: EdgeInsets.only(left: 12), child: Text( contact.name, style: TextStyle( @@ -157,69 +158,6 @@ class ContactListPage extends BasePage { ); } - Image? _getCurrencyImage(CryptoCurrency currency) { - Image? image; - - switch (currency) { - case CryptoCurrency.xmr: - image = - Image.asset('assets/images/monero_logo.png', height: 24, width: 24); - break; - case CryptoCurrency.ada: - image = Image.asset('assets/images/ada.png', height: 24, width: 24); - break; - case CryptoCurrency.bch: - image = Image.asset('assets/images/bch.png', height: 24, width: 24); - break; - case CryptoCurrency.bnb: - image = Image.asset('assets/images/bnb.png', height: 24, width: 24); - break; - case CryptoCurrency.btc: - image = Image.asset('assets/images/bitcoin.png', height: 24, width: 24); - break; - case CryptoCurrency.dai: - image = Image.asset('assets/images/dai.png', height: 24, width: 24); - break; - case CryptoCurrency.dash: - image = Image.asset('assets/images/dash.png', height: 24, width: 24); - break; - case CryptoCurrency.eos: - image = Image.asset('assets/images/eos.png', height: 24, width: 24); - break; - case CryptoCurrency.eth: - image = Image.asset('assets/images/eth.png', height: 24, width: 24); - break; - case CryptoCurrency.ltc: - image = - Image.asset('assets/images/litecoin.png', height: 24, width: 24); - break; - case CryptoCurrency.nano: - image = Image.asset('assets/images/nano.png', height: 24, width: 24); - break; - case CryptoCurrency.trx: - image = Image.asset('assets/images/trx.png', height: 24, width: 24); - break; - case CryptoCurrency.usdt: - image = Image.asset('assets/images/usdt.png', height: 24, width: 24); - break; - case CryptoCurrency.usdterc20: - image = Image.asset('assets/images/usdterc.png', height: 24, width: 24); - break; - case CryptoCurrency.xlm: - image = Image.asset('assets/images/xlm.png', height: 24, width: 24); - break; - case CryptoCurrency.xrp: - image = Image.asset('assets/images/xrp.png', height: 24, width: 24); - break; - case CryptoCurrency.xhv: - image = Image.asset('assets/images/haven_logo.png', height: 24, width: 24); - break; - default: - image = null; - } - return image; - } - Future showAlertDialog(BuildContext context) async { return await showPopUp( context: context, From 11a5e9771197496ac08b72972daf25108c47707b Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 3 Dec 2022 23:34:23 +0200 Subject: [PATCH 098/203] Fix navigation error when state is changed to denied at app first start [skip_ci] --- lib/main.dart | 2 +- lib/reactions/bootstrap.dart | 6 +++--- lib/reactions/on_authentication_state_change.dart | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index e1fade7b4..11eee146b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -261,7 +261,7 @@ class AppState extends State with SingleTickerProviderStateMixin { final statusBarColor = Colors.transparent; final authenticationStore = getIt.get(); final initialRoute = - authenticationStore.state == AuthenticationState.denied + authenticationStore.state == AuthenticationState.uninitialized ? Routes.disclaimer : Routes.login; final currentTheme = settingsStore.currentTheme; diff --git a/lib/reactions/bootstrap.dart b/lib/reactions/bootstrap.dart index 8d9950e64..a40a17088 100644 --- a/lib/reactions/bootstrap.dart +++ b/lib/reactions/bootstrap.dart @@ -22,9 +22,9 @@ Future bootstrap(GlobalKey navigatorKey) async { final currentWalletName = getIt .get() .getString(PreferencesKey.currentWalletName); - authenticationStore.state = currentWalletName == null - ? AuthenticationState.denied - : AuthenticationState.installed; + if (currentWalletName != null) { + authenticationStore.state = AuthenticationState.installed; + } startAuthenticationStateChange(authenticationStore, navigatorKey); startCurrentWalletChangeReaction( diff --git a/lib/reactions/on_authentication_state_change.dart b/lib/reactions/on_authentication_state_change.dart index 560326cb5..c91f5277e 100644 --- a/lib/reactions/on_authentication_state_change.dart +++ b/lib/reactions/on_authentication_state_change.dart @@ -23,12 +23,12 @@ void startAuthenticationStateChange(AuthenticationStore authenticationStore, } if (state == AuthenticationState.allowed) { - await navigatorKey.currentState?.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false); + await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false); return; } if (state == AuthenticationState.denied) { - await navigatorKey.currentState?.pushNamedAndRemoveUntil(Routes.welcome, (_) => false); + await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.welcome, (_) => false); return; } }); From 98da1c221d2bd5f9162c950406e64b22366d10e6 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 3 Dec 2022 23:36:27 +0200 Subject: [PATCH 099/203] revert nullability change with navigation in authentication state change [skip_ci] --- lib/reactions/on_authentication_state_change.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/reactions/on_authentication_state_change.dart b/lib/reactions/on_authentication_state_change.dart index 560326cb5..c91f5277e 100644 --- a/lib/reactions/on_authentication_state_change.dart +++ b/lib/reactions/on_authentication_state_change.dart @@ -23,12 +23,12 @@ void startAuthenticationStateChange(AuthenticationStore authenticationStore, } if (state == AuthenticationState.allowed) { - await navigatorKey.currentState?.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false); + await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false); return; } if (state == AuthenticationState.denied) { - await navigatorKey.currentState?.pushNamedAndRemoveUntil(Routes.welcome, (_) => false); + await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.welcome, (_) => false); return; } }); From 9d64789983dac6b90f3a5a1aa228ebf181fbc0a7 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sun, 4 Dec 2022 05:08:42 +0200 Subject: [PATCH 100/203] Fix Conflict with main Rename classes to advanced privacy settings to avoid confusion between settings/privacy-settings --- lib/di.dart | 6 +-- lib/router.dart | 11 ++-- .../advanced_privacy_settings_page.dart | 9 ++-- .../screens/new_wallet/new_wallet_page.dart | 2 +- .../advanced_privacy_settings_view_model.dart | 51 ++++++++++++++++++ .../privacy_settings_view_model.dart | 54 ------------------- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_zh.arb | 3 +- 21 files changed, 96 insertions(+), 82 deletions(-) create mode 100644 lib/view_model/advanced_privacy_settings_view_model.dart delete mode 100644 lib/view_model/privacy_settings_view_model.dart diff --git a/lib/di.dart b/lib/di.dart index a896bf1e4..7a7621203 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -35,7 +35,7 @@ import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart'; import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart'; import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart'; -import 'package:cake_wallet/view_model/privacy_settings_view_model.dart' +import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cake_wallet/core/backup_service.dart'; import 'package:cw_core/wallet_service.dart'; @@ -816,8 +816,8 @@ Future setup( (IoniaAnyPayPaymentInfo paymentInfo, AnyPayPaymentCommittedInfo committedInfo) => IoniaPaymentStatusPage(getIt.get(param1: paymentInfo, param2: committedInfo))); - getIt.registerFactoryParam((type, _) => - PrivacySettingsViewModel(type)) + getIt.registerFactoryParam((type, _) => + AdvancedPrivacySettingsViewModel(type, getIt.get())); _isSetupFinished = true; } diff --git a/lib/router.dart b/lib/router.dart index f22fd3e18..20e4d7632 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -27,7 +27,7 @@ import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; -import 'package:cake_wallet/view_model/privacy_settings_view_model.dart'; +import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; @@ -494,13 +494,14 @@ Route createRoute(RouteSettings settings) { case Routes.onramperPage: return CupertinoPageRoute(builder: (_) => getIt.get()); - case Routes.privacySettings: + case Routes.advancedPrivacySettings: final type = settings.arguments as WalletType; - final privacySettingsViewModel = getIt.get(param1: type); - final nodeCreateViewModel = getIt.get(param1: type); return CupertinoPageRoute( - builder: (_) => AdvancedPrivacySettingsPage(privacySettingsViewModel, nodeCreateViewModel)); + builder: (_) => AdvancedPrivacySettingsPage( + getIt.get(param1: type), + getIt.get(param1: type), + )); default: return MaterialPageRoute( diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index da67d4511..33aca0307 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -1,7 +1,7 @@ import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; -import 'package:cake_wallet/view_model/privacy_settings_view_model.dart'; +import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -12,7 +12,7 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; class AdvancedPrivacySettingsPage extends BasePage { AdvancedPrivacySettingsPage(this.privacySettingsViewModel, this.nodeViewModel); - final PrivacySettingsViewModel privacySettingsViewModel; + final AdvancedPrivacySettingsViewModel privacySettingsViewModel; final NodeCreateOrEditViewModel nodeViewModel; @override @@ -27,7 +27,7 @@ class AdvancedPrivacySettingsBody extends StatefulWidget { const AdvancedPrivacySettingsBody(this.privacySettingsViewModel, this.nodeViewModel, {Key? key}) : super(key: key); - final PrivacySettingsViewModel privacySettingsViewModel; + final AdvancedPrivacySettingsViewModel privacySettingsViewModel; final NodeCreateOrEditViewModel nodeViewModel; @override @@ -39,7 +39,7 @@ class _AdvancedPrivacySettingsBodyState extends State { _AdvancedPrivacySettingsBodyState(this.privacySettingsViewModel, this.nodeViewModel); - final PrivacySettingsViewModel privacySettingsViewModel; + final AdvancedPrivacySettingsViewModel privacySettingsViewModel; final NodeCreateOrEditViewModel nodeViewModel; final _formKey = GlobalKey(); @@ -84,6 +84,7 @@ class _AdvancedPrivacySettingsBodyState LoadingPrimaryButton( onPressed: () { nodeViewModel.save(); + Navigator.pop(context); }, text: S.of(context).continue_text, color: Theme.of(context).accentTextTheme.bodyText1!.color!, diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 0abeaede2..9e0cd898c 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -219,7 +219,7 @@ class _WalletNameFormState extends State { GestureDetector( onTap: () { Navigator.of(context) - .pushNamed(Routes.privacySettings, arguments: _walletNewVM.type); + .pushNamed(Routes.advancedPrivacySettings, arguments: _walletNewVM.type); }, child: Text(S.of(context).advanced_privacy_settings), ), diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart new file mode 100644 index 000000000..ef9ab878f --- /dev/null +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -0,0 +1,51 @@ +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/view_model/settings/switcher_list_item.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/generated/i18n.dart'; + +part 'advanced_privacy_settings_view_model.g.dart'; + +class AdvancedPrivacySettingsViewModel = AdvancedPrivacySettingsViewModelBase + with _$AdvancedPrivacySettingsViewModel; + +abstract class AdvancedPrivacySettingsViewModelBase with Store { + AdvancedPrivacySettingsViewModelBase(this.type, this._settingsStore) + : _disableFiat = false, + _addCustomNode = false { + settings = [ + // TODO: uncomment when Disable Fiat PR is merged + // SwitcherListItem( + // title: S.current.disable_fiat, + // value: () => _disableFiat, + // onValueChange: (_, bool value) => _disableFiat = value, + // ), + SwitcherListItem( + title: S.current.disable_exchange, + value: () => _settingsStore.disableExchange, + onValueChange: (_, bool value) { + _settingsStore.disableExchange = value; + }, + ), + SwitcherListItem( + title: S.current.add_custom_node, + value: () => _addCustomNode, + onValueChange: (_, bool value) => _addCustomNode = value, + ), + ]; + } + + late List settings; + + @observable + bool _disableFiat = false; + + @observable + bool _addCustomNode = false; + + final WalletType type; + final SettingsStore _settingsStore; + + @computed + bool get addCustomNode => _addCustomNode; +} diff --git a/lib/view_model/privacy_settings_view_model.dart b/lib/view_model/privacy_settings_view_model.dart deleted file mode 100644 index 760c577ef..000000000 --- a/lib/view_model/privacy_settings_view_model.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:cake_wallet/view_model/settings/switcher_list_item.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/generated/i18n.dart'; - -part 'privacy_settings_view_model.g.dart'; - -class PrivacySettingsViewModel = PrivacySettingsViewModelBase - with _$PrivacySettingsViewModel; - -abstract class PrivacySettingsViewModelBase with Store { - PrivacySettingsViewModelBase(this.type) - : _disableFiat = false, - _disableExchange = false, - _addCustomNode = false { - settings = [ - SwitcherListItem( - // TODO: replace when Disable Fiat PR is merged - title: "Disable Fiat API", - // title: S.current.disable_fiat, - value: () => _disableFiat, - onValueChange: (_, bool value) => _disableFiat = value, - ), - SwitcherListItem( - title: "Disable Exchange", - // title: S.current.disable_exchange, - value: () => _disableExchange, - onValueChange: (_, bool value) => _disableExchange = value, - ), - SwitcherListItem( - title: "Add New Custom Node", - // title: S.current.add_custom_node, - value: () => _addCustomNode, - onValueChange: (_, bool value) => _addCustomNode = value, - ), - ]; - } - - late List settings; - - @observable - bool _disableFiat = false; - - @observable - bool _disableExchange = false; - - @observable - bool _addCustomNode = false; - - final WalletType type; - - @computed - bool get addCustomNode => _addCustomNode; -} diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 8f339d090..d9eb8d78a 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -663,5 +663,6 @@ "other_settings": "Andere Einstellungen", "disable_exchange": "Exchange deaktivieren", "advanced_privacy_settings": "Erweiterte Datenschutzeinstellungen", - "settings_can_be_changed_later": "Diese Einstellungen können später in den App-Einstellungen geändert werden" + "settings_can_be_changed_later": "Diese Einstellungen können später in den App-Einstellungen geändert werden", + "add_custom_node": "Neuen benutzerdefinierten Knoten hinzufügen" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index b50ba6c83..baf955fcd 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -663,5 +663,6 @@ "other_settings": "Other settings", "disable_exchange": "Disable exchange", "advanced_privacy_settings": "Advanced Privacy Settings", - "settings_can_be_changed_later": "These settings can be changed later in the app settings" + "settings_can_be_changed_later": "These settings can be changed later in the app settings", + "add_custom_node": "Add New Custom Node" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 738e64849..54b3fae18 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -663,5 +663,6 @@ "other_settings": "Otras configuraciones", "disable_exchange": "Deshabilitar intercambio", "advanced_privacy_settings": "Configuración avanzada de privacidad", - "settings_can_be_changed_later": "Estas configuraciones se pueden cambiar más tarde en la configuración de la aplicación" + "settings_can_be_changed_later": "Estas configuraciones se pueden cambiar más tarde en la configuración de la aplicación", + "add_custom_node": "Agregar nuevo nodo personalizado" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index f04a6181c..b6836ab18 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -661,5 +661,6 @@ "other_settings": "Autres paramètres", "disable_exchange": "Désactiver l'échange", "advanced_privacy_settings": "Paramètres de confidentialité avancés", - "settings_can_be_changed_later": "Ces paramètres peuvent être modifiés ultérieurement dans les paramètres de l'application" + "settings_can_be_changed_later": "Ces paramètres peuvent être modifiés ultérieurement dans les paramètres de l'application", + "add_custom_node": "Ajouter un nouveau nœud personnalisé" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index fdf565a7b..72a21f333 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -663,5 +663,6 @@ "other_settings": "अन्य सेटिंग्स", "disable_exchange": "एक्सचेंज अक्षम करें", "advanced_privacy_settings": "उन्नत गोपनीयता सेटिंग्स", - "settings_can_be_changed_later": "इन सेटिंग्स को बाद में ऐप सेटिंग में बदला जा सकता है" + "settings_can_be_changed_later": "इन सेटिंग्स को बाद में ऐप सेटिंग में बदला जा सकता है", + "add_custom_node": "नया कस्टम नोड जोड़ें" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index ece52e656..16b388a05 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -663,5 +663,6 @@ "other_settings": "Ostale postavke", "disable_exchange": "Onemogući exchange", "advanced_privacy_settings": "Napredne postavke privatnosti", - "settings_can_be_changed_later": "Te se postavke mogu promijeniti kasnije u postavkama aplikacije" + "settings_can_be_changed_later": "Te se postavke mogu promijeniti kasnije u postavkama aplikacije", + "add_custom_node": "Dodaj novi prilagođeni čvor" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index d5f591c64..28ad40d47 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -663,5 +663,6 @@ "other_settings": "Altre impostazioni", "disable_exchange": "Disabilita scambio", "advanced_privacy_settings": "Impostazioni avanzate sulla privacy", - "settings_can_be_changed_later": "Queste impostazioni possono essere modificate in seguito nelle impostazioni dell'app" + "settings_can_be_changed_later": "Queste impostazioni possono essere modificate in seguito nelle impostazioni dell'app", + "add_custom_node": "Aggiungi nuovo nodo personalizzato" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 21c21c7a8..d79f58e7a 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -663,5 +663,6 @@ "other_settings": "その他の設定", "disable_exchange": "交換を無効にする", "advanced_privacy_settings": "高度なプライバシー設定", - "settings_can_be_changed_later": "これらの設定は、後でアプリの設定で変更できます" + "settings_can_be_changed_later": "これらの設定は、後でアプリの設定で変更できます", + "add_custom_node": "新しいカスタム ノードを追加" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 0d2bc31bc..0652ffc54 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -663,5 +663,6 @@ "other_settings": "기타 설정", "disable_exchange": "교환 비활성화", "advanced_privacy_settings": "고급 개인 정보 설정", - "settings_can_be_changed_later": "이 설정은 나중에 앱 설정에서 변경할 수 있습니다." + "settings_can_be_changed_later": "이 설정은 나중에 앱 설정에서 변경할 수 있습니다.", + "add_custom_node": "새 사용자 정의 노드 추가" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index b7bb86d9c..2c6e528ca 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -663,5 +663,6 @@ "other_settings": "Andere instellingen", "disable_exchange": "Uitwisseling uitschakelen", "advanced_privacy_settings": "Geavanceerde privacy-instellingen", - "settings_can_be_changed_later": "Deze instellingen kunnen later worden gewijzigd in de app-instellingen" + "settings_can_be_changed_later": "Deze instellingen kunnen later worden gewijzigd in de app-instellingen", + "add_custom_node": "Voeg een nieuw aangepast knooppunt toe" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 20a0b2f98..179f7267b 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -663,5 +663,6 @@ "other_settings": "Inne ustawienia", "disable_exchange": "Wyłącz wymianę", "advanced_privacy_settings": "Zaawansowane ustawienia prywatności", - "settings_can_be_changed_later": "Te ustawienia można później zmienić w ustawieniach aplikacji" + "settings_can_be_changed_later": "Te ustawienia można później zmienić w ustawieniach aplikacji", + "add_custom_node": "Dodaj nowy węzeł niestandardowy" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 65438a26c..cf0669585 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -662,5 +662,6 @@ "other_settings": "Outras configurações", "disable_exchange": "Desativar troca", "advanced_privacy_settings": "Configurações de privacidade avançadas", - "settings_can_be_changed_later": "Essas configurações podem ser alteradas posteriormente nas configurações do aplicativo" + "settings_can_be_changed_later": "Essas configurações podem ser alteradas posteriormente nas configurações do aplicativo", + "add_custom_node": "Adicionar novo nó personalizado" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 4dcda3007..f73ad4564 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -663,5 +663,6 @@ "other_settings": "Другие настройки", "disable_exchange": "Отключить обмен", "advanced_privacy_settings": "Расширенные настройки конфиденциальности", - "settings_can_be_changed_later": "Эти настройки можно изменить позже в настройках приложения." + "settings_can_be_changed_later": "Эти настройки можно изменить позже в настройках приложения.", + "add_custom_node": "Добавить новый пользовательский узел" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 61f6cfb0d..c52359d64 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -662,5 +662,6 @@ "other_settings": "Інші налаштування", "disable_exchange": "Вимкнути exchange", "advanced_privacy_settings": "Розширені налаштування конфіденційності", - "settings_can_be_changed_later": "Ці параметри можна змінити пізніше в налаштуваннях програми" + "settings_can_be_changed_later": "Ці параметри можна змінити пізніше в налаштуваннях програми", + "add_custom_node": "Додати новий спеціальний вузол" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 750b4e605..a8f9119da 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -661,5 +661,6 @@ "other_settings": "其他设置", "disable_exchange": "禁用交换", "advanced_privacy_settings": "高级隐私设置", - "settings_can_be_changed_later": "稍后可以在应用设置中更改这些设置" + "settings_can_be_changed_later": "稍后可以在应用设置中更改这些设置", + "add_custom_node": "添加新的自定义节点" } From 7e6439947645fc197d74127d0c593161dcfffe8d Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sun, 4 Dec 2022 05:27:49 +0200 Subject: [PATCH 101/203] remove un-necessary attributes passing --- .../advanced_privacy_settings_page.dart | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index 33aca0307..e0dd1a729 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -31,16 +31,11 @@ class AdvancedPrivacySettingsBody extends StatefulWidget { final NodeCreateOrEditViewModel nodeViewModel; @override - _AdvancedPrivacySettingsBodyState createState() => - _AdvancedPrivacySettingsBodyState(privacySettingsViewModel, nodeViewModel); + _AdvancedPrivacySettingsBodyState createState() => _AdvancedPrivacySettingsBodyState(); } -class _AdvancedPrivacySettingsBodyState - extends State { - _AdvancedPrivacySettingsBodyState(this.privacySettingsViewModel, this.nodeViewModel); - - final AdvancedPrivacySettingsViewModel privacySettingsViewModel; - final NodeCreateOrEditViewModel nodeViewModel; +class _AdvancedPrivacySettingsBodyState extends State { + _AdvancedPrivacySettingsBodyState(); final _formKey = GlobalKey(); @@ -53,7 +48,7 @@ class _AdvancedPrivacySettingsBodyState content: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - ...privacySettingsViewModel.settings.map( + ...widget.privacySettingsViewModel.settings.map( (item) => Observer( builder: (_) => SettingsSwitcherCell( title: item.title, @@ -64,12 +59,12 @@ class _AdvancedPrivacySettingsBodyState ), Observer( builder: (_) { - if (privacySettingsViewModel.addCustomNode) { + if (widget.privacySettingsViewModel.addCustomNode) { return Padding( padding: EdgeInsets.only(left: 24, right: 24, top: 24), child: NodeForm( formKey: _formKey, - nodeViewModel: nodeViewModel, + nodeViewModel: widget.nodeViewModel, ), ); } @@ -83,7 +78,7 @@ class _AdvancedPrivacySettingsBodyState children: [ LoadingPrimaryButton( onPressed: () { - nodeViewModel.save(); + widget.nodeViewModel.save(); Navigator.pop(context); }, text: S.of(context).continue_text, @@ -92,8 +87,7 @@ class _AdvancedPrivacySettingsBodyState ), const SizedBox(height: 25), Padding( - padding: EdgeInsets.symmetric( - horizontal: MediaQuery.of(context).size.width * 0.15), + padding: EdgeInsets.symmetric(horizontal: MediaQuery.of(context).size.width * 0.15), child: Text( S.of(context).settings_can_be_changed_later, textAlign: TextAlign.center, From 9eb8a442d813ece2f9f73b11142afc30faf96721 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sun, 4 Dec 2022 17:30:09 +0200 Subject: [PATCH 102/203] Allow setting the new added node as the current selected node --- lib/di.dart | 7 +++++-- .../new_wallet/advanced_privacy_settings_page.dart | 8 ++++---- .../node_list/node_create_or_edit_view_model.dart | 11 +++++++++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index 7a7621203..a5c7702d8 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -500,8 +500,11 @@ Future setup( getIt.registerFactory(() => OtherSettingsPage(getIt.get())); getIt.registerFactoryParam( - (WalletType? type, _) => - NodeCreateOrEditViewModel(_nodeSource, type ?? getIt.get().wallet!.type)); + (WalletType? type, _) => NodeCreateOrEditViewModel( + _nodeSource, + type ?? getIt.get().wallet!.type, + getIt.get(), + )); getIt.registerFactory( () => NodeCreateOrEditPage(getIt.get())); diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index e0dd1a729..ff1c83f90 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -10,9 +10,9 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; class AdvancedPrivacySettingsPage extends BasePage { - AdvancedPrivacySettingsPage(this.privacySettingsViewModel, this.nodeViewModel); + AdvancedPrivacySettingsPage(this.advancedPrivacySettingsViewModel, this.nodeViewModel); - final AdvancedPrivacySettingsViewModel privacySettingsViewModel; + final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel; final NodeCreateOrEditViewModel nodeViewModel; @override @@ -20,7 +20,7 @@ class AdvancedPrivacySettingsPage extends BasePage { @override Widget body(BuildContext context) => - AdvancedPrivacySettingsBody(privacySettingsViewModel, nodeViewModel); + AdvancedPrivacySettingsBody(advancedPrivacySettingsViewModel, nodeViewModel); } class AdvancedPrivacySettingsBody extends StatefulWidget { @@ -78,7 +78,7 @@ class _AdvancedPrivacySettingsBodyState extends State _nodeSource; + final SettingsStore _settingsStore; @action void reset() { @@ -75,13 +77,18 @@ abstract class NodeCreateOrEditViewModelBase with Store { } @action - Future save() async { + Future save({bool saveAsCurrent = false}) async { try { state = IsExecutingState(); final node = Node(uri: uri, type: _walletType, login: login, password: password, useSSL: useSSL, trusted: trusted); await _nodeSource.add(node); + + if (saveAsCurrent) { + _settingsStore.nodes[_walletType] = node; + } + state = ExecutedSuccessfullyState(); } catch (e) { state = FailureState(e.toString()); From 7b95533cd3b8173be6576fdbd352bca0e8babdc4 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sun, 4 Dec 2022 20:06:17 +0200 Subject: [PATCH 103/203] fix nullable type --- cw_core/lib/crypto_currency.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index 48ebede75..42e72d2eb 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -139,8 +139,8 @@ class CryptoCurrency extends EnumerableItem with Serializable { return acc; }); - static final Map _nameCurrencyMap = - all.fold>({}, (acc, item) { + static final Map _nameCurrencyMap = + all.fold>({}, (acc, item) { acc.addAll({item.name: item}); return acc; }); From 23358e131876b4f4535e3074492da83df9fc1c2d Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Mon, 5 Dec 2022 13:38:29 +0100 Subject: [PATCH 104/203] Update security settings view model --- lib/di.dart | 2 +- .../security_settings_view_model.dart | 20 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index d55a147ca..35a1b4d1a 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -434,7 +434,7 @@ Future setup( }); getIt.registerFactory(() { - return SecuritySettingsViewModel(getIt.get()); + return SecuritySettingsViewModel(getIt.get(), getIt.get()); }); getIt.registerFactory(() => WalletSeedViewModel(getIt.get().wallet!)); diff --git a/lib/view_model/settings/security_settings_view_model.dart b/lib/view_model/settings/security_settings_view_model.dart index 4a88b633f..c48223af6 100644 --- a/lib/view_model/settings/security_settings_view_model.dart +++ b/lib/view_model/settings/security_settings_view_model.dart @@ -1,4 +1,6 @@ +import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/biometric_auth.dart'; +import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:mobx/mobx.dart'; @@ -7,19 +9,33 @@ part 'security_settings_view_model.g.dart'; class SecuritySettingsViewModel = SecuritySettingsViewModelBase with _$SecuritySettingsViewModel; abstract class SecuritySettingsViewModelBase with Store { - SecuritySettingsViewModelBase(this._settingsStore) : _biometricAuth = BiometricAuth(); + SecuritySettingsViewModelBase( + this._settingsStore, + this._authService, + ) : _biometricAuth = BiometricAuth(); final BiometricAuth _biometricAuth; final SettingsStore _settingsStore; + final AuthService _authService; @computed bool get allowBiometricalAuthentication => _settingsStore.allowBiometricalAuthentication; + @computed + PinCodeRequiredDuration get pinCodeRequiredDuration => _settingsStore.pinTimeOutDuration; + @action Future biometricAuthenticated() async { return await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated(); } @action - void setAllowBiometricalAuthentication(bool value) => _settingsStore.allowBiometricalAuthentication = value; + void setAllowBiometricalAuthentication(bool value) => + _settingsStore.allowBiometricalAuthentication = value; + + @action + setPinCodeRequiredDuration(PinCodeRequiredDuration duration) => + _settingsStore.pinTimeOutDuration = duration; + + bool checkPinCodeRiquired() => _authService.requireAuth(); } From 3aa0e626ff2e1936bed9d9bbdb248d867d68e035 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Mon, 5 Dec 2022 18:37:35 +0200 Subject: [PATCH 105/203] Pass selected currency to the view model instead of the UI --- lib/di.dart | 8 ++-- .../screens/contact/contact_list_page.dart | 23 +++++------ .../contact_list/contact_list_view_model.dart | 39 ++++++++----------- 3 files changed, 28 insertions(+), 42 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index 539681036..c37f4eeac 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -459,13 +459,11 @@ Future setup( (ContactRecord? contact, _) => ContactViewModel(_contactSource, contact: contact)); - getIt.registerFactory( - () => ContactListViewModel(_contactSource, _walletInfoSource)); + getIt.registerFactoryParam( + (CryptoCurrency? cur, _) => ContactListViewModel(_contactSource, _walletInfoSource, cur)); getIt.registerFactoryParam((CryptoCurrency? cur, _) - => ContactListPage( - getIt.get(), - selectedCurrency: cur)); + => ContactListPage(getIt.get(param1: cur))); getIt.registerFactoryParam( (ContactRecord? contact, _) => diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 9d0d1ab5a..7cd7a0157 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -9,25 +9,22 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; import 'package:cake_wallet/src/widgets/collapsible_standart_list.dart'; class ContactListPage extends BasePage { - ContactListPage(this.contactListViewModel, - {this.selectedCurrency}); + ContactListPage(this.contactListViewModel); final ContactListViewModel contactListViewModel; - final CryptoCurrency? selectedCurrency; @override String get title => S.current.address_book; @override Widget? trailing(BuildContext context) { - if (selectedCurrency != null) { + if (!contactListViewModel.isEditable) { return null; } @@ -66,10 +63,8 @@ class ContactListPage extends BasePage { padding: EdgeInsets.only(top: 20.0, bottom: 20.0), child: Observer( builder: (_) { - final contacts = - contactListViewModel.getContacts(selectedCurrency); - final walletContacts = - contactListViewModel.getWallets(selectedCurrency); + final contacts = contactListViewModel.contactsToShow; + final walletContacts = contactListViewModel.walletContactsToShow; return CollapsibleSectionList( context: context, sectionCount: 2, @@ -98,13 +93,13 @@ class ContactListPage extends BasePage { final contact = contacts[index]; final content = generateRaw(context, contact); - return selectedCurrency != null - ? content - : Slidable( + return contactListViewModel.isEditable + ? Slidable( key: Key('${contact.key}'), endActionPane: _actionPane(context, contact), child: content, - ); + ) + : content; }, );}) ); @@ -118,7 +113,7 @@ class ContactListPage extends BasePage { return GestureDetector( onTap: () async { - if (selectedCurrency != null) { + if (!contactListViewModel.isEditable) { Navigator.of(context).pop(contact); return; } diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart index 3fa9a73a4..5b0187fc8 100644 --- a/lib/view_model/contact_list/contact_list_view_model.dart +++ b/lib/view_model/contact_list/contact_list_view_model.dart @@ -11,24 +11,22 @@ import 'package:cw_core/crypto_currency.dart'; part 'contact_list_view_model.g.dart'; -class ContactListViewModel = ContactListViewModelBase - with _$ContactListViewModel; +class ContactListViewModel = ContactListViewModelBase with _$ContactListViewModel; abstract class ContactListViewModelBase with Store { - ContactListViewModelBase(this.contactSource, this.walletInfoSource) + ContactListViewModelBase(this.contactSource, this.walletInfoSource, this._currency) : contacts = ObservableList(), walletContacts = [] { walletInfoSource.values.forEach((info) { if (info.addresses?.isNotEmpty ?? false) { info.addresses?.forEach((address, label) { - final name = label.isNotEmpty - ? info.name + ' ($label)' - : info.name; + final name = label.isNotEmpty ? info.name + ' ($label)' : info.name; walletContacts.add(WalletContact( - address, - name, - walletTypeToCryptoCurrency(info.type))); + address, + name, + walletTypeToCryptoCurrency(info.type), + )); }); } }); @@ -42,23 +40,18 @@ abstract class ContactListViewModelBase with Store { final Box walletInfoSource; final ObservableList contacts; final List walletContacts; + final CryptoCurrency? _currency; StreamSubscription? _subscription; + bool get isEditable => _currency == null; + Future delete(ContactRecord contact) async => contact.original.delete(); - List getContacts(CryptoCurrency? cur) { - if (cur != null) { - return contacts.where((element) => element.type == cur).toList(); - } + @computed + List get contactsToShow => + contacts.where((element) => _currency == null || element.type == _currency).toList(); - return contacts; - } - - List getWallets(CryptoCurrency? cur) { - if (cur != null) { - return walletContacts.where((element) => element.type == cur).toList(); - } - - return walletContacts; - } + @computed + List get walletContactsToShow => + walletContacts.where((element) => _currency == null || element.type == _currency).toList(); } From d19f7b6d3896e39cd906c08bd7eb4358df661f70 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Mon, 5 Dec 2022 18:40:53 +0200 Subject: [PATCH 106/203] Remove unused state 'denied' from authentication state [skip ci] --- lib/reactions/on_authentication_state_change.dart | 5 ----- lib/store/authentication_store.dart | 5 +---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/reactions/on_authentication_state_change.dart b/lib/reactions/on_authentication_state_change.dart index c91f5277e..edadf33b0 100644 --- a/lib/reactions/on_authentication_state_change.dart +++ b/lib/reactions/on_authentication_state_change.dart @@ -26,10 +26,5 @@ void startAuthenticationStateChange(AuthenticationStore authenticationStore, await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false); return; } - - if (state == AuthenticationState.denied) { - await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.welcome, (_) => false); - return; - } }); } diff --git a/lib/store/authentication_store.dart b/lib/store/authentication_store.dart index 626ca2a91..b734d7acb 100644 --- a/lib/store/authentication_store.dart +++ b/lib/store/authentication_store.dart @@ -4,7 +4,7 @@ part 'authentication_store.g.dart'; class AuthenticationStore = AuthenticationStoreBase with _$AuthenticationStore; -enum AuthenticationState { uninitialized, installed, allowed, denied } +enum AuthenticationState { uninitialized, installed, allowed } abstract class AuthenticationStoreBase with Store { AuthenticationStoreBase() : state = AuthenticationState.uninitialized; @@ -17,7 +17,4 @@ abstract class AuthenticationStoreBase with Store { @action void allowed() => state = AuthenticationState.allowed; - - @action - void denied() => state = AuthenticationState.denied; } From c156691e09139a36688d992911873ff9efb92b7c Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Mon, 5 Dec 2022 20:14:46 +0100 Subject: [PATCH 107/203] [skip ci] undo formatting in di --- lib/di.dart | 398 ++++++++++-------- .../security_settings_view_model.dart | 20 +- 2 files changed, 235 insertions(+), 183 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index d55a147ca..bf926cbda 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -194,7 +194,8 @@ Future setup( _unspentCoinsInfoSource = unspentCoinsInfoSource; if (!_isSetupFinished) { - getIt.registerSingletonAsync(() => SharedPreferences.getInstance()); + getIt.registerSingletonAsync( + () => SharedPreferences.getInstance()); } final isBitcoinBuyEnabled = (secrets.wyreSecretKey?.isNotEmpty ?? false) && @@ -220,64 +221,73 @@ Future setup( walletList: getIt.get(), settingsStore: getIt.get(), nodeListStore: getIt.get())); - getIt.registerSingleton( - TradesStore(tradesSource: _tradesSource, settingsStore: getIt.get())); - getIt.registerSingleton( - OrdersStore(ordersSource: _ordersSource, settingsStore: getIt.get())); + getIt.registerSingleton(TradesStore( + tradesSource: _tradesSource, settingsStore: getIt.get())); + getIt.registerSingleton(OrdersStore( + ordersSource: _ordersSource, settingsStore: getIt.get())); getIt.registerSingleton(TradeFilterStore()); getIt.registerSingleton(TransactionFilterStore()); getIt.registerSingleton(FiatConversionStore()); - getIt.registerSingleton(SendTemplateStore(templateSource: _templates)); + getIt.registerSingleton( + SendTemplateStore(templateSource: _templates)); getIt.registerSingleton( ExchangeTemplateStore(templateSource: _exchangeTemplates)); - getIt.registerSingleton( - YatStore(appStore: getIt.get(), secureStorage: getIt.get()) - ..init()); + getIt.registerSingleton(YatStore( + appStore: getIt.get(), + secureStorage: getIt.get()) + ..init()); - final secretStore = await SecretStoreBase.load(getIt.get()); + final secretStore = + await SecretStoreBase.load(getIt.get()); getIt.registerSingleton(secretStore); - getIt.registerFactory(() => KeyService(getIt.get())); + getIt.registerFactory( + () => KeyService(getIt.get())); - getIt.registerFactoryParam((type, _) => - WalletCreationService( + getIt.registerFactoryParam( + (type, _) => WalletCreationService( initialType: type, keyService: getIt.get(), secureStorage: getIt.get(), sharedPreferences: getIt.get(), walletInfoSource: _walletInfoSource)); - getIt.registerFactory(() => WalletLoadingService( + getIt.registerFactory( + () => WalletLoadingService( getIt.get(), getIt.get(), (WalletType type) => getIt.get(param1: type))); - getIt.registerFactoryParam((type, _) => WalletNewVM( - getIt.get(), getIt.get(param1: type), _walletInfoSource, - type: type)); + getIt.registerFactoryParam((type, _) => + WalletNewVM(getIt.get(), + getIt.get(param1: type), _walletInfoSource, + type: type)); - getIt.registerFactoryParam((args, _) { + getIt + .registerFactoryParam((args, _) { final type = args.first as WalletType; final language = args[1] as String; final mnemonic = args[2] as String; - return WalletRestorationFromSeedVM( - getIt.get(), getIt.get(param1: type), _walletInfoSource, + return WalletRestorationFromSeedVM(getIt.get(), + getIt.get(param1: type), _walletInfoSource, type: type, language: language, seed: mnemonic); }); - getIt.registerFactoryParam((args, _) { + getIt + .registerFactoryParam((args, _) { final type = args.first as WalletType; final language = args[1] as String; - return WalletRestorationFromKeysVM( - getIt.get(), getIt.get(param1: type), _walletInfoSource, + return WalletRestorationFromKeysVM(getIt.get(), + getIt.get(param1: type), _walletInfoSource, type: type, language: language); }); getIt.registerFactory(() => - WalletAddressListViewModel(appStore: getIt.get(), yatStore: getIt.get())); + WalletAddressListViewModel( + appStore: getIt.get(), yatStore: getIt.get())); getIt.registerFactory(() => BalanceViewModel( appStore: getIt.get(), @@ -298,12 +308,15 @@ Future setup( secureStorage: getIt.get(), sharedPreferences: getIt.get())); - getIt.registerFactory(() => AuthViewModel(getIt.get(), - getIt.get(), getIt.get(), BiometricAuth())); + getIt.registerFactory(() => AuthViewModel( + getIt.get(), + getIt.get(), + getIt.get(), + BiometricAuth())); getIt.registerFactory( - () => AuthPage(getIt.get(), - onAuthenticationFinished: (isAuthenticated, AuthPageState authPageState) { + () => AuthPage(getIt.get(), onAuthenticationFinished: + (isAuthenticated, AuthPageState authPageState) { if (!isAuthenticated) { return; } @@ -318,7 +331,8 @@ Future setup( authPageState.changeProcessText('Loading the wallet'); if (loginError != null) { - authPageState.changeProcessText('ERROR: ${loginError.toString()}'); + authPageState + .changeProcessText('ERROR: ${loginError.toString()}'); } ReactionDisposer? _reaction; @@ -329,29 +343,28 @@ Future setup( }, closable: false), instanceName: 'login'); - getIt.registerFactoryParam( - (onAuthFinished, closable) => AuthPage(getIt.get(), - onAuthenticationFinished: onAuthFinished, closable: closable ?? false)); + getIt + .registerFactoryParam( + (onAuthFinished, closable) => AuthPage(getIt.get(), + onAuthenticationFinished: onAuthFinished, + closable: closable ?? false)); - getIt.registerFactory(() => BalancePage( - dashboardViewModel: getIt.get(), - settingsStore: getIt.get())); + getIt.registerFactory(() => + BalancePage(dashboardViewModel: getIt.get(), settingsStore: getIt.get())); - getIt.registerFactory(() => DashboardPage( - balancePage: getIt.get(), - walletViewModel: getIt.get(), + getIt.registerFactory(() => DashboardPage( balancePage: getIt.get(), walletViewModel: getIt.get(), addressListViewModel: getIt.get())); + getIt.registerFactory(() => ReceivePage( addressListViewModel: getIt.get())); - getIt.registerFactory( - () => ReceivePage(addressListViewModel: getIt.get())); getIt.registerFactory(() => AddressPage( addressListViewModel: getIt.get(), walletViewModel: getIt.get())); - getIt.registerFactoryParam((dynamic item, _) => - WalletAddressEditOrCreateViewModel(wallet: getIt.get().wallet!, item: item)); + getIt.registerFactoryParam( + (dynamic item, _) => WalletAddressEditOrCreateViewModel( + wallet: getIt.get().wallet!, item: item)); - getIt.registerFactoryParam((dynamic item, _) => - AddressEditOrCreatePage( + getIt.registerFactoryParam( + (dynamic item, _) => AddressEditOrCreatePage( addressEditOrCreateViewModel: getIt.get(param1: item))); @@ -369,16 +382,19 @@ Future setup( getIt.get(), _transactionDescriptionBox)); - getIt.registerFactory(() => SendPage(sendViewModel: getIt.get())); - getIt.registerFactory( - () => SendTemplatePage(sendTemplateViewModel: getIt.get())); + () => SendPage(sendViewModel: getIt.get())); + + getIt.registerFactory(() => SendTemplatePage( + sendTemplateViewModel: getIt.get())); getIt.registerFactory(() => WalletListViewModel( - _walletInfoSource, getIt.get(), getIt.get())); + _walletInfoSource, + getIt.get(), + getIt.get())); - getIt - .registerFactory(() => WalletListPage(walletListViewModel: getIt.get())); + getIt.registerFactory(() => + WalletListPage(walletListViewModel: getIt.get())); getIt.registerFactory(() { final wallet = getIt.get().wallet!; @@ -387,12 +403,11 @@ Future setup( return MoneroAccountListViewModel(wallet); } - throw Exception( - 'Unexpected wallet type: ${wallet.type} for generate MoneroAccountListViewModel'); + throw Exception('Unexpected wallet type: ${wallet.type} for generate MoneroAccountListViewModel'); }); - getIt.registerFactory( - () => MoneroAccountListPage(accountListViewModel: getIt.get())); + getIt.registerFactory(() => MoneroAccountListPage( + accountListViewModel: getIt.get())); /*getIt.registerFactory(() { final wallet = getIt.get().wallet; @@ -409,14 +424,16 @@ Future setup( moneroAccountCreationViewModel: getIt.get()));*/ - getIt.registerFactoryParam( + getIt.registerFactoryParam( (AccountListItem? account, _) => MoneroAccountEditOrCreateViewModel( monero!.getAccountList(getIt.get().wallet!), haven?.getAccountList(getIt.get().wallet!), wallet: getIt.get().wallet!, accountListItem: account)); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (AccountListItem? account, _) => MoneroAccountEditOrCreatePage( moneroAccountCreationViewModel: getIt.get(param1: account))); @@ -434,36 +451,44 @@ Future setup( }); getIt.registerFactory(() { - return SecuritySettingsViewModel(getIt.get()); + return SecuritySettingsViewModel(getIt.get(), getIt.get()); }); - getIt.registerFactory(() => WalletSeedViewModel(getIt.get().wallet!)); + getIt + .registerFactory(() => WalletSeedViewModel(getIt.get().wallet!)); - getIt.registerFactoryParam((bool isWalletCreated, _) => - WalletSeedPage(getIt.get(), isNewWalletCreated: isWalletCreated)); + getIt.registerFactoryParam( + (bool isWalletCreated, _) => WalletSeedPage( + getIt.get(), + isNewWalletCreated: isWalletCreated)); - getIt.registerFactory(() => WalletKeysViewModel(getIt.get().wallet!)); + getIt + .registerFactory(() => WalletKeysViewModel(getIt.get().wallet!)); getIt.registerFactory(() => WalletKeysPage(getIt.get())); getIt.registerFactoryParam( - (ContactRecord? contact, _) => ContactViewModel(_contactSource, contact: contact)); + (ContactRecord? contact, _) => + ContactViewModel(_contactSource, contact: contact)); - getIt.registerFactory(() => ContactListViewModel(_contactSource, _walletInfoSource)); + getIt.registerFactory( + () => ContactListViewModel(_contactSource, _walletInfoSource)); - getIt.registerFactoryParam((bool isEditable, _) => - ContactListPage(getIt.get(), isEditable: isEditable)); + getIt.registerFactoryParam( + (bool isEditable, _) => ContactListPage(getIt.get(), + isEditable: isEditable)); getIt.registerFactoryParam( - (ContactRecord? contact, _) => ContactPage(getIt.get(param1: contact))); + (ContactRecord? contact, _) => + ContactPage(getIt.get(param1: contact))); getIt.registerFactory(() { final appStore = getIt.get(); - return NodeListViewModel(_nodeSource, appStore.wallet!, appStore.settingsStore); + return NodeListViewModel( + _nodeSource, appStore.wallet!, appStore.settingsStore); }); - getIt.registerFactory( - () => ConnectionSyncPage(getIt.get(), getIt.get())); + getIt.registerFactory(() => ConnectionSyncPage(getIt.get(), getIt.get())); getIt.registerFactory(() => SecurityBackupPage(getIt.get())); @@ -473,22 +498,24 @@ Future setup( getIt.registerFactory(() => OtherSettingsPage(getIt.get())); - getIt - .registerFactory(() => NodeCreateOrEditViewModel(_nodeSource, getIt.get().wallet!)); + getIt.registerFactory(() => + NodeCreateOrEditViewModel(_nodeSource, getIt.get().wallet!)); - getIt.registerFactory(() => NodeCreateOrEditPage(getIt.get())); + getIt.registerFactory( + () => NodeCreateOrEditPage(getIt.get())); getIt.registerFactory(() => OnRamperPage( - settingsStore: getIt.get().settingsStore, wallet: getIt.get().wallet!)); + settingsStore: getIt.get().settingsStore, + wallet: getIt.get().wallet!)); getIt.registerFactory(() => ExchangeViewModel( - getIt.get().wallet!, - _tradesSource, - getIt.get(), - getIt.get(), - getIt.get().settingsStore, - getIt.get(), - )); + getIt.get().wallet!, + _tradesSource, + getIt.get(), + getIt.get(), + getIt.get().settingsStore, + getIt.get(), + )); getIt.registerFactory(() => ExchangeTradeViewModel( wallet: getIt.get().wallet!, @@ -498,34 +525,40 @@ Future setup( getIt.registerFactory(() => ExchangePage(getIt.get())); - getIt.registerFactory(() => ExchangeConfirmPage(tradesStore: getIt.get())); + getIt.registerFactory( + () => ExchangeConfirmPage(tradesStore: getIt.get())); + + getIt.registerFactory(() => ExchangeTradePage( + exchangeTradeViewModel: getIt.get())); getIt.registerFactory( - () => ExchangeTradePage(exchangeTradeViewModel: getIt.get())); + () => ExchangeTemplatePage(getIt.get())); - getIt.registerFactory(() => ExchangeTemplatePage(getIt.get())); - - getIt.registerFactoryParam((WalletType param1, __) { + getIt.registerFactoryParam( + (WalletType param1, __) { switch (param1) { case WalletType.haven: return haven!.createHavenWalletService(_walletInfoSource); case WalletType.monero: return monero!.createMoneroWalletService(_walletInfoSource); case WalletType.bitcoin: - return bitcoin!.createBitcoinWalletService(_walletInfoSource, _unspentCoinsInfoSource!); + return bitcoin!.createBitcoinWalletService( + _walletInfoSource, _unspentCoinsInfoSource!); case WalletType.litecoin: - return bitcoin!.createLitecoinWalletService(_walletInfoSource, _unspentCoinsInfoSource!); + return bitcoin!.createLitecoinWalletService( + _walletInfoSource, _unspentCoinsInfoSource!); default: throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService'); } }); - getIt.registerFactory( - () => SetupPinCodeViewModel(getIt.get(), getIt.get())); + getIt.registerFactory(() => SetupPinCodeViewModel( + getIt.get(), getIt.get())); - getIt.registerFactoryParam, String), - void>( - (onSuccessfulPinSetup, _) => SetupPinCodePage(getIt.get(), + getIt.registerFactoryParam, String), void>( + (onSuccessfulPinSetup, _) => SetupPinCodePage( + getIt.get(), onSuccessfulPinSetup: onSuccessfulPinSetup)); getIt.registerFactory(() => RescanViewModel(getIt.get().wallet!)); @@ -534,16 +567,17 @@ Future setup( getIt.registerFactory(() => FaqPage(getIt.get())); - getIt.registerFactoryParam((type, _) => - WalletRestoreViewModel( - getIt.get(), getIt.get(param1: type), _walletInfoSource, + getIt.registerFactoryParam( + (type, _) => WalletRestoreViewModel(getIt.get(), + getIt.get(param1: type), _walletInfoSource, type: type)); - getIt.registerFactoryParam( - (type, _) => WalletRestorePage(getIt.get(param1: type))); + getIt.registerFactoryParam((type, _) => + WalletRestorePage(getIt.get(param1: type))); - getIt.registerFactoryParam( - (TransactionInfo transactionInfo, _) { + getIt + .registerFactoryParam( + (TransactionInfo transactionInfo, _) { final wallet = getIt.get().wallet!; return TransactionDetailsViewModel( transactionInfo: transactionInfo, @@ -557,47 +591,52 @@ Future setup( transactionDetailsViewModel: getIt.get(param1: transactionInfo))); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (param1, _) => NewWalletTypePage(onTypeSelected: param1)); getIt.registerFactoryParam( (WalletType type, _) => PreSeedPage(type)); getIt.registerFactoryParam((trade, _) => - TradeDetailsViewModel( - tradeForDetails: trade, - trades: _tradesSource, + TradeDetailsViewModel(tradeForDetails: trade, trades: _tradesSource, settingsStore: getIt.get())); - getIt.registerFactory(() => BackupService(getIt.get(), _walletInfoSource, - getIt.get(), getIt.get())); + getIt.registerFactory(() => BackupService( + getIt.get(), + _walletInfoSource, + getIt.get(), + getIt.get())); - getIt.registerFactory(() => BackupViewModel( - getIt.get(), getIt.get(), getIt.get())); + getIt.registerFactory(() => BackupViewModel(getIt.get(), + getIt.get(), getIt.get())); getIt.registerFactory(() => BackupPage(getIt.get())); - getIt.registerFactory(() => - EditBackupPasswordViewModel(getIt.get(), getIt.get())); + getIt.registerFactory( + () => EditBackupPasswordViewModel(getIt.get(), getIt.get())); - getIt.registerFactory(() => EditBackupPasswordPage(getIt.get())); + getIt.registerFactory( + () => EditBackupPasswordPage(getIt.get())); getIt.registerFactory(() => RestoreOptionsPage()); - getIt.registerFactory(() => RestoreFromBackupViewModel(getIt.get())); + getIt.registerFactory( + () => RestoreFromBackupViewModel(getIt.get())); - getIt.registerFactory(() => RestoreFromBackupPage(getIt.get())); + getIt.registerFactory( + () => RestoreFromBackupPage(getIt.get())); - getIt.registerFactoryParam( - (Trade trade, _) => TradeDetailsPage(getIt.get(param1: trade))); + getIt.registerFactoryParam((Trade trade, _) => + TradeDetailsPage(getIt.get(param1: trade))); getIt.registerFactory(() => BuyAmountViewModel()); getIt.registerFactory(() { final wallet = getIt.get().wallet; - return BuyViewModel(_ordersSource, getIt.get(), getIt.get(), - getIt.get(), + return BuyViewModel(_ordersSource, getIt.get(), + getIt.get(), getIt.get(), wallet: wallet!); }); @@ -609,8 +648,7 @@ Future setup( final url = args.first as String; final buyViewModel = args[1] as BuyViewModel; - return BuyWebViewPage( - buyViewModel: buyViewModel, ordersStore: getIt.get(), url: url); + return BuyWebViewPage(buyViewModel: buyViewModel, ordersStore: getIt.get(), url: url); }); getIt.registerFactoryParam((order, _) { @@ -619,8 +657,8 @@ Future setup( return OrderDetailsViewModel(wallet: wallet!, orderForDetails: order); }); - getIt.registerFactoryParam( - (Order order, _) => OrderDetailsPage(getIt.get(param1: order))); + getIt.registerFactoryParam((Order order, _) => + OrderDetailsPage(getIt.get(param1: order))); getIt.registerFactory(() => SupportViewModel()); @@ -629,18 +667,20 @@ Future setup( getIt.registerFactory(() { final wallet = getIt.get().wallet; - return UnspentCoinsListViewModel(wallet: wallet!, unspentCoinsInfo: _unspentCoinsInfoSource!); + return UnspentCoinsListViewModel( + wallet: wallet!, unspentCoinsInfo: _unspentCoinsInfoSource!); }); - getIt.registerFactory(() => - UnspentCoinsListPage(unspentCoinsListViewModel: getIt.get())); + getIt.registerFactory(() => UnspentCoinsListPage( + unspentCoinsListViewModel: getIt.get())); getIt.registerFactoryParam( - (item, model) => - UnspentCoinsDetailsViewModel(unspentCoinsItem: item, unspentCoinsListViewModel: model)); + (item, model) => UnspentCoinsDetailsViewModel( + unspentCoinsItem: item, unspentCoinsListViewModel: model)); - getIt.registerFactoryParam((List args, _) { + getIt.registerFactoryParam( + (List args, _) { final item = args.first as UnspentCoinsItem; final unspentCoinsListViewModel = args[1] as UnspentCoinsListViewModel; @@ -653,15 +693,12 @@ Future setup( getIt.registerFactory(() => YatService()); - getIt.registerFactory(() => AddressResolver( - yatService: getIt.get(), walletType: getIt.get().wallet!.type)); + getIt.registerFactory(() => AddressResolver(yatService: getIt.get(), + walletType: getIt.get().wallet!.type)); getIt.registerFactoryParam( - (String qrData, bool isLight) => FullscreenQRPage( - qrData: qrData, - isLight: isLight, - )); - + (String qrData, bool isLight) => FullscreenQRPage(qrData: qrData, isLight: isLight,)); + getIt.registerFactory(() => IoniaApi()); getIt.registerFactory(() => AnyPayApi()); @@ -669,24 +706,26 @@ Future setup( getIt.registerFactory( () => IoniaService(getIt.get(), getIt.get())); - getIt.registerFactory(() => IoniaAnyPay( - getIt.get(), getIt.get(), getIt.get().wallet!)); + getIt.registerFactory( + () => IoniaAnyPay( + getIt.get(), + getIt.get(), + getIt.get().wallet!)); getIt.registerFactory(() => IoniaGiftCardsListViewModel(ioniaService: getIt.get())); getIt.registerFactory(() => IoniaAuthViewModel(ioniaService: getIt.get())); - getIt.registerFactoryParam( - (double amount, merchant) { + getIt.registerFactoryParam((double amount, merchant) { return IoniaMerchPurchaseViewModel( - ioniaAnyPayService: getIt.get(), - amount: amount, - ioniaMerchant: merchant, - sendViewModel: getIt.get()); + ioniaAnyPayService: getIt.get(), + amount: amount, + ioniaMerchant: merchant, + sendViewModel: getIt.get() + ); }); - getIt.registerFactoryParam( - (IoniaMerchant merchant, _) { + getIt.registerFactoryParam((IoniaMerchant merchant, _) { return IoniaBuyCardViewModel(ioniaMerchant: merchant); }); @@ -714,44 +753,42 @@ Future setup( getIt.registerFactoryParam((List args, _) { final amount = args.first as double; final merchant = args.last as IoniaMerchant; - return IoniaBuyGiftCardDetailPage( - getIt.get(param1: amount, param2: merchant)); + return IoniaBuyGiftCardDetailPage(getIt.get(param1: amount, param2: merchant)); }); - getIt.registerFactoryParam( - (IoniaGiftCard giftCard, _) { - return IoniaGiftCardDetailsViewModel( - ioniaService: getIt.get(), giftCard: giftCard); + getIt.registerFactoryParam((IoniaGiftCard giftCard, _) { + return IoniaGiftCardDetailsViewModel( + ioniaService: getIt.get(), + giftCard: giftCard); + }); + + getIt.registerFactoryParam((List args, _) { + final amount = args[0] as double; + final merchant = args[1] as IoniaMerchant; + final tip = args[2] as IoniaTip; + + return IoniaCustomTipViewModel(amount: amount, tip: tip, ioniaMerchant: merchant); + }); + + getIt.registerFactoryParam((IoniaGiftCard giftCard, _) { + return IoniaGiftCardDetailPage(getIt.get(param1: giftCard)); }); - getIt.registerFactoryParam((List args, _) { - final amount = args[0] as double; - final merchant = args[1] as IoniaMerchant; - final tip = args[2] as IoniaTip; - - return IoniaCustomTipViewModel(amount: amount, tip: tip, ioniaMerchant: merchant); - }); - - getIt.registerFactoryParam( - (IoniaGiftCard giftCard, _) { - return IoniaGiftCardDetailPage(getIt.get(param1: giftCard)); - }); - - getIt.registerFactoryParam((List args, _) { + getIt.registerFactoryParam((List args, _){ final giftCard = args.first as IoniaGiftCard; - - return IoniaMoreOptionsPage(giftCard); + + return IoniaMoreOptionsPage(giftCard); }); - getIt.registerFactoryParam( - (IoniaGiftCard giftCard, _) => IoniaCustomRedeemViewModel(giftCard)); + getIt.registerFactoryParam((IoniaGiftCard giftCard, _) => IoniaCustomRedeemViewModel(giftCard)); - getIt.registerFactoryParam((List args, _) { + getIt.registerFactoryParam((List args, _){ final giftCard = args.first as IoniaGiftCard; - - return IoniaCustomRedeemPage(getIt.get(param1: giftCard)); + + return IoniaCustomRedeemPage(getIt.get(param1: giftCard) ); }); + getIt.registerFactoryParam((List args, _) { return IoniaCustomTipPage(getIt.get(param1: args)); }); @@ -766,17 +803,16 @@ Future setup( getIt.registerFactory(() => IoniaAccountCardsPage(getIt.get())); - getIt.registerFactoryParam( - (IoniaAnyPayPaymentInfo paymentInfo, AnyPayPaymentCommittedInfo committedInfo) => - IoniaPaymentStatusViewModel(getIt.get(), - paymentInfo: paymentInfo, committedInfo: committedInfo)); + getIt.registerFactoryParam( + (IoniaAnyPayPaymentInfo paymentInfo, AnyPayPaymentCommittedInfo committedInfo) + => IoniaPaymentStatusViewModel( + getIt.get(), + paymentInfo: paymentInfo, + committedInfo: committedInfo)); - getIt.registerFactoryParam( - (IoniaAnyPayPaymentInfo paymentInfo, AnyPayPaymentCommittedInfo committedInfo) => - IoniaPaymentStatusPage( - getIt.get(param1: paymentInfo, param2: committedInfo))); + getIt.registerFactoryParam( + (IoniaAnyPayPaymentInfo paymentInfo, AnyPayPaymentCommittedInfo committedInfo) + => IoniaPaymentStatusPage(getIt.get(param1: paymentInfo, param2: committedInfo))); _isSetupFinished = true; -} +} \ No newline at end of file diff --git a/lib/view_model/settings/security_settings_view_model.dart b/lib/view_model/settings/security_settings_view_model.dart index 4a88b633f..c48223af6 100644 --- a/lib/view_model/settings/security_settings_view_model.dart +++ b/lib/view_model/settings/security_settings_view_model.dart @@ -1,4 +1,6 @@ +import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/biometric_auth.dart'; +import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:mobx/mobx.dart'; @@ -7,19 +9,33 @@ part 'security_settings_view_model.g.dart'; class SecuritySettingsViewModel = SecuritySettingsViewModelBase with _$SecuritySettingsViewModel; abstract class SecuritySettingsViewModelBase with Store { - SecuritySettingsViewModelBase(this._settingsStore) : _biometricAuth = BiometricAuth(); + SecuritySettingsViewModelBase( + this._settingsStore, + this._authService, + ) : _biometricAuth = BiometricAuth(); final BiometricAuth _biometricAuth; final SettingsStore _settingsStore; + final AuthService _authService; @computed bool get allowBiometricalAuthentication => _settingsStore.allowBiometricalAuthentication; + @computed + PinCodeRequiredDuration get pinCodeRequiredDuration => _settingsStore.pinTimeOutDuration; + @action Future biometricAuthenticated() async { return await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated(); } @action - void setAllowBiometricalAuthentication(bool value) => _settingsStore.allowBiometricalAuthentication = value; + void setAllowBiometricalAuthentication(bool value) => + _settingsStore.allowBiometricalAuthentication = value; + + @action + setPinCodeRequiredDuration(PinCodeRequiredDuration duration) => + _settingsStore.pinTimeOutDuration = duration; + + bool checkPinCodeRiquired() => _authService.requireAuth(); } From 35b7c05bc1650d41b25c3cc67385cd7b5a8caf95 Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 6 Dec 2022 11:41:25 +0200 Subject: [PATCH 108/203] fix null check --- .../sideshift/sideshift_exchange_provider.dart | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/sideshift/sideshift_exchange_provider.dart index 8cd4593c1..23e506858 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/sideshift/sideshift_exchange_provider.dart @@ -249,12 +249,14 @@ class SideShiftExchangeProvider extends ExchangeProvider { final expectedSendAmount = responseJSON['depositAmount'].toString(); final deposits = responseJSON['deposits'] as List?; TradeState? state; - - if (deposits != null && deposits.isEmpty) { - state = TradeState.deserialize(raw: 'created'); - } else { - final status = deposits?[0]['status'] as String; - state = TradeState.deserialize(raw: status); + + if (deposits != null) { + if (deposits.isEmpty) { + state = TradeState.deserialize(raw: 'created'); + } else { + final status = deposits[0]['status'] as String; + state = TradeState.deserialize(raw: status); + } } final expiredAtRaw = responseJSON['expiresAtISO'] as String; From 36c27026881c4bbbd957fd65cfbfb64a9c76d301 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 6 Dec 2022 13:30:11 +0200 Subject: [PATCH 109/203] - Recalculate best rate if isFixedRate changed - check limits against the receive amount if isFixedRate --- .../exchange/exchange_view_model.dart | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index b19434166..cda65527a 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -44,7 +44,6 @@ abstract class ExchangeViewModelBase with Store { ExchangeViewModelBase(this.wallet, this.trades, this._exchangeTemplateStore, this.tradesStore, this._settingsStore, this.sharedPreferences) : _cryptoNumberFormat = NumberFormat(), - isReverse = false, isFixedRateMode = false, isReceiveAmountEntered = false, depositAmount = '', @@ -112,7 +111,11 @@ abstract class ExchangeViewModelBase with Store { loadLimits(); reaction( (_) => isFixedRateMode, - (Object _) => loadLimits()); + (Object _) { + loadLimits(); + _bestRate = 0; + _calculateBestRate(); + }); } final WalletBase wallet; @@ -227,8 +230,6 @@ abstract class ExchangeViewModelBase with Store { Limits limits; - bool isReverse; - NumberFormat _cryptoNumberFormat; final SettingsStore _settingsStore; @@ -258,7 +259,6 @@ abstract class ExchangeViewModelBase with Store { @action Future changeReceiveAmount({required String amount}) async { receiveAmount = amount; - isReverse = true; if (amount.isEmpty) { depositAmount = ''; @@ -283,7 +283,6 @@ abstract class ExchangeViewModelBase with Store { @action Future changeDepositAmount({required String amount}) async { depositAmount = amount; - isReverse = false; if (amount.isEmpty) { depositAmount = ''; @@ -307,7 +306,7 @@ abstract class ExchangeViewModelBase with Store { } Future _calculateBestRate() async { - final amount = double.tryParse(isFixedRateMode ? receiveAmount : depositAmount) ?? 1; + final amount = double.tryParse(depositAmount) ?? 1; final result = await Future.wait( _tradeAvailableProviders @@ -401,7 +400,7 @@ abstract class ExchangeViewModelBase with Store { settleAddress: receiveAddress, refundAddress: depositAddress, ); - amount = depositAmount; + amount = isFixedRateMode ? receiveAmount : depositAmount; } if (provider is SimpleSwapExchangeProvider) { @@ -412,7 +411,7 @@ abstract class ExchangeViewModelBase with Store { address: receiveAddress, refundAddress: depositAddress, ); - amount = depositAmount; + amount = isFixedRateMode ? receiveAmount : depositAmount; } if (provider is XMRTOExchangeProvider) { @@ -424,7 +423,7 @@ abstract class ExchangeViewModelBase with Store { address: receiveAddress, refundAddress: depositAddress, isBTCRequest: isReceiveAmountEntered); - amount = depositAmount; + amount = isFixedRateMode ? receiveAmount : depositAmount; } if (provider is ChangeNowExchangeProvider) { @@ -435,8 +434,8 @@ abstract class ExchangeViewModelBase with Store { toAmount: receiveAmount.replaceAll(',', '.'), refundAddress: depositAddress, address: receiveAddress, - isReverse: isReverse); - amount = isReverse ? receiveAmount : depositAmount; + isReverse: isFixedRateMode); + amount = isFixedRateMode ? receiveAmount : depositAmount; } if (provider is MorphTokenExchangeProvider) { @@ -446,13 +445,13 @@ abstract class ExchangeViewModelBase with Store { amount: depositAmount.replaceAll(',', '.'), refundAddress: depositAddress, address: receiveAddress); - amount = depositAmount; + amount = isFixedRateMode ? receiveAmount : depositAmount; } amount = amount.replaceAll(',', '.'); if (limitsState is LimitsLoadedSuccessfully) { - if (double.parse(amount) < limits.min!) { + if (limits.max != null && double.parse(amount) < limits.min!) { continue; } else if (limits.max != null && double.parse(amount) > limits.max!) { continue; From 8514887da6f48262b8f5ab6aed254167bf43502b Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 6 Dec 2022 15:40:40 +0200 Subject: [PATCH 110/203] Negate is Fixed rate mode in simpleswap --- .../simpleswap/simpleswap_exchange_provider.dart | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart b/lib/exchange/simpleswap/simpleswap_exchange_provider.dart index c6e1baeea..0fb799cec 100644 --- a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart +++ b/lib/exchange/simpleswap/simpleswap_exchange_provider.dart @@ -20,8 +20,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { .where((i) => i != CryptoCurrency.zaddr) .map((i) => CryptoCurrency.all .where((i) => i != CryptoCurrency.zaddr) - .map((k) => ExchangePair(from: i, to: k, reverse: true)) - .where((c) => c != null)) + .map((k) => ExchangePair(from: i, to: k, reverse: true))) .expand((i) => i) .toList()); @@ -54,12 +53,12 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { 'currency_from': fromCurrency, 'currency_to': toCurrency, 'amount': amount.toString(), - 'fixed': isFixedRateMode.toString() + 'fixed': (!isFixedRateMode).toString() }; final uri = Uri.https(apiAuthority, getEstimatePath, params); final response = await get(uri); - if (response.body == null || response.body == "null") return 0.00; + if (response.body == "null") return 0.00; final data = json.decode(response.body) as String; return double.parse(data); } catch (_) { @@ -87,7 +86,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { "currency_from": _normalizeCryptoCurrency(_request.from), "currency_to": _normalizeCryptoCurrency(_request.to), "amount": _request.amount, - "fixed": isFixedRateMode, + "fixed": !isFixedRateMode, "user_refund_address": _request.refundAddress, "address_to": _request.address }; From f29f17476c0faf16dfc169067841c9b937511d66 Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 6 Dec 2022 17:14:07 +0200 Subject: [PATCH 111/203] add null check [skip ci] --- .../sideshift/sideshift_exchange_provider.dart | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/sideshift/sideshift_exchange_provider.dart index 23e506858..0cd74061f 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/sideshift/sideshift_exchange_provider.dart @@ -249,15 +249,12 @@ class SideShiftExchangeProvider extends ExchangeProvider { final expectedSendAmount = responseJSON['depositAmount'].toString(); final deposits = responseJSON['deposits'] as List?; TradeState? state; - - if (deposits != null) { - if (deposits.isEmpty) { - state = TradeState.deserialize(raw: 'created'); - } else { - final status = deposits[0]['status'] as String; - state = TradeState.deserialize(raw: status); - } + String? status; + + if (deposits?.isNotEmpty ?? false) { + status = deposits![0]['status'] as String; } + state = TradeState.deserialize(raw: status ?? 'created'); final expiredAtRaw = responseJSON['expiresAtISO'] as String; final expiredAt = From fa5c705bc888abea53703ca06589e344a63d7ee8 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 6 Dec 2022 17:29:44 +0200 Subject: [PATCH 112/203] Add nullability to `status` String [skip ci] --- lib/exchange/sideshift/sideshift_exchange_provider.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/sideshift/sideshift_exchange_provider.dart index 0cd74061f..920dc9907 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/sideshift/sideshift_exchange_provider.dart @@ -252,7 +252,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { String? status; if (deposits?.isNotEmpty ?? false) { - status = deposits![0]['status'] as String; + status = deposits![0]['status'] as String?; } state = TradeState.deserialize(raw: status ?? 'created'); From f14c01303fa08dd0a8d80571bf61e16ac990da39 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 6 Dec 2022 19:23:46 +0200 Subject: [PATCH 113/203] - Add whether this provide supports fixed rate or not - Fix Change now fixed rate exchange due to wrong rate id --- .../changenow_exchange_provider.dart | 20 +++++++++++++------ lib/exchange/exchange_provider.dart | 2 +- .../morphtoken_exchange_provider.dart | 3 +++ .../sideshift_exchange_provider.dart | 10 +++++----- .../simpleswap_exchange_provider.dart | 3 +++ .../xmrto/xmrto_exchange_provider.dart | 3 +++ .../exchange/exchange_view_model.dart | 3 ++- 7 files changed, 31 insertions(+), 13 deletions(-) diff --git a/lib/exchange/changenow/changenow_exchange_provider.dart b/lib/exchange/changenow/changenow_exchange_provider.dart index 96b6142e6..8ef376370 100644 --- a/lib/exchange/changenow/changenow_exchange_provider.dart +++ b/lib/exchange/changenow/changenow_exchange_provider.dart @@ -11,7 +11,6 @@ import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/exchange/changenow/changenow_request.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/exchange/trade_not_created_exeption.dart'; class ChangeNowExchangeProvider extends ExchangeProvider { ChangeNowExchangeProvider() @@ -21,8 +20,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { .where((i) => i != CryptoCurrency.xhv) .map((i) => CryptoCurrency.all .where((i) => i != CryptoCurrency.xhv) - .map((k) => ExchangePair(from: i, to: k, reverse: true)) - .where((c) => c != null)) + .map((k) => ExchangePair(from: i, to: k, reverse: true))) .expand((i) => i) .toList()); @@ -43,6 +41,9 @@ class ChangeNowExchangeProvider extends ExchangeProvider { @override bool get isEnabled => true; + @override + bool get supportsFixedRate => true; + @override ExchangeProviderDescription get description => ExchangeProviderDescription.changeNow; @@ -109,6 +110,15 @@ class ChangeNowExchangeProvider extends ExchangeProvider { }; if (isFixedRateMode) { + // since we schedule to calculate the rate every 5 seconds we need to ensure that + // we have the latest rate id with the given inputs before creating the trade + await calculateAmount( + from: _request.to, + to: _request.from, + amount: double.tryParse(_request.toAmount) ?? 0, + isFixedRateMode: true, + isReceiveAmount: true, + ); body['rateId'] = _lastUsedRateId; } @@ -180,9 +190,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { final extraId = responseJSON['payinExtraId'] as String; final outputTransaction = responseJSON['payoutHash'] as String; final expiredAtRaw = responseJSON['validUntil'] as String; - final expiredAt = expiredAtRaw != null - ? DateTime.parse(expiredAtRaw).toLocal() - : null; + final expiredAt = DateTime.tryParse(expiredAtRaw)?.toLocal(); return Trade( id: id, diff --git a/lib/exchange/exchange_provider.dart b/lib/exchange/exchange_provider.dart index 14fba803f..108256015 100644 --- a/lib/exchange/exchange_provider.dart +++ b/lib/exchange/exchange_provider.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/exchange_pair.dart'; @@ -14,6 +13,7 @@ abstract class ExchangeProvider { ExchangeProviderDescription get description; bool get isAvailable; bool get isEnabled; + bool get supportsFixedRate; @override String toString() => title; diff --git a/lib/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/exchange/morphtoken/morphtoken_exchange_provider.dart index 1df4fef87..6650d4f3a 100644 --- a/lib/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -66,6 +66,9 @@ class MorphTokenExchangeProvider extends ExchangeProvider { @override bool get isEnabled => true; + @override + bool get supportsFixedRate => false; + @override ExchangeProviderDescription get description => ExchangeProviderDescription.morphToken; diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/sideshift/sideshift_exchange_provider.dart index 920dc9907..b93f0a80f 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/sideshift/sideshift_exchange_provider.dart @@ -12,7 +12,6 @@ import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/exchange/limits.dart'; -import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; class SideShiftExchangeProvider extends ExchangeProvider { @@ -48,8 +47,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { return supportedCurrencies .map((i) => supportedCurrencies - .map((k) => ExchangePair(from: i, to: k, reverse: true)) - .where((c) => c != null)) + .map((k) => ExchangePair(from: i, to: k, reverse: true))) .expand((i) => i) .toList(); } @@ -257,8 +255,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { state = TradeState.deserialize(raw: status ?? 'created'); final expiredAtRaw = responseJSON['expiresAtISO'] as String; - final expiredAt = - expiredAtRaw != null ? DateTime.parse(expiredAtRaw).toLocal() : null; + final expiredAt = DateTime.tryParse(expiredAtRaw)?.toLocal(); return Trade( id: id, @@ -278,6 +275,9 @@ class SideShiftExchangeProvider extends ExchangeProvider { @override bool get isEnabled => true; + @override + bool get supportsFixedRate => true; + @override String get title => 'SideShift'; diff --git a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart b/lib/exchange/simpleswap/simpleswap_exchange_provider.dart index 0fb799cec..97681f0aa 100644 --- a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart +++ b/lib/exchange/simpleswap/simpleswap_exchange_provider.dart @@ -209,6 +209,9 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { @override bool get isEnabled => true; + @override + bool get supportsFixedRate => false; + @override String get title => 'SimpleSwap'; diff --git a/lib/exchange/xmrto/xmrto_exchange_provider.dart b/lib/exchange/xmrto/xmrto_exchange_provider.dart index d5f79361e..da367e4d4 100644 --- a/lib/exchange/xmrto/xmrto_exchange_provider.dart +++ b/lib/exchange/xmrto/xmrto_exchange_provider.dart @@ -48,6 +48,9 @@ class XMRTOExchangeProvider extends ExchangeProvider { @override bool get isEnabled => true; + @override + bool get supportsFixedRate => false; + @override ExchangeProviderDescription get description => ExchangeProviderDescription.xmrto; diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index cda65527a..49ee9ea95 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -306,10 +306,11 @@ abstract class ExchangeViewModelBase with Store { } Future _calculateBestRate() async { - final amount = double.tryParse(depositAmount) ?? 1; + final amount = double.tryParse(isFixedRateMode ? receiveAmount : depositAmount) ?? 1; final result = await Future.wait( _tradeAvailableProviders + .where((element) => element.supportsFixedRate) .map((element) => element.calculateAmount( from: depositCurrency, to: receiveCurrency, From 117a8beec403cd31d6570a576fdb533b4d270619 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 6 Dec 2022 19:40:39 +0200 Subject: [PATCH 114/203] Fix localization generation error --- res/values/strings_de.arb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index e90803444..dd88cc042 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -662,5 +662,5 @@ "privacy_settings": "Datenschutzeinstellungen", "privacy": "Datenschutz", "display_settings": "Anzeigeeinstellungen", - "other_settings": "Andere Einstellungen", + "other_settings": "Andere Einstellungen" } From a9f0466825247f6e2a877aac3799851adb1bd142 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 6 Dec 2022 20:10:26 +0200 Subject: [PATCH 115/203] Revert SimpleSwap changes since we disabled it for fixed rate --- lib/exchange/simpleswap/simpleswap_exchange_provider.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart b/lib/exchange/simpleswap/simpleswap_exchange_provider.dart index 97681f0aa..4c42835ed 100644 --- a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart +++ b/lib/exchange/simpleswap/simpleswap_exchange_provider.dart @@ -53,7 +53,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { 'currency_from': fromCurrency, 'currency_to': toCurrency, 'amount': amount.toString(), - 'fixed': (!isFixedRateMode).toString() + 'fixed': isFixedRateMode.toString() }; final uri = Uri.https(apiAuthority, getEstimatePath, params); final response = await get(uri); @@ -86,7 +86,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { "currency_from": _normalizeCryptoCurrency(_request.from), "currency_to": _normalizeCryptoCurrency(_request.to), "amount": _request.amount, - "fixed": !isFixedRateMode, + "fixed": isFixedRateMode, "user_refund_address": _request.refundAddress, "address_to": _request.address }; From f4148e0989a00081e20ed3f08154a98e5460a5ec Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 7 Dec 2022 01:38:36 +0200 Subject: [PATCH 116/203] [skip ci] rework UI for disable fiat mode --- lib/core/backup_service.dart | 7 ++++ lib/entities/default_settings_migration.dart | 18 ++++++++- lib/entities/fiat_api_mode.dart | 39 +++++++++++++++++++ lib/entities/preferences_key.dart | 2 +- lib/src/screens/send/widgets/send_card.dart | 2 +- lib/src/screens/settings/privacy_page.dart | 13 ++++++- lib/store/settings_store.dart | 24 ++++++------ .../dashboard/balance_view_model.dart | 4 +- .../settings/privacy_settings_view_model.dart | 7 ++++ 9 files changed, 98 insertions(+), 18 deletions(-) create mode 100644 lib/entities/fiat_api_mode.dart diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 999b67120..46868cf1a 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -214,6 +214,7 @@ class BackupService { final currentBitcoinElectrumSererId = data[PreferencesKey.currentBitcoinElectrumSererIdKey] as int?; final currentLanguageCode = data[PreferencesKey.currentLanguageCode] as String?; final displayActionListMode = data[PreferencesKey.displayActionListModeKey] as int?; + final fiatApiMode = data[PreferencesKey.currentFiatApiModeKey] as int?; final currentPinLength = data[PreferencesKey.currentPinLength] as int?; final currentTheme = data[PreferencesKey.currentTheme] as int?; final currentDefaultSettingsMigrationVersion = data[PreferencesKey.currentDefaultSettingsMigrationVersion] as int?; @@ -266,6 +267,10 @@ class BackupService { await _sharedPreferences.setInt(PreferencesKey.displayActionListModeKey, displayActionListMode); + if (fiatApiMode != null) + await _sharedPreferences.setInt(PreferencesKey.currentFiatApiModeKey, + fiatApiMode); + if (currentPinLength != null) await _sharedPreferences.setInt(PreferencesKey.currentPinLength, currentPinLength); @@ -427,6 +432,8 @@ class BackupService { _sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority), PreferencesKey.moneroTransactionPriority: _sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority), + PreferencesKey.currentFiatApiModeKey: + _sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey), }; return json.encode(preferences); diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 40d26b93f..d65b4401d 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -20,6 +20,8 @@ import 'package:cake_wallet/exchange/trade.dart'; import 'package:encrypt/encrypt.dart' as encrypt; import 'package:collection/collection.dart'; +import 'fiat_api_mode.dart'; + const newCakeWalletMoneroUri = 'xmr-node.cakewallet.com:18081'; const cakeWalletBitcoinElectrumUri = 'electrum.cakewallet.com:50002'; const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002'; @@ -61,7 +63,9 @@ Future defaultSettingsMigration( await sharedPreferences.setInt( PreferencesKey.currentBalanceDisplayModeKey, BalanceDisplayMode.availableBalance.raw); - await sharedPreferences.setBool('disable_fiat', false); + await sharedPreferences.setInt( + PreferencesKey.currentFiatApiModeKey, + FiatApiMode.enabled.raw); await sharedPreferences.setBool('save_recipient_address', true); await resetToDefault(nodes); await changeMoneroCurrentNodeToDefault( @@ -140,6 +144,10 @@ Future defaultSettingsMigration( await addOnionNode(nodes); break; + case 19: + await updateFiatApiModes(sharedPreferences); + break; + default: break; } @@ -350,6 +358,14 @@ Future updateDisplayModes(SharedPreferences sharedPreferences) async { PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode); } +Future updateFiatApiModes(SharedPreferences sharedPreferences) async { + final currentFiatApiMode = + sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? -1; + final fiatApiMode = currentFiatApiMode < 1 ? 2 : 1; + await sharedPreferences.setInt( + PreferencesKey.currentFiatApiModeKey, fiatApiMode); +} + Future generateBackupPassword(FlutterSecureStorage secureStorage) async { final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword); diff --git a/lib/entities/fiat_api_mode.dart b/lib/entities/fiat_api_mode.dart new file mode 100644 index 000000000..615784986 --- /dev/null +++ b/lib/entities/fiat_api_mode.dart @@ -0,0 +1,39 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cw_core/enumerable_item.dart'; + +class FiatApiMode extends EnumerableItem with Serializable { + const FiatApiMode({required String title, required int raw}) : super(title: title, raw: raw); + + static const all = [FiatApiMode.enabled, FiatApiMode.torOnly, FiatApiMode.disabled]; + + static const enabled = FiatApiMode(raw: 0, title: 'Enabled'); + static const torOnly = FiatApiMode(raw: 1, title: 'Tor only'); + static const disabled = FiatApiMode(raw: 2, title: 'Disabled'); + + static FiatApiMode deserialize({required int raw}) { + switch (raw) { + case 0: + return enabled; + case 1: + return torOnly; + case 2: + return disabled; + default: + throw Exception('Unexpected token: $raw for FiatApiMode deserialize'); + } + } + + @override + String toString() { + switch (this) { + case FiatApiMode.enabled: + return 'enable'; + case FiatApiMode.torOnly: + return 'torOnly'; + case FiatApiMode.disabled: + return 'disable'; + default: + return ''; + } + } +} diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 0df7981bd..7d1d75000 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -9,7 +9,7 @@ class PreferencesKey { static const currentTransactionPriorityKeyLegacy = 'current_fee_priority'; static const currentBalanceDisplayModeKey = 'current_balance_display_mode'; static const shouldSaveRecipientAddressKey = 'save_recipient_address'; - static const shouldDisableFiatKey = 'disable_fiat'; + static const currentFiatApiModeKey = 'current_fiat_api_mode'; static const allowBiometricalAuthenticationKey = 'allow_biometrical_authentication'; static const disableExchangeKey = 'disable_exchange'; diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 60da5a8ea..503494c92 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -331,7 +331,7 @@ class SendCardState extends State ], ), )), - if (sendViewModel.balanceViewModel.disableFiat) + if (!sendViewModel.balanceViewModel.disableFiat) Padding( padding: const EdgeInsets.only(top: 20), child: BaseTextFormField( diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index 128d864f4..34957fa4a 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -1,9 +1,12 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; +import 'package:cake_wallet/entities/fiat_api_mode.dart'; class PrivacyPage extends BasePage { PrivacyPage(this._privacySettingsViewModel); @@ -18,10 +21,17 @@ class PrivacyPage extends BasePage { return Container( padding: EdgeInsets.only(top: 10), child: Observer(builder: (_) { - return Observer(builder: (_) { return Column( mainAxisSize: MainAxisSize.min, children: [ + SettingsChoicesCell( + ChoicesListItem( + title: 'Fiat api', + items: FiatApiMode.all, + selectedItem: _privacySettingsViewModel.fiatApiMode, + onItemSelected: (FiatApiMode mode) => _privacySettingsViewModel.setFiatMode(mode), + ), + ), SettingsSwitcherCell( title: S.current.disable_exchange, value: _privacySettingsViewModel.disableExchange, @@ -36,7 +46,6 @@ class PrivacyPage extends BasePage { }) ], ); - }); }), ); } diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 1f49be479..419b03e49 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -17,8 +17,10 @@ import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cw_core/node.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/entities/action_list_display_mode.dart'; +import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; + part 'settings_store.g.dart'; class SettingsStore = SettingsStoreBase with _$SettingsStore; @@ -29,7 +31,7 @@ abstract class SettingsStoreBase with Store { required FiatCurrency initialFiatCurrency, required BalanceDisplayMode initialBalanceDisplayMode, required bool initialSaveRecipientAddress, - required bool initialDisableFiat, + required FiatApiMode initialFiatMode, required bool initialAllowBiometricalAuthentication, required bool initialExchangeEnabled, required ThemeBase initialTheme, @@ -48,7 +50,7 @@ abstract class SettingsStoreBase with Store { fiatCurrency = initialFiatCurrency, balanceDisplayMode = initialBalanceDisplayMode, shouldSaveRecipientAddress = initialSaveRecipientAddress, - shouldDisableFiat = initialDisableFiat, + fiatApiMode = initialFiatMode, allowBiometricalAuthentication = initialAllowBiometricalAuthentication, disableExchange = initialExchangeEnabled, currentTheme = initialTheme, @@ -92,10 +94,9 @@ abstract class SettingsStoreBase with Store { shouldSaveRecipientAddress)); reaction( - (_) => shouldDisableFiat, - (bool shouldDisableFiat) => sharedPreferences.setBool( - PreferencesKey.shouldDisableFiatKey, - shouldDisableFiat)); + (_) => fiatApiMode, + (FiatApiMode mode) => sharedPreferences.setInt( + PreferencesKey.currentFiatApiModeKey, mode.serialize())); reaction( (_) => currentTheme, @@ -148,10 +149,10 @@ abstract class SettingsStoreBase with Store { BalanceDisplayMode balanceDisplayMode; @observable - bool shouldSaveRecipientAddress; + FiatApiMode fiatApiMode; @observable - bool shouldDisableFiat; + bool shouldSaveRecipientAddress; @observable bool allowBiometricalAuthentication; @@ -234,8 +235,9 @@ abstract class SettingsStoreBase with Store { // FIX-ME: Check for which default value we should have here final shouldSaveRecipientAddress = sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? false; - final shouldDisableFiat = - sharedPreferences.getBool(PreferencesKey.shouldDisableFiatKey) ?? false; + final currentFiatApiMode = FiatApiMode.deserialize( + raw: sharedPreferences + .getInt(PreferencesKey.currentFiatApiModeKey)!); final allowBiometricalAuthentication = sharedPreferences .getBool(PreferencesKey.allowBiometricalAuthenticationKey) ?? false; @@ -303,7 +305,7 @@ abstract class SettingsStoreBase with Store { initialFiatCurrency: currentFiatCurrency, initialBalanceDisplayMode: currentBalanceDisplayMode, initialSaveRecipientAddress: shouldSaveRecipientAddress, - initialDisableFiat: shouldDisableFiat, + initialFiatMode: currentFiatApiMode, initialAllowBiometricalAuthentication: allowBiometricalAuthentication, initialExchangeEnabled: disableExchange, initialTheme: savedTheme, diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index 40502bb84..6728859da 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/balance.dart'; @@ -10,7 +11,6 @@ import 'package:cake_wallet/entities/calculate_fiat_amount.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; -import 'package:flutter/cupertino.dart'; import 'package:mobx/mobx.dart'; part 'balance_view_model.g.dart'; @@ -72,7 +72,7 @@ abstract class BalanceViewModelBase with Store { BalanceDisplayMode get savedDisplayMode => settingsStore.balanceDisplayMode; @computed - bool get disableFiat => settingsStore.shouldDisableFiat; + bool get disableFiat => settingsStore.fiatApiMode == FiatApiMode.disabled; @computed String get asset { diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index 88311bf1f..2d8418d11 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/store/settings_store.dart'; import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/entities/fiat_api_mode.dart'; part 'privacy_settings_view_model.g.dart'; @@ -16,9 +17,15 @@ abstract class PrivacySettingsViewModelBase with Store { @computed bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress; + @computed + FiatApiMode get fiatApiMode => _settingsStore.fiatApiMode; + @action void setShouldSaveRecipientAddress(bool value) => _settingsStore.shouldSaveRecipientAddress = value; @action void setEnableExchange(bool value) => _settingsStore.disableExchange = value; + + @action + void setFiatMode(FiatApiMode mode) => _settingsStore.fiatApiMode = mode; } From 228e157b3992db2efbba68fe5ef4f820422d5772 Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 7 Dec 2022 14:04:14 +0200 Subject: [PATCH 117/203] [skip ci] Update localization --- lib/entities/fiat_api_mode.dart | 6 +++--- lib/reactions/fiat_rate_update.dart | 3 ++- lib/src/screens/settings/privacy_page.dart | 2 +- res/values/strings_de.arb | 7 +++++-- res/values/strings_en.arb | 7 +++++-- res/values/strings_es.arb | 7 +++++-- res/values/strings_fr.arb | 7 +++++-- res/values/strings_hi.arb | 7 +++++-- res/values/strings_hr.arb | 7 +++++-- res/values/strings_it.arb | 7 +++++-- res/values/strings_ja.arb | 7 +++++-- res/values/strings_ko.arb | 7 +++++-- res/values/strings_nl.arb | 7 +++++-- res/values/strings_pl.arb | 7 +++++-- res/values/strings_pt.arb | 7 +++++-- res/values/strings_ru.arb | 7 +++++-- res/values/strings_uk.arb | 7 +++++-- res/values/strings_zh.arb | 7 +++++-- 18 files changed, 81 insertions(+), 35 deletions(-) diff --git a/lib/entities/fiat_api_mode.dart b/lib/entities/fiat_api_mode.dart index 615784986..bb16ca5a4 100644 --- a/lib/entities/fiat_api_mode.dart +++ b/lib/entities/fiat_api_mode.dart @@ -27,11 +27,11 @@ class FiatApiMode extends EnumerableItem with Serializable { String toString() { switch (this) { case FiatApiMode.enabled: - return 'enable'; + return S.current.enabled; case FiatApiMode.torOnly: - return 'torOnly'; + return S.current.tor_only; case FiatApiMode.disabled: - return 'disable'; + return S.current.disabled; default: return ''; } diff --git a/lib/reactions/fiat_rate_update.dart b/lib/reactions/fiat_rate_update.dart index fb40a26e3..ff10a176c 100644 --- a/lib/reactions/fiat_rate_update.dart +++ b/lib/reactions/fiat_rate_update.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'package:cake_wallet/core/fiat_conversion_service.dart'; +import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/update_haven_rate.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; @@ -28,7 +29,7 @@ Future startFiatRateUpdate(AppStore appStore, SettingsStore settingsStore, await updateHavenRate(fiatConversionStore); } else { fiatConversionStore.prices[appStore.wallet!.currency] = - settingsStore.shouldDisableFiat ? 0.0 + settingsStore.fiatApiMode == FiatApiMode.disabled ? 0.0 : await FiatConversionService.fetchPrice( appStore.wallet!.currency, settingsStore.fiatCurrency); } diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index 34957fa4a..a0fc280b9 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -26,7 +26,7 @@ class PrivacyPage extends BasePage { children: [ SettingsChoicesCell( ChoicesListItem( - title: 'Fiat api', + title: S.current.fiat_api, items: FiatApiMode.all, selectedItem: _privacySettingsViewModel.fiatApiMode, onItemSelected: (FiatApiMode mode) => _privacySettingsViewModel.setFiatMode(mode), diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index dd88cc042..ecbd3838e 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -654,7 +654,7 @@ "use_suggested": "Vorgeschlagen verwenden", "do_not_share_warning_text" : "Teilen Sie diese nicht mit anderen, einschließlich des Supports.\n\nSie werden Ihr Geld stehlen!", "help": "hilfe", - "disable_fiat": "Fiat deaktivieren", + "fiat_api": "Fiat API", "disable_exchange": "Exchange deaktivieren", "connection_sync": "Verbindung und Synchronisierung", "security_and_backup": "Sicherheit und Datensicherung", @@ -662,5 +662,8 @@ "privacy_settings": "Datenschutzeinstellungen", "privacy": "Datenschutz", "display_settings": "Anzeigeeinstellungen", - "other_settings": "Andere Einstellungen" + "other_settings": "Andere Einstellungen", + "disabled": "Deaktiviert", + "enabled": "Ermöglicht", + "tor_only": "Nur Tor" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 753ad18a9..c6d71a2b1 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -654,7 +654,7 @@ "use_suggested": "Use Suggested", "do_not_share_warning_text" : "Do not share these with anyone else, including support.\n\nThey will steal your money!", "help": "help", - "disable_fiat": "Disable fiat", + "fiat_api": "Fiat API", "disable_exchange": "Disable exchange", "connection_sync": "Connection and sync", "security_and_backup": "Security and backup", @@ -662,5 +662,8 @@ "privacy_settings": "Privacy settings", "privacy": "Privacy", "display_settings": "Display settings", - "other_settings": "Other settings" + "other_settings": "Other settings", + "disabled": "Disabled", + "enabled": "Enabled", + "tor_only": "Tor only" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 6efcb85a0..09878ede1 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -654,7 +654,7 @@ "use_suggested": "Usar sugerido", "do_not_share_warning_text" : "No comparta estos con nadie más, incluido el soporte.\n\n¡Te robarán tu dinero!", "help": "ayuda", - "disable_fiat": "Deshabilitar fiat", + "fiat_api": "Fiat API", "disable_exchange": "Deshabilitar intercambio", "connection_sync": "Conexión y sincronización", "security_and_backup": "Seguridad y respaldo", @@ -662,5 +662,8 @@ "privacy_settings": "Configuración de privacidad", "privacy": "Privacidad", "display_settings": "Configuración de pantalla", - "other_settings": "Otras configuraciones" + "other_settings": "Otras configuraciones", + "disabled": "Desactivado", + "enabled": "Activado", + "tor_only": "solo Tor" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index aefe68b96..66f60af81 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -652,7 +652,7 @@ "use_suggested": "Utilisation suggérée", "do_not_share_warning_text" : "Ne les partagez avec personne d'autre, y compris avec l'assistance.\n\nIls vont voler votre argent!", "help": "aider", - "disable_fiat": "Désactiver fiat", + "fiat_api": "Fiat API", "disable_exchange": "Désactiver l'échange", "connection_sync": "Connexion et synchronisation", "security_and_backup": "Sécurité et sauvegarde", @@ -660,5 +660,8 @@ "privacy_settings": "Paramètres de confidentialité", "privacy": "Confidentialité", "display_settings": "Paramètres d'affichage", - "other_settings": "Autres paramètres" + "other_settings": "Autres paramètres", + "disabled": "Handicapé", + "enabled": "Activé", + "tor_only": "Tor uniquement" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 52b46ee60..a25b649c3 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -655,12 +655,15 @@ "do_not_share_warning_text" : "इन्हें समर्थन सहित किसी और के साथ साझा न करें।\n\nवे आपका पैसा चुरा लेंगे!", "help": "मदद करना", "disable_fiat": "िएट अक्षम करें", - "disable_exchange": "एक्सचेंज अक्षम करें", + "fiat_api": "फिएट पैसे API", "connection_sync": "कनेक्शन और सिंक", "security_and_backup": "सुरक्षा और बैकअप", "create_backup": "बैकअप बनाएँ", "privacy_settings": "गोपनीयता सेटिंग्स", "privacy": "गोपनीयता", "display_settings": "प्रदर्शन सेटिंग्स", - "other_settings": "अन्य सेटिंग्स" + "other_settings": "अन्य सेटिंग्स", + "disabled": "अक्षम", + "enabled": "सक्रिय", + "tor_only": "Tor केवल" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index f2181bca0..e7e0ff1e4 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -654,7 +654,7 @@ "use_suggested": "Koristite predloženo", "do_not_share_warning_text" : "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nUkrast će vam novac!", "help": "pomozite", - "disable_fiat": "Isključi, fiat", + "fiat_api": "Fiat API", "disable_exchange": "Onemogući exchange", "connection_sync": "Povezivanje i sinkronizacija", "security_and_backup": "Sigurnost i sigurnosna kopija", @@ -662,5 +662,8 @@ "privacy_settings": "Postavke privatnosti", "privacy": "Privatnost", "display_settings": "Postavke zaslona", - "other_settings": "Ostale postavke" + "other_settings": "Ostale postavke", + "disabled": "Onemogućeno", + "enabled": "Omogućeno", + "tor_only": "Samo Tor" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 1ec0a9d81..80a0ea1fd 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -654,7 +654,7 @@ "use_suggested": "Usa suggerito", "do_not_share_warning_text" : "Non condividerli con nessun altro, incluso il supporto.\n\nTi ruberanno i soldi!", "help": "aiuto", - "disable_fiat": "Disabilita fiat", + "fiat_api": "Fiat API", "disable_exchange": "Disabilita scambio", "connection_sync": "Connessione e sincronizzazione", "security_and_backup": "Sicurezza e backup", @@ -662,5 +662,8 @@ "privacy_settings": "Impostazioni privacy", "privacy": "Privacy", "display_settings": "Impostazioni di visualizzazione", - "other_settings": "Altre impostazioni" + "other_settings": "Altre impostazioni", + "disabled": "Disabilitato", + "enabled": "Abilitato", + "tor_only": "Solo Tor" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 6fde3fc91..b38066916 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -654,7 +654,7 @@ "use_suggested": "推奨を使用", "do_not_share_warning_text" : "サポートを含め、これらを他の誰とも共有しないでください。\n\n彼らはあなたのお金を盗みます!", "help": "ヘルプ", - "disable_fiat": "フィアットを無効にする", + "fiat_api": "不換紙幣 API", "disable_exchange": "交換を無効にする", "connection_sync": "接続と同期", "security_and_backup": "セキュリティとバックアップ", @@ -662,5 +662,8 @@ "privacy_settings": "プライバシー設定", "privacy": "プライバシー", "display_settings": "表示設定", - "other_settings": "その他の設定" + "other_settings": "その他の設定", + "disabled": "無効", + "enabled": "有効", + "tor_only": "Torのみ" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 4f2e7da5e..e4915cbb0 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -654,7 +654,7 @@ "use_suggested": "추천 사용", "do_not_share_warning_text" : "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n그들은 당신의 돈을 훔칠 것입니다!", "help": "돕다", - "disable_fiat": "법정화폐 비활성화", + "fiat_api": "명목 화폐 API", "disable_exchange": "교환 비활성화", "connection_sync": "연결 및 동기화", "security_and_backup": "보안 및 백업", @@ -662,5 +662,8 @@ "privacy_settings": "개인정보 설정", "privacy": "프라이버시", "display_settings": "디스플레이 설정", - "other_settings": "기타 설정" + "other_settings": "기타 설정", + "disabled": "장애가 있는", + "enabled": "사용", + "tor_only": "Tor 뿐" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 25e0e1e7a..59a816602 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -654,7 +654,7 @@ "use_suggested": "Gebruik aanbevolen", "do_not_share_warning_text" : "Deel deze met niemand anders, ook niet met support.\n\nZe zullen je geld stelen!", "help": "helpen", - "disable_fiat": "법정화폐 비활성화", + "fiat_api": "Fiat API", "disable_exchange": "Uitwisseling uitschakelen", "connection_sync": "Verbinding en synchronisatie", "security_and_backup": "Beveiliging en back-up", @@ -662,5 +662,8 @@ "privacy_settings": "Privacy-instellingen", "privacy": "Privacy", "display_settings": "Weergave-instellingen", - "other_settings": "Andere instellingen" + "other_settings": "Andere instellingen", + "disabled": "Gehandicapt", + "enabled": "Ingeschakeld", + "tor_only": "Alleen Tor" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index db3353bad..a2dc5c8fd 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -654,7 +654,7 @@ "use_suggested": "Użyj sugerowane", "do_not_share_warning_text" : "Nie udostępniaj ich nikomu innemu, w tym wsparcia.\n\nUkradną twoje pieniądze!", "help": "pomoc", - "disable_fiat": "Wyłącz fiat", + "fiat_api": "API Fiata", "disable_exchange": "Wyłącz wymianę", "connection_sync": "Połączenie i synchronizacja", "security_and_backup": "Bezpieczeństwo i kopia zapasowa", @@ -662,5 +662,8 @@ "privacy_settings": "Ustawienia prywatności", "privacy": "Prywatność", "display_settings": "Ustawienia wyświetlania", - "other_settings": "Inne ustawienia" + "other_settings": "Inne ustawienia", + "disabled": "Wyłączone", + "enabled": "Włączony", + "tor_only": "Tylko Tor" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 692dd118a..f61ac5e67 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -653,7 +653,7 @@ "use_suggested": "Uso sugerido", "do_not_share_warning_text" : "Não os compartilhe com mais ninguém, incluindo suporte.\n\nEles vão roubar seu dinheiro!", "help": "ajuda", - "disable_fiat": "Desativar fiat", + "fiat_api": "API da Fiat", "disable_exchange": "Desativar troca", "connection_sync": "Conexão e sincronização", "security_and_backup": "Segurança e backup", @@ -661,5 +661,8 @@ "privacy_settings": "Configurações de privacidade", "privacy": "Privacidade", "display_settings": "Configurações de exibição", - "other_settings": "Outras configurações" + "other_settings": "Outras configurações", + "disabled": "Desabilitado", + "enabled": "Habilitado", + "tor_only": "Tor apenas" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index e6c10bd2b..c44e9af35 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -654,7 +654,7 @@ "use_suggested": "Использовать предложенный", "do_not_share_warning_text" : "Не делитесь ими с кем-либо еще, в том числе со службой поддержки.\n\nОни украдут ваши деньги!", "help": "помощь", - "disable_fiat": "Отключить фиат", + "fiat_api": "Фиат API", "disable_exchange": "Отключить обмен", "connection_sync": "Подключение и синхронизация", "security_and_backup": "Безопасность и резервное копирование", @@ -662,5 +662,8 @@ "privacy_settings": "Настройки конфиденциальности", "privacy": "Конфиденциальность", "display_settings": "Настройки отображения", - "other_settings": "Другие настройки" + "other_settings": "Другие настройки", + "disabled": "Отключено", + "enabled": "Включено", + "tor_only": "Только Tor" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 3013dda6a..a766641d7 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -653,7 +653,7 @@ "use_suggested": "Використати запропоноване", "do_not_share_warning_text" : "Не повідомляйте їх нікому, включно зі службою підтримки.\n\nВони вкрадуть ваші гроші!", "help": "допомога", - "disable_fiat": "Вимкнути фиат", + "fiat_api": "Фіат API", "disable_exchange": "Вимкнути exchange", "connection_sync": "Підключення та синхронізація", "security_and_backup": "Безпека та резервне копіювання", @@ -661,6 +661,9 @@ "privacy_settings": "Налаштування конфіденційності", "privacy": "Конфіденційність", "display_settings": "Налаштування дисплея", - "other_settings": "Інші налаштування" + "other_settings": "Інші налаштування", + "disabled": "Вимкнено", + "enabled": "Увімкнено", + "tor_only": "Тільки Tor" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index a82a3ee9d..ae5ffbea5 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -652,7 +652,7 @@ "use_suggested": "使用建议", "do_not_share_warning_text" : "不要與其他任何人分享這些內容,包括支持。\n\n他們會偷你的錢!", "help": "帮助", - "disable_fiat": "禁用法令", + "fiat_api": "法币API", "disable_exchange": "禁用交换", "connection_sync": "连接和同步", "security_and_backup": "安全和备份", @@ -660,5 +660,8 @@ "privacy_settings": "隐私设置", "privacy":"隐私", "display_settings": "显示设置", - "other_settings": "其他设置" + "other_settings": "其他设置", + "disabled": "禁用", + "enabled": "启用", + "tor_only": "仅限 Tor" } From 37ca7957560c6b30efa717bd990152cd2aeda867 Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 7 Dec 2022 15:31:33 +0200 Subject: [PATCH 118/203] [skip ci] change fiat api UI to swich mode --- lib/src/screens/settings/privacy_page.dart | 12 +++++------- .../settings/privacy_settings_view_model.dart | 11 +++++++++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index a0fc280b9..c779eb316 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -24,14 +24,12 @@ class PrivacyPage extends BasePage { return Column( mainAxisSize: MainAxisSize.min, children: [ - SettingsChoicesCell( - ChoicesListItem( + SettingsSwitcherCell( title: S.current.fiat_api, - items: FiatApiMode.all, - selectedItem: _privacySettingsViewModel.fiatApiMode, - onItemSelected: (FiatApiMode mode) => _privacySettingsViewModel.setFiatMode(mode), - ), - ), + value: _privacySettingsViewModel.fiatApiMode, + onValueChange: (BuildContext context, bool value) { + _privacySettingsViewModel.setFiatMode(value); + }), SettingsSwitcherCell( title: S.current.disable_exchange, value: _privacySettingsViewModel.disableExchange, diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index 2d8418d11..b5c58a1b7 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -18,7 +18,7 @@ abstract class PrivacySettingsViewModelBase with Store { bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress; @computed - FiatApiMode get fiatApiMode => _settingsStore.fiatApiMode; + bool get fiatApiMode => _settingsStore.fiatApiMode == FiatApiMode.disabled; @action void setShouldSaveRecipientAddress(bool value) => _settingsStore.shouldSaveRecipientAddress = value; @@ -27,5 +27,12 @@ abstract class PrivacySettingsViewModelBase with Store { void setEnableExchange(bool value) => _settingsStore.disableExchange = value; @action - void setFiatMode(FiatApiMode mode) => _settingsStore.fiatApiMode = mode; + void setFiatMode(bool value) { + if (value) { + _settingsStore.fiatApiMode = FiatApiMode.disabled; + return; + } + _settingsStore.fiatApiMode = FiatApiMode.enabled; + } + } From c235df89353ba0cdc8f1222ebb64f8c73bee6b85 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 7 Dec 2022 16:41:04 +0200 Subject: [PATCH 119/203] - Fix reloading settings store - Revert changes to backup_service.dart --- lib/core/backup_service.dart | 6 +- lib/di.dart | 4 +- lib/store/settings_store.dart | 69 ++++++++----------- .../restore_from_backup_view_model.dart | 5 +- 4 files changed, 31 insertions(+), 53 deletions(-) diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 780185a66..999b67120 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; -import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; @@ -21,7 +20,7 @@ import 'package:cake_backup/backup.dart' as cake_backup; class BackupService { BackupService(this._flutterSecureStorage, this._walletInfoSource, - this._keyService, this._sharedPreferences, this._settingsStore) + this._keyService, this._sharedPreferences) : _cipher = Cryptography.instance.chacha20Poly1305Aead(), _correctWallets = []; @@ -34,7 +33,6 @@ class BackupService { final FlutterSecureStorage _flutterSecureStorage; final SharedPreferences _sharedPreferences; final Box _walletInfoSource; - final SettingsStore _settingsStore; final KeyService _keyService; List _correctWallets; @@ -303,7 +301,6 @@ class BackupService { as Map; final keychainWalletsInfo = keychainJSON['wallets'] as List; final decodedPin = keychainJSON['pin'] as String; - _settingsStore.pinCodeLength = decodedPin.length; final pinCodeKey = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); @@ -334,7 +331,6 @@ class BackupService { final keychainWalletsInfo = keychainJSON['wallets'] as List; final decodedPin = keychainJSON['pin'] as String; final pinCodeKey = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); - _settingsStore.pinCodeLength = decodedPin.length; final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPassword = keychainJSON[backupPasswordKey] as String; diff --git a/lib/di.dart b/lib/di.dart index 2a07919d5..c62dc9790 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -606,9 +606,7 @@ Future setup( getIt.get(), _walletInfoSource, getIt.get(), - getIt.get(), - getIt.get(), - )); + getIt.get())); getIt.registerFactory(() => BackupViewModel(getIt.get(), getIt.get(), getIt.get())); diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 534ea67e9..9fc082ec4 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -3,7 +3,6 @@ import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/themes/theme_list.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; @@ -234,8 +233,7 @@ abstract class SettingsStoreBase with Store { : ThemeType.bright.index; final savedTheme = ThemeList.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? - legacyTheme ?? - 0); + legacyTheme); final actionListDisplayMode = ObservableList(); actionListDisplayMode.addAll(deserializeActionlistDisplayModes( sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? @@ -281,7 +279,7 @@ abstract class SettingsStoreBase with Store { if (havenNode != null) { nodes[WalletType.haven] = havenNode; } - + return SettingsStore( sharedPreferences: sharedPreferences, nodes: nodes, @@ -301,48 +299,35 @@ abstract class SettingsStoreBase with Store { shouldShowYatPopup: shouldShowYatPopup); } - // FIX-ME: Dead code + Future reload( + {required Box nodeSource, + FiatCurrency initialFiatCurrency = FiatCurrency.usd, + TransactionPriority? initialMoneroTransactionPriority, + TransactionPriority? initialBitcoinTransactionPriority, + BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance}) async { + if (initialBitcoinTransactionPriority == null) { + initialBitcoinTransactionPriority = bitcoin?.getMediumTransactionPriority(); + } - //Future reload( - // {required Box nodeSource, - // FiatCurrency initialFiatCurrency = FiatCurrency.usd, - // TransactionPriority? initialMoneroTransactionPriority, - // TransactionPriority? initialBitcoinTransactionPriority, - // BalanceDisplayMode initialBalanceDisplayMode = - // BalanceDisplayMode.availableBalance}) async { - - // if (initialBitcoinTransactionPriority == null) { - // initialBitcoinTransactionPriority = bitcoin?.getMediumTransactionPriority(); - // } + if (initialMoneroTransactionPriority == null) { + initialMoneroTransactionPriority = monero?.getDefaultTransactionPriority(); + } - // if (initialMoneroTransactionPriority == null) { - // initialMoneroTransactionPriority = monero?.getDefaultTransactionPriority(); - // } + final isBitcoinBuyEnabled = (secrets.wyreSecretKey.isNotEmpty) && + (secrets.wyreApiKey.isNotEmpty) && + (secrets.wyreAccountId.isNotEmpty); - // final isBitcoinBuyEnabled = (secrets.wyreSecretKey?.isNotEmpty ?? false) && - // (secrets.wyreApiKey?.isNotEmpty ?? false) && - // (secrets.wyreAccountId?.isNotEmpty ?? false); + final settings = await SettingsStoreBase.load( + nodeSource: nodeSource, + isBitcoinBuyEnabled: isBitcoinBuyEnabled, + initialBalanceDisplayMode: initialBalanceDisplayMode, + initialFiatCurrency: initialFiatCurrency, + initialMoneroTransactionPriority: initialMoneroTransactionPriority, + initialBitcoinTransactionPriority: initialBitcoinTransactionPriority); - // final settings = await SettingsStoreBase.load( - // nodeSource: nodeSource, - // isBitcoinBuyEnabled: isBitcoinBuyEnabled, - // initialBalanceDisplayMode: initialBalanceDisplayMode, - // initialFiatCurrency: initialFiatCurrency, - // initialMoneroTransactionPriority: initialMoneroTransactionPriority, - // initialBitcoinTransactionPriority: initialBitcoinTransactionPriority); - // fiatCurrency = settings.fiatCurrency; - // actionlistDisplayMode = settings.actionlistDisplayMode; - // priority[WalletType.monero] = initialMoneroTransactionPriority; - // priority[WalletType.bitcoin] = initialBitcoinTransactionPriority; - // balanceDisplayMode = settings.balanceDisplayMode; - // shouldSaveRecipientAddress = settings.shouldSaveRecipientAddress; - // allowBiometricalAuthentication = settings.allowBiometricalAuthentication; - // currentTheme = settings.currentTheme; - // pinCodeLength = settings.pinCodeLength; - // languageCode = settings.languageCode; - // appVersion = settings.appVersion; - // shouldShowYatPopup = settings.shouldShowYatPopup; - //} + getIt.unregister(); + getIt.registerSingleton(settings); + } Future _saveCurrentNode(Node node, WalletType walletType) async { switch (walletType) { diff --git a/lib/view_model/restore_from_backup_view_model.dart b/lib/view_model/restore_from_backup_view_model.dart index d3542a668..403ae3ff1 100644 --- a/lib/view_model/restore_from_backup_view_model.dart +++ b/lib/view_model/restore_from_backup_view_model.dart @@ -35,7 +35,7 @@ abstract class RestoreFromBackupViewModelBase with Store { try { state = IsExecutingState(); - if (filePath?.isEmpty ?? true) { + if (filePath.isEmpty) { state = FailureState('Backup file is not selected.'); return; } @@ -48,8 +48,7 @@ abstract class RestoreFromBackupViewModelBase with Store { final store = getIt.get(); ReactionDisposer? reaction; - // FIX-ME: SettingsStore reload - // await store.settingsStore.reload(nodeSource: getIt.get>()); + await store.settingsStore.reload(nodeSource: getIt.get>()); reaction = autorun((_) { final wallet = store.wallet; From 8b333f2925ebb6105cc299deb93ad50ccba9af7e Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 7 Dec 2022 17:14:27 +0200 Subject: [PATCH 120/203] - Add disable exchange to the export/import flow - Save changes to Disable Exchange --- lib/core/backup_service.dart | 7 +++++++ lib/store/settings_store.dart | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 999b67120..2c680db1b 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -216,6 +216,7 @@ class BackupService { final displayActionListMode = data[PreferencesKey.displayActionListModeKey] as int?; final currentPinLength = data[PreferencesKey.currentPinLength] as int?; final currentTheme = data[PreferencesKey.currentTheme] as int?; + final disableExchange = data[PreferencesKey.disableExchangeKey] as bool?; final currentDefaultSettingsMigrationVersion = data[PreferencesKey.currentDefaultSettingsMigrationVersion] as int?; final moneroTransactionPriority = data[PreferencesKey.moneroTransactionPriority] as int?; final bitcoinTransactionPriority = data[PreferencesKey.bitcoinTransactionPriority] as int?; @@ -274,6 +275,10 @@ class BackupService { await _sharedPreferences.setInt( PreferencesKey.currentTheme, currentTheme); + if (disableExchange != null) + await _sharedPreferences.setBool( + PreferencesKey.disableExchangeKey, disableExchange); + if (currentDefaultSettingsMigrationVersion != null) await _sharedPreferences.setInt( PreferencesKey.currentDefaultSettingsMigrationVersion, @@ -421,6 +426,8 @@ class BackupService { _sharedPreferences.getInt(PreferencesKey.displayActionListModeKey), PreferencesKey.currentTheme: _sharedPreferences.getInt(PreferencesKey.currentTheme), + PreferencesKey.disableExchangeKey: + _sharedPreferences.getBool(PreferencesKey.disableExchangeKey), PreferencesKey.currentDefaultSettingsMigrationVersion: _sharedPreferences .getInt(PreferencesKey.currentDefaultSettingsMigrationVersion), PreferencesKey.bitcoinTransactionPriority: diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 9fc082ec4..ecc5baf8a 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -114,6 +114,11 @@ abstract class SettingsStoreBase with Store { (BalanceDisplayMode mode) => sharedPreferences.setInt( PreferencesKey.currentBalanceDisplayModeKey, mode.serialize())); + reaction( + (_) => disableExchange, + (bool disableExchange) => sharedPreferences.setBool( + PreferencesKey.disableExchangeKey, disableExchange)); + this .nodes .observe((change) { From 8ff8cf38b87a577df232b231a4b84ea7f7cd2cb0 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 7 Dec 2022 18:15:30 +0200 Subject: [PATCH 121/203] Check if the provider supportsFixedRate only if fixed rate is applied [skip ci] --- lib/view_model/exchange/exchange_view_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 49ee9ea95..510e0ac3a 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -310,7 +310,7 @@ abstract class ExchangeViewModelBase with Store { final result = await Future.wait( _tradeAvailableProviders - .where((element) => element.supportsFixedRate) + .where((element) => !isFixedRateMode || element.supportsFixedRate) .map((element) => element.calculateAmount( from: depositCurrency, to: receiveCurrency, From 0203f686c555581308c6bf25c05622606782d56f Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 7 Dec 2022 18:12:45 +0100 Subject: [PATCH 122/203] fix issue with custom redeem amount remaining --- lib/di.dart | 3 +- .../ionia/cards/ionia_custom_redeem_page.dart | 69 ++++++++++-------- .../cards/ionia_gift_card_detail_page.dart | 70 +++++++++---------- .../ionia/cards/ionia_more_options_page.dart | 67 ++++++++++-------- .../ionia/ionia_custom_redeem_view_model.dart | 36 ++++++++-- .../ionia_gift_card_details_view_model.dart | 33 ++++----- 6 files changed, 156 insertions(+), 122 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index 90549cf6f..910feae4a 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -760,7 +760,8 @@ Future setup( return IoniaMoreOptionsPage(giftCard); }); - getIt.registerFactoryParam((IoniaGiftCard giftCard, _) => IoniaCustomRedeemViewModel(giftCard)); + getIt.registerFactoryParam((IoniaGiftCard giftCard, _) + => IoniaCustomRedeemViewModel(giftCard: giftCard, ioniaService: getIt.get())); getIt.registerFactoryParam((List args, _){ final giftCard = args.first as IoniaGiftCard; diff --git a/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart b/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart index f9ce0ae88..f2702d791 100644 --- a/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart +++ b/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/card_item.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; @@ -18,12 +19,11 @@ class IoniaCustomRedeemPage extends BasePage { ) : _amountFieldFocus = FocusNode(), _amountController = TextEditingController() { _amountController.addListener(() { - ioniaCustomRedeemViewModel.updateAmount(_amountController.text); + ioniaCustomRedeemViewModel.updateAmount(_amountController.text); }); } final IoniaCustomRedeemViewModel ioniaCustomRedeemViewModel; - @override String get title => S.current.custom_redeem_amount; @@ -50,7 +50,7 @@ class IoniaCustomRedeemPage extends BasePage { disableScroll: true, config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context).accentTextTheme!.bodyText1!.backgroundColor!, + keyboardBarColor: Theme.of(context).accentTextTheme.bodyText1!.backgroundColor!, nextFocus: false, actions: [ KeyboardActionsItem( @@ -67,10 +67,11 @@ class IoniaCustomRedeemPage extends BasePage { Container( padding: EdgeInsets.symmetric(horizontal: 25), decoration: BoxDecoration( - borderRadius: BorderRadius.only(bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), gradient: LinearGradient(colors: [ - Theme.of(context).primaryTextTheme!.subtitle1!.color!, - Theme.of(context).primaryTextTheme!.subtitle1!.decorationColor!, + Theme.of(context).primaryTextTheme.subtitle1!.color!, + Theme.of(context).primaryTextTheme.subtitle1!.decorationColor!, ], begin: Alignment.topLeft, end: Alignment.bottomRight), ), child: Column( @@ -85,11 +86,11 @@ class IoniaCustomRedeemPage extends BasePage { inputFormatters: [FilteringTextInputFormatter.deny(RegExp('[\-|\ ]'))], hintText: '1000', placeholderTextStyle: TextStyle( - color: Theme.of(context).primaryTextTheme!.headline5!.color!, + color: Theme.of(context).primaryTextTheme.headline5!.color!, fontWeight: FontWeight.w500, fontSize: 36, ), - borderColor: Theme.of(context).primaryTextTheme!.headline5!.color!, + borderColor: Theme.of(context).primaryTextTheme.headline5!.color!, textColor: Colors.white, textStyle: TextStyle( color: Colors.white, @@ -114,14 +115,17 @@ class IoniaCustomRedeemPage extends BasePage { ), ), SizedBox(height: 8), - Observer(builder: (_)=> - !ioniaCustomRedeemViewModel.disableRedeem ? - Center( - child: Text('\$${giftCard.remainingAmount} - \$${ioniaCustomRedeemViewModel.amount} = \$${ioniaCustomRedeemViewModel.formattedRemaining} ${S.of(context).remaining}', - style: TextStyle( - color: Theme.of(context).primaryTextTheme!.headline5!.color!, - ),), - ) : SizedBox.shrink(), + Observer( + builder: (_) => !ioniaCustomRedeemViewModel.disableRedeem + ? Center( + child: Text( + '\$${giftCard.remainingAmount} - \$${ioniaCustomRedeemViewModel.amount} = \$${ioniaCustomRedeemViewModel.formattedRemaining} ${S.of(context).remaining}', + style: TextStyle( + color: Theme.of(context).primaryTextTheme.headline5!.color!, + ), + ), + ) + : SizedBox.shrink(), ), SizedBox(height: 24), ], @@ -131,30 +135,37 @@ class IoniaCustomRedeemPage extends BasePage { padding: const EdgeInsets.all(24.0), child: CardItem( title: giftCard.legalName, - backgroundColor: Theme.of(context).accentTextTheme!.headline1!.backgroundColor!.withOpacity(0.1), + backgroundColor: Theme.of(context) + .accentTextTheme + .headline1! + .backgroundColor! + .withOpacity(0.1), discount: giftCard.remainingAmount, isAmount: true, discountBackground: AssetImage('assets/images/red_badge_discount.png'), - titleColor: Theme.of(context).accentTextTheme!.headline1!.backgroundColor!, + titleColor: Theme.of(context).accentTextTheme.headline1!.backgroundColor!, subtitleColor: Theme.of(context).hintColor, subTitle: S.of(context).online, logoUrl: giftCard.logoUrl, ), - ), + ), ], ), bottomSection: Column( children: [ - Padding( - padding: EdgeInsets.only(bottom: 12), - child: PrimaryButton( - onPressed: () { - Navigator.of(context).pop([ioniaCustomRedeemViewModel.remaining.toString(), ioniaCustomRedeemViewModel.amount.toString()]); - }, - isDisabled: ioniaCustomRedeemViewModel.disableRedeem, - text: S.of(context).add_custom_redemption, - color: Theme.of(context).accentTextTheme!.bodyText1!.color!, - textColor: Colors.white, + Observer( + builder: (_) => Padding( + padding: EdgeInsets.only(bottom: 12), + child: LoadingPrimaryButton( + isLoading: ioniaCustomRedeemViewModel.redeemState is IsExecutingState, + isDisabled: ioniaCustomRedeemViewModel.disableRedeem, + text: S.of(context).add_custom_redemption, + color: Theme.of(context).accentTextTheme.bodyText1!.color!, + textColor: Colors.white, + onPressed: () => ioniaCustomRedeemViewModel.addCustomRedeem().then((value) { + Navigator.of(context).pop(ioniaCustomRedeemViewModel.remaining.toString()); + }), + ), ), ), SizedBox(height: 30), diff --git a/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart b/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart index 2e7162e40..5b3c980ec 100644 --- a/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart +++ b/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart @@ -32,7 +32,7 @@ class IoniaGiftCardDetailPage extends BasePage { final _backButton = Icon( Icons.arrow_back_ios, - color: Theme.of(context).primaryTextTheme!.headline6!.color!, + color: Theme.of(context).primaryTextTheme.headline6!.color!, size: 16, ); return Padding( @@ -43,7 +43,7 @@ class IoniaGiftCardDetailPage extends BasePage { child: ButtonTheme( minWidth: double.minPositive, child: TextButton( - // FIX-ME: Style + // FIX-ME: Style //highlightColor: Colors.transparent, //splashColor: Colors.transparent, //padding: EdgeInsets.all(0), @@ -61,7 +61,8 @@ class IoniaGiftCardDetailPage extends BasePage { Widget middle(BuildContext context) { return Text( viewModel.giftCard.legalName, - style: textMediumSemiBold(color: Theme.of(context).accentTextTheme!.headline1!.backgroundColor!), + style: + textMediumSemiBold(color: Theme.of(context).accentTextTheme.headline1!.backgroundColor!), ); } @@ -102,20 +103,21 @@ class IoniaGiftCardDetailPage extends BasePage { title: S.of(context).gift_card_number, subTitle: viewModel.giftCard.cardNumber, ), - if (viewModel.giftCard.cardPin?.isNotEmpty ?? false) - ...[Divider(height: 30), + if (viewModel.giftCard.cardPin.isNotEmpty) ...[ + Divider(height: 30), buildIoniaTile( context, title: S.of(context).pin_number, subTitle: viewModel.giftCard.cardPin, - )], + ) + ], Divider(height: 30), - Observer(builder: (_) => - buildIoniaTile( - context, - title: S.of(context).amount, - subTitle: viewModel.remainingAmount.toStringAsFixed(2) ?? '0.00', - )), + Observer( + builder: (_) => buildIoniaTile( + context, + title: S.of(context).amount, + subTitle: viewModel.remainingAmount.toStringAsFixed(2), + )), Divider(height: 50), TextIconButton( label: S.of(context).how_to_use_card, @@ -131,24 +133,23 @@ class IoniaGiftCardDetailPage extends BasePage { return Column( children: [ PrimaryButton( - onPressed: () async { - final amount = await Navigator.of(context) - .pushNamed(Routes.ioniaMoreOptionsPage, arguments: [viewModel.giftCard]) as List?; - if (amount != null) { - viewModel.updateRemaining( balance: double.parse(amount.first), customAmount: double.parse(amount.last)); - } - }, - text: S.of(context).more_options, - color: Theme.of(context).accentTextTheme.caption!.color!, - textColor: Theme.of(context).primaryTextTheme.headline6!.color!, + onPressed: () async { + await Navigator.of(context).pushNamed( + Routes.ioniaMoreOptionsPage, + arguments: [viewModel.giftCard]) as String?; + viewModel.refeshCard(); + }, + text: S.of(context).more_options, + color: Theme.of(context).accentTextTheme.caption!.color!, + textColor: Theme.of(context).primaryTextTheme.headline6!.color!, ), SizedBox(height: 12), LoadingPrimaryButton( isLoading: viewModel.redeemState is IsExecutingState, onPressed: () => viewModel.redeem().then( (_) { - Navigator.of(context) - .pushNamedAndRemoveUntil(Routes.ioniaManageCardsPage, (route) => route.isFirst); + Navigator.of(context).pushNamedAndRemoveUntil( + Routes.ioniaManageCardsPage, (route) => route.isFirst); }, ), text: S.of(context).mark_as_redeemed, @@ -168,12 +169,11 @@ class IoniaGiftCardDetailPage extends BasePage { Widget buildIoniaTile(BuildContext context, {required String title, required String subTitle}) { return IoniaTile( - title: title, - subTitle: subTitle, - onTap: () { - Clipboard.setData(ClipboardData(text: subTitle)); - showBar(context, - S.of(context).transaction_details_copied(title)); + title: title, + subTitle: subTitle, + onTap: () { + Clipboard.setData(ClipboardData(text: subTitle)); + showBar(context, S.of(context).transaction_details_copied(title)); }); } @@ -184,10 +184,10 @@ class IoniaGiftCardDetailPage extends BasePage { showPopUp( context: context, builder: (BuildContext context) { - return IoniaAlertModal( + return IoniaAlertModal( title: S.of(context).how_to_use_card, content: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: viewModel.giftCard.instructions .map((instruction) { return [ @@ -196,13 +196,13 @@ class IoniaGiftCardDetailPage extends BasePage { child: Text( instruction.header, style: textLargeSemiBold( - color: Theme.of(context).textTheme!.headline3!.color!, + color: Theme.of(context).textTheme.headline3!.color!, ), )), Text( instruction.body, style: textMedium( - color: Theme.of(context).textTheme!.headline3!.color!, + color: Theme.of(context).textTheme.headline3!.color!, ), ) ]; @@ -210,7 +210,7 @@ class IoniaGiftCardDetailPage extends BasePage { .expand((e) => e) .toList()), actionTitle: S.of(context).send_got_it, - ); + ); }); } } diff --git a/lib/src/screens/ionia/cards/ionia_more_options_page.dart b/lib/src/screens/ionia/cards/ionia_more_options_page.dart index d4e378f84..facdfaf32 100644 --- a/lib/src/screens/ionia/cards/ionia_more_options_page.dart +++ b/lib/src/screens/ionia/cards/ionia_more_options_page.dart @@ -5,7 +5,6 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/typography.dart'; import 'package:flutter/material.dart'; - class IoniaMoreOptionsPage extends BasePage { IoniaMoreOptionsPage(this.giftCard); @@ -16,7 +15,7 @@ class IoniaMoreOptionsPage extends BasePage { return Text( S.current.more_options, style: textMediumSemiBold( - color: Theme.of(context).accentTextTheme!.headline1!.backgroundColor!, + color: Theme.of(context).accentTextTheme.headline1!.backgroundColor!, ), ); } @@ -27,40 +26,46 @@ class IoniaMoreOptionsPage extends BasePage { padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - SizedBox(height: 10,), - Center(child: Text(S.of(context).choose_from_available_options, style: textMedium( - color: Theme.of(context).primaryTextTheme!.headline6!.color!, - ),)), - SizedBox(height: 40,), - InkWell( - onTap: () async { - final amounts = await Navigator.of(context).pushNamed(Routes.ioniaCustomRedeemPage, arguments: [giftCard]) as List; - if(amounts.first.isNotEmpty){ - Navigator.pop(context, amounts); - } - }, - child: _GradiantContainer( - content: Padding( - padding: const EdgeInsets.only(top: 24, left: 20, right: 24, bottom: 50), - child: Text( - S.of(context).custom_redeem_amount, - style: textXLargeSemiBold(), - ), - ), - ), - ) - ], - ), + children: [ + SizedBox( + height: 10, + ), + Center( + child: Text( + S.of(context).choose_from_available_options, + style: textMedium( + color: Theme.of(context).primaryTextTheme.headline6!.color!, + ), + )), + SizedBox( + height: 40, + ), + InkWell( + onTap: () async { + final amount = await Navigator.of(context) + .pushNamed(Routes.ioniaCustomRedeemPage, arguments: [giftCard]) as String?; + if (amount != null && amount.isNotEmpty) { + Navigator.pop(context); + } + }, + child: _GradiantContainer( + content: Padding( + padding: const EdgeInsets.only(top: 24, left: 20, right: 24, bottom: 50), + child: Text( + S.of(context).custom_redeem_amount, + style: textXLargeSemiBold(), + ), + ), + ), + ) + ], + ), ); } } class _GradiantContainer extends StatelessWidget { - const _GradiantContainer({ - Key? key, - required this.content - }) : super(key: key); + const _GradiantContainer({Key? key, required this.content}) : super(key: key); final Widget content; diff --git a/lib/view_model/ionia/ionia_custom_redeem_view_model.dart b/lib/view_model/ionia/ionia_custom_redeem_view_model.dart index 963604c15..6471c7378 100644 --- a/lib/view_model/ionia/ionia_custom_redeem_view_model.dart +++ b/lib/view_model/ionia/ionia_custom_redeem_view_model.dart @@ -1,29 +1,51 @@ +import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; +import 'package:cake_wallet/ionia/ionia_service.dart'; import 'package:mobx/mobx.dart'; part 'ionia_custom_redeem_view_model.g.dart'; + class IoniaCustomRedeemViewModel = IoniaCustomRedeemViewModelBase with _$IoniaCustomRedeemViewModel; abstract class IoniaCustomRedeemViewModelBase with Store { - IoniaCustomRedeemViewModelBase(this.giftCard) - : amount = 0; + IoniaCustomRedeemViewModelBase({ + required this.giftCard, + required this.ioniaService, + }) : amount = 0, + redeemState = InitialExecutionState(); final IoniaGiftCard giftCard; + final IoniaService ioniaService; + + @observable + ExecutionState redeemState; + @observable double amount; @computed - double get remaining => amount <= giftCard.remainingAmount ? giftCard.remainingAmount - amount : 0; + double get remaining => + amount <= giftCard.remainingAmount ? giftCard.remainingAmount - amount : 0; @computed - String get formattedRemaining => remaining.toStringAsFixed(2); + String get formattedRemaining => remaining.toStringAsFixed(2); @computed bool get disableRedeem => amount > giftCard.remainingAmount; @action - void updateAmount(String text){ - amount = text.isEmpty ? 0 : (double.parse(text.replaceAll(',', '.')) ?? 0); + void updateAmount(String text) { + amount = text.isEmpty ? 0 : (double.parse(text.replaceAll(',', '.'))); } -} \ No newline at end of file + @action + Future addCustomRedeem() async { + try { + redeemState = IsExecutingState(); + await ioniaService.redeem(giftCardId: giftCard.id, amount: amount); + redeemState = ExecutedSuccessfullyState(); + } catch (e) { + redeemState = FailureState(e.toString()); + } + } +} diff --git a/lib/view_model/ionia/ionia_gift_card_details_view_model.dart b/lib/view_model/ionia/ionia_gift_card_details_view_model.dart index 745f2d530..cbf5ebc78 100644 --- a/lib/view_model/ionia/ionia_gift_card_details_view_model.dart +++ b/lib/view_model/ionia/ionia_gift_card_details_view_model.dart @@ -6,30 +6,25 @@ import 'package:device_display_brightness/device_display_brightness.dart'; part 'ionia_gift_card_details_view_model.g.dart'; -class IoniaGiftCardDetailsViewModel = IoniaGiftCardDetailsViewModelBase with _$IoniaGiftCardDetailsViewModel; +class IoniaGiftCardDetailsViewModel = IoniaGiftCardDetailsViewModelBase + with _$IoniaGiftCardDetailsViewModel; abstract class IoniaGiftCardDetailsViewModelBase with Store { - - IoniaGiftCardDetailsViewModelBase({ - required this.ioniaService, - required this.giftCard}) - : redeemState = InitialExecutionState(), - remainingAmount = giftCard.remainingAmount, - adjustedAmount = 0, - brightness = 0; + IoniaGiftCardDetailsViewModelBase({required this.ioniaService, required this.giftCard}) + : redeemState = InitialExecutionState(), + remainingAmount = giftCard.remainingAmount, + brightness = 0; final IoniaService ioniaService; - + double brightness; - + @observable IoniaGiftCard giftCard; @observable double remainingAmount; - double adjustedAmount; - @observable ExecutionState redeemState; @@ -38,22 +33,22 @@ abstract class IoniaGiftCardDetailsViewModelBase with Store { giftCard.remainingAmount = remainingAmount; try { redeemState = IsExecutingState(); - await ioniaService.redeem(giftCardId: giftCard.id, amount : adjustedAmount > 0 ? adjustedAmount : giftCard.remainingAmount); + await ioniaService.redeem(giftCardId: giftCard.id, amount: giftCard.remainingAmount); giftCard = await ioniaService.getGiftCard(id: giftCard.id); redeemState = ExecutedSuccessfullyState(); - } catch(e) { + } catch (e) { redeemState = FailureState(e.toString()); } } @action - void updateRemaining({required double balance, required double customAmount}) { - remainingAmount = balance; - adjustedAmount = customAmount; + Future refeshCard() async { + giftCard = await ioniaService.getGiftCard(id: giftCard.id); + remainingAmount = giftCard.remainingAmount; } void increaseBrightness() async { brightness = await DeviceDisplayBrightness.getBrightness(); await DeviceDisplayBrightness.setBrightness(1.0); } -} \ No newline at end of file +} From 0da48f66fef74b94270ef77767c64182dbb4f08e Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 7 Dec 2022 21:09:15 +0200 Subject: [PATCH 123/203] Delegate returning rate to each provider to handle its logic internally --- .../changenow/changenow_exchange_provider.dart | 14 +++++++------- .../sideshift/sideshift_exchange_provider.dart | 4 +--- .../simpleswap/simpleswap_exchange_provider.dart | 2 +- lib/view_model/exchange/exchange_view_model.dart | 4 ++-- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/exchange/changenow/changenow_exchange_provider.dart b/lib/exchange/changenow/changenow_exchange_provider.dart index 8ef376370..ca245923f 100644 --- a/lib/exchange/changenow/changenow_exchange_provider.dart +++ b/lib/exchange/changenow/changenow_exchange_provider.dart @@ -113,8 +113,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider { // since we schedule to calculate the rate every 5 seconds we need to ensure that // we have the latest rate id with the given inputs before creating the trade await calculateAmount( - from: _request.to, - to: _request.from, + from: _request.from, + to: _request.to, amount: double.tryParse(_request.toAmount) ?? 0, isFixedRateMode: true, isReceiveAmount: true, @@ -222,10 +222,10 @@ class ChangeNowExchangeProvider extends ExchangeProvider { final type = isReverse ? 'reverse' : 'direct'; final flow = getFlow(isFixedRateMode); final params = { - 'fromCurrency': isReverse ? normalizeCryptoCurrency(to) : normalizeCryptoCurrency(from), - 'toCurrency': isReverse ? normalizeCryptoCurrency(from) : normalizeCryptoCurrency(to), - 'fromNetwork': isReverse ? networkFor(to) : networkFor(from), - 'toNetwork': isReverse ? networkFor(from) : networkFor(to), + 'fromCurrency': normalizeCryptoCurrency(from), + 'toCurrency': normalizeCryptoCurrency(to), + 'fromNetwork': networkFor(from), + 'toNetwork': networkFor(to), 'type': type, 'flow': flow}; @@ -246,7 +246,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { _lastUsedRateId = rateId; } - return isReverse ? fromAmount : toAmount; + return isReverse ? (amount / fromAmount) : (toAmount / amount); } catch(e) { print(e.toString()); return 0.0; diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/sideshift/sideshift_exchange_provider.dart index b93f0a80f..912ad89c5 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/sideshift/sideshift_exchange_provider.dart @@ -79,9 +79,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { if (amount > max) return 0.00; - final estimatedAmount = rate * amount; - - return estimatedAmount; + return rate; } catch (_) { return 0.00; } diff --git a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart b/lib/exchange/simpleswap/simpleswap_exchange_provider.dart index 4c42835ed..0c1027000 100644 --- a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart +++ b/lib/exchange/simpleswap/simpleswap_exchange_provider.dart @@ -60,7 +60,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { if (response.body == "null") return 0.00; final data = json.decode(response.body) as String; - return double.parse(data); + return double.parse(data) / amount; } catch (_) { return 0.00; } diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 510e0ac3a..80551304f 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -316,7 +316,7 @@ abstract class ExchangeViewModelBase with Store { to: receiveCurrency, amount: amount, isFixedRateMode: isFixedRateMode, - isReceiveAmount: false)) + isReceiveAmount: isFixedRateMode)) ); _sortedAvailableProviders.clear(); @@ -324,7 +324,7 @@ abstract class ExchangeViewModelBase with Store { for (int i=0;i Date: Wed, 7 Dec 2022 22:07:32 +0200 Subject: [PATCH 124/203] - Make getters to ease attribute access - Add the old 'disable_fiat' translation - rename getters to be more bool like names --- lib/entities/default_settings_migration.dart | 17 ----------------- .../dashboard/widgets/transactions_page.dart | 2 +- .../exchange_trade/exchange_trade_page.dart | 5 +---- lib/src/screens/send/widgets/send_card.dart | 6 +++--- lib/src/screens/settings/privacy_page.dart | 7 ++----- lib/store/settings_store.dart | 2 +- .../dashboard/balance_view_model.dart | 10 +++++----- .../exchange/exchange_trade_view_model.dart | 4 ++-- lib/view_model/send/send_view_model.dart | 7 +++++-- .../settings/privacy_settings_view_model.dart | 2 +- res/values/strings_de.arb | 3 ++- res/values/strings_en.arb | 3 ++- res/values/strings_es.arb | 3 ++- res/values/strings_fr.arb | 3 ++- res/values/strings_hi.arb | 3 ++- res/values/strings_hr.arb | 3 ++- res/values/strings_it.arb | 3 ++- res/values/strings_ja.arb | 3 ++- res/values/strings_ko.arb | 3 ++- res/values/strings_nl.arb | 3 ++- res/values/strings_pl.arb | 3 ++- res/values/strings_pt.arb | 3 ++- res/values/strings_ru.arb | 3 ++- res/values/strings_uk.arb | 3 ++- res/values/strings_zh.arb | 3 ++- 25 files changed, 51 insertions(+), 56 deletions(-) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index d65b4401d..9aff05500 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -20,8 +20,6 @@ import 'package:cake_wallet/exchange/trade.dart'; import 'package:encrypt/encrypt.dart' as encrypt; import 'package:collection/collection.dart'; -import 'fiat_api_mode.dart'; - const newCakeWalletMoneroUri = 'xmr-node.cakewallet.com:18081'; const cakeWalletBitcoinElectrumUri = 'electrum.cakewallet.com:50002'; const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002'; @@ -63,9 +61,6 @@ Future defaultSettingsMigration( await sharedPreferences.setInt( PreferencesKey.currentBalanceDisplayModeKey, BalanceDisplayMode.availableBalance.raw); - await sharedPreferences.setInt( - PreferencesKey.currentFiatApiModeKey, - FiatApiMode.enabled.raw); await sharedPreferences.setBool('save_recipient_address', true); await resetToDefault(nodes); await changeMoneroCurrentNodeToDefault( @@ -144,10 +139,6 @@ Future defaultSettingsMigration( await addOnionNode(nodes); break; - case 19: - await updateFiatApiModes(sharedPreferences); - break; - default: break; } @@ -358,14 +349,6 @@ Future updateDisplayModes(SharedPreferences sharedPreferences) async { PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode); } -Future updateFiatApiModes(SharedPreferences sharedPreferences) async { - final currentFiatApiMode = - sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? -1; - final fiatApiMode = currentFiatApiMode < 1 ? 2 : 1; - await sharedPreferences.setInt( - PreferencesKey.currentFiatApiModeKey, fiatApiMode); -} - Future generateBackupPassword(FlutterSecureStorage secureStorage) async { final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword); diff --git a/lib/src/screens/dashboard/widgets/transactions_page.dart b/lib/src/screens/dashboard/widgets/transactions_page.dart index 9e09bae8c..64f02c73c 100644 --- a/lib/src/screens/dashboard/widgets/transactions_page.dart +++ b/lib/src/screens/dashboard/widgets/transactions_page.dart @@ -58,7 +58,7 @@ class TransactionsPage extends StatelessWidget { .format(transaction.date), formattedAmount: item.formattedCryptoAmount, formattedFiatAmount: - dashboardViewModel.balanceViewModel.disableFiat + dashboardViewModel.balanceViewModel.isFiatDisabled ? '' : item.formattedFiatAmount, isPending: transaction.isPending)); } diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index 001c13ba9..7c9fc1be7 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -74,12 +74,9 @@ class ExchangeTradePage extends BasePage { } class ExchangeTradeForm extends StatefulWidget { - ExchangeTradeForm(this.exchangeTradeViewModel) - : disableFiat = - exchangeTradeViewModel.sendViewModel.balanceViewModel.disableFiat; + ExchangeTradeForm(this.exchangeTradeViewModel); final ExchangeTradeViewModel exchangeTradeViewModel; - final bool disableFiat; @override ExchangeTradeState createState() => ExchangeTradeState(); diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 503494c92..261f5dde5 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -331,8 +331,8 @@ class SendCardState extends State ], ), )), - if (!sendViewModel.balanceViewModel.disableFiat) - Padding( + if (!sendViewModel.isFiatDisabled) + Padding( padding: const EdgeInsets.only(top: 20), child: BaseTextFormField( focusNode: fiatAmountFocus, @@ -438,7 +438,7 @@ class SendCardState extends State Padding( padding: EdgeInsets.only(top: 5), - child: sendViewModel.balanceViewModel.disableFiat + child: sendViewModel.isFiatDisabled ? const SizedBox(height: 14) : Text(output .estimatedFeeFiatAmount diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index c779eb316..2f15cc225 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -1,12 +1,9 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; -import 'package:cake_wallet/entities/fiat_api_mode.dart'; class PrivacyPage extends BasePage { PrivacyPage(this._privacySettingsViewModel); @@ -25,8 +22,8 @@ class PrivacyPage extends BasePage { mainAxisSize: MainAxisSize.min, children: [ SettingsSwitcherCell( - title: S.current.fiat_api, - value: _privacySettingsViewModel.fiatApiMode, + title: S.current.disable_fiat, + value: _privacySettingsViewModel.isFiatDisabled, onValueChange: (BuildContext context, bool value) { _privacySettingsViewModel.setFiatMode(value); }), diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 419b03e49..237846495 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -237,7 +237,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? false; final currentFiatApiMode = FiatApiMode.deserialize( raw: sharedPreferences - .getInt(PreferencesKey.currentFiatApiModeKey)!); + .getInt(PreferencesKey.currentFiatApiModeKey) ?? FiatApiMode.enabled.raw); final allowBiometricalAuthentication = sharedPreferences .getBool(PreferencesKey.allowBiometricalAuthenticationKey) ?? false; diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index 6728859da..33fe01ba9 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -72,7 +72,7 @@ abstract class BalanceViewModelBase with Store { BalanceDisplayMode get savedDisplayMode => settingsStore.balanceDisplayMode; @computed - bool get disableFiat => settingsStore.fiatApiMode == FiatApiMode.disabled; + bool get isFiatDisabled => settingsStore.fiatApiMode == FiatApiMode.disabled; @computed String get asset { @@ -183,8 +183,8 @@ abstract class BalanceViewModelBase with Store { return MapEntry(key, BalanceRecord( availableBalance: '---', additionalBalance: '---', - fiatAdditionalBalance: disableFiat ? '' : '---', - fiatAvailableBalance: disableFiat ? '' : '---', + fiatAdditionalBalance: isFiatDisabled ? '' : '---', + fiatAvailableBalance: isFiatDisabled ? '' : '---', asset: key, formattedAssetTitle: _formatterAsset(key))); } @@ -195,13 +195,13 @@ abstract class BalanceViewModelBase with Store { // throw Exception('Price is null for: $key'); // } - final additionalFiatBalance = disableFiat ? '' : (fiatCurrency.toString() + final additionalFiatBalance = isFiatDisabled ? '' : (fiatCurrency.toString() + ' ' + _getFiatBalance( price: price, cryptoAmount: value.formattedAdditionalBalance)); - final availableFiatBalance = disableFiat ? '' : (fiatCurrency.toString() + final availableFiatBalance = isFiatDisabled ? '' : (fiatCurrency.toString() + ' ' + _getFiatBalance( price: price, diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index 133b4a228..10ddf25e4 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -74,13 +74,13 @@ abstract class ExchangeTradeViewModelBase with Store { @computed String get pendingTransactionFiatAmountValueFormatted => - sendViewModel.balanceViewModel.disableFiat + sendViewModel.isFiatDisabled ? '' : sendViewModel.pendingTransactionFiatAmount + ' ' + sendViewModel.fiat.title; @computed String get pendingTransactionFeeFiatAmountFormatted => - sendViewModel.balanceViewModel.disableFiat + sendViewModel.isFiatDisabled ? '' : sendViewModel.pendingTransactionFeeFiatAmount + ' ' + sendViewModel.fiat.title; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 096f4e9f0..fd783cf6f 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -142,14 +142,17 @@ abstract class SendViewModelBase with Store { @computed String get balance => balanceViewModel.availableBalance; + @computed + bool get isFiatDisabled => balanceViewModel.isFiatDisabled; + @computed String get pendingTransactionFiatAmountFormatted => - balanceViewModel.disableFiat ? '' : pendingTransactionFiatAmount + + isFiatDisabled ? '' : pendingTransactionFiatAmount + ' ' + fiat.title; @computed String get pendingTransactionFeeFiatAmountFormatted => - balanceViewModel.disableFiat ? '' : pendingTransactionFeeFiatAmount + + isFiatDisabled ? '' : pendingTransactionFeeFiatAmount + ' ' + fiat.title; @computed diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index b5c58a1b7..f8c3e5b50 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -18,7 +18,7 @@ abstract class PrivacySettingsViewModelBase with Store { bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress; @computed - bool get fiatApiMode => _settingsStore.fiatApiMode == FiatApiMode.disabled; + bool get isFiatDisabled => _settingsStore.fiatApiMode == FiatApiMode.disabled; @action void setShouldSaveRecipientAddress(bool value) => _settingsStore.shouldSaveRecipientAddress = value; diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index ecbd3838e..915e43e5d 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -654,7 +654,6 @@ "use_suggested": "Vorgeschlagen verwenden", "do_not_share_warning_text" : "Teilen Sie diese nicht mit anderen, einschließlich des Supports.\n\nSie werden Ihr Geld stehlen!", "help": "hilfe", - "fiat_api": "Fiat API", "disable_exchange": "Exchange deaktivieren", "connection_sync": "Verbindung und Synchronisierung", "security_and_backup": "Sicherheit und Datensicherung", @@ -663,6 +662,8 @@ "privacy": "Datenschutz", "display_settings": "Anzeigeeinstellungen", "other_settings": "Andere Einstellungen", + "disable_fiat": "Fiat deaktivieren", + "fiat_api": "Fiat API", "disabled": "Deaktiviert", "enabled": "Ermöglicht", "tor_only": "Nur Tor" diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index c6d71a2b1..a997b9f1f 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -654,7 +654,6 @@ "use_suggested": "Use Suggested", "do_not_share_warning_text" : "Do not share these with anyone else, including support.\n\nThey will steal your money!", "help": "help", - "fiat_api": "Fiat API", "disable_exchange": "Disable exchange", "connection_sync": "Connection and sync", "security_and_backup": "Security and backup", @@ -663,6 +662,8 @@ "privacy": "Privacy", "display_settings": "Display settings", "other_settings": "Other settings", + "disable_fiat": "Disable fiat", + "fiat_api": "Fiat API", "disabled": "Disabled", "enabled": "Enabled", "tor_only": "Tor only" diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 09878ede1..959b2a9a2 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -654,7 +654,6 @@ "use_suggested": "Usar sugerido", "do_not_share_warning_text" : "No comparta estos con nadie más, incluido el soporte.\n\n¡Te robarán tu dinero!", "help": "ayuda", - "fiat_api": "Fiat API", "disable_exchange": "Deshabilitar intercambio", "connection_sync": "Conexión y sincronización", "security_and_backup": "Seguridad y respaldo", @@ -663,6 +662,8 @@ "privacy": "Privacidad", "display_settings": "Configuración de pantalla", "other_settings": "Otras configuraciones", + "disable_fiat": "Deshabilitar fiat", + "fiat_api": "Fiat API", "disabled": "Desactivado", "enabled": "Activado", "tor_only": "solo Tor" diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 66f60af81..d82cad2f9 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -652,7 +652,6 @@ "use_suggested": "Utilisation suggérée", "do_not_share_warning_text" : "Ne les partagez avec personne d'autre, y compris avec l'assistance.\n\nIls vont voler votre argent!", "help": "aider", - "fiat_api": "Fiat API", "disable_exchange": "Désactiver l'échange", "connection_sync": "Connexion et synchronisation", "security_and_backup": "Sécurité et sauvegarde", @@ -661,6 +660,8 @@ "privacy": "Confidentialité", "display_settings": "Paramètres d'affichage", "other_settings": "Autres paramètres", + "disable_fiat": "Désactiver fiat", + "fiat_api": "Fiat API", "disabled": "Handicapé", "enabled": "Activé", "tor_only": "Tor uniquement" diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index a25b649c3..42f408229 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -655,7 +655,6 @@ "do_not_share_warning_text" : "इन्हें समर्थन सहित किसी और के साथ साझा न करें।\n\nवे आपका पैसा चुरा लेंगे!", "help": "मदद करना", "disable_fiat": "िएट अक्षम करें", - "fiat_api": "फिएट पैसे API", "connection_sync": "कनेक्शन और सिंक", "security_and_backup": "सुरक्षा और बैकअप", "create_backup": "बैकअप बनाएँ", @@ -663,6 +662,8 @@ "privacy": "गोपनीयता", "display_settings": "प्रदर्शन सेटिंग्स", "other_settings": "अन्य सेटिंग्स", + "disable_exchange": "एक्सचेंज अक्षम करें", + "fiat_api": "फिएट पैसे API", "disabled": "अक्षम", "enabled": "सक्रिय", "tor_only": "Tor केवल" diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index e7e0ff1e4..0e026e97d 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -654,7 +654,6 @@ "use_suggested": "Koristite predloženo", "do_not_share_warning_text" : "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nUkrast će vam novac!", "help": "pomozite", - "fiat_api": "Fiat API", "disable_exchange": "Onemogući exchange", "connection_sync": "Povezivanje i sinkronizacija", "security_and_backup": "Sigurnost i sigurnosna kopija", @@ -663,6 +662,8 @@ "privacy": "Privatnost", "display_settings": "Postavke zaslona", "other_settings": "Ostale postavke", + "disable_fiat": "Isključi, fiat", + "fiat_api": "Fiat API", "disabled": "Onemogućeno", "enabled": "Omogućeno", "tor_only": "Samo Tor" diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 80a0ea1fd..db2a98658 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -654,7 +654,6 @@ "use_suggested": "Usa suggerito", "do_not_share_warning_text" : "Non condividerli con nessun altro, incluso il supporto.\n\nTi ruberanno i soldi!", "help": "aiuto", - "fiat_api": "Fiat API", "disable_exchange": "Disabilita scambio", "connection_sync": "Connessione e sincronizzazione", "security_and_backup": "Sicurezza e backup", @@ -663,6 +662,8 @@ "privacy": "Privacy", "display_settings": "Impostazioni di visualizzazione", "other_settings": "Altre impostazioni", + "disable_fiat": "Disabilita fiat", + "fiat_api": "Fiat API", "disabled": "Disabilitato", "enabled": "Abilitato", "tor_only": "Solo Tor" diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index b38066916..21fe513e9 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -654,7 +654,6 @@ "use_suggested": "推奨を使用", "do_not_share_warning_text" : "サポートを含め、これらを他の誰とも共有しないでください。\n\n彼らはあなたのお金を盗みます!", "help": "ヘルプ", - "fiat_api": "不換紙幣 API", "disable_exchange": "交換を無効にする", "connection_sync": "接続と同期", "security_and_backup": "セキュリティとバックアップ", @@ -663,6 +662,8 @@ "privacy": "プライバシー", "display_settings": "表示設定", "other_settings": "その他の設定", + "disable_fiat": "フィアットを無効にする", + "fiat_api": "不換紙幣 API", "disabled": "無効", "enabled": "有効", "tor_only": "Torのみ" diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index e4915cbb0..38f001df0 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -654,7 +654,6 @@ "use_suggested": "추천 사용", "do_not_share_warning_text" : "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n그들은 당신의 돈을 훔칠 것입니다!", "help": "돕다", - "fiat_api": "명목 화폐 API", "disable_exchange": "교환 비활성화", "connection_sync": "연결 및 동기화", "security_and_backup": "보안 및 백업", @@ -663,6 +662,8 @@ "privacy": "프라이버시", "display_settings": "디스플레이 설정", "other_settings": "기타 설정", + "disable_fiat": "법정화폐 비활성화", + "fiat_api": "명목 화폐 API", "disabled": "장애가 있는", "enabled": "사용", "tor_only": "Tor 뿐" diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 59a816602..6283518f6 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -654,7 +654,6 @@ "use_suggested": "Gebruik aanbevolen", "do_not_share_warning_text" : "Deel deze met niemand anders, ook niet met support.\n\nZe zullen je geld stelen!", "help": "helpen", - "fiat_api": "Fiat API", "disable_exchange": "Uitwisseling uitschakelen", "connection_sync": "Verbinding en synchronisatie", "security_and_backup": "Beveiliging en back-up", @@ -663,6 +662,8 @@ "privacy": "Privacy", "display_settings": "Weergave-instellingen", "other_settings": "Andere instellingen", + "disable_fiat": "Schakel Fiat uit", + "fiat_api": "Fiat API", "disabled": "Gehandicapt", "enabled": "Ingeschakeld", "tor_only": "Alleen Tor" diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index a2dc5c8fd..e768d7d4d 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -654,7 +654,6 @@ "use_suggested": "Użyj sugerowane", "do_not_share_warning_text" : "Nie udostępniaj ich nikomu innemu, w tym wsparcia.\n\nUkradną twoje pieniądze!", "help": "pomoc", - "fiat_api": "API Fiata", "disable_exchange": "Wyłącz wymianę", "connection_sync": "Połączenie i synchronizacja", "security_and_backup": "Bezpieczeństwo i kopia zapasowa", @@ -663,6 +662,8 @@ "privacy": "Prywatność", "display_settings": "Ustawienia wyświetlania", "other_settings": "Inne ustawienia", + "disable_fiat": "Wyłącz fiat", + "fiat_api": "API Fiata", "disabled": "Wyłączone", "enabled": "Włączony", "tor_only": "Tylko Tor" diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index f61ac5e67..bd9c5e474 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -653,7 +653,6 @@ "use_suggested": "Uso sugerido", "do_not_share_warning_text" : "Não os compartilhe com mais ninguém, incluindo suporte.\n\nEles vão roubar seu dinheiro!", "help": "ajuda", - "fiat_api": "API da Fiat", "disable_exchange": "Desativar troca", "connection_sync": "Conexão e sincronização", "security_and_backup": "Segurança e backup", @@ -662,6 +661,8 @@ "privacy": "Privacidade", "display_settings": "Configurações de exibição", "other_settings": "Outras configurações", + "disable_fiat": "Desativar fiat", + "fiat_api": "API da Fiat", "disabled": "Desabilitado", "enabled": "Habilitado", "tor_only": "Tor apenas" diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index c44e9af35..8e1e0f21c 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -654,7 +654,6 @@ "use_suggested": "Использовать предложенный", "do_not_share_warning_text" : "Не делитесь ими с кем-либо еще, в том числе со службой поддержки.\n\nОни украдут ваши деньги!", "help": "помощь", - "fiat_api": "Фиат API", "disable_exchange": "Отключить обмен", "connection_sync": "Подключение и синхронизация", "security_and_backup": "Безопасность и резервное копирование", @@ -663,6 +662,8 @@ "privacy": "Конфиденциальность", "display_settings": "Настройки отображения", "other_settings": "Другие настройки", + "disable_fiat": "Отключить фиат", + "fiat_api": "Фиат API", "disabled": "Отключено", "enabled": "Включено", "tor_only": "Только Tor" diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index a766641d7..1f72c1052 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -653,7 +653,6 @@ "use_suggested": "Використати запропоноване", "do_not_share_warning_text" : "Не повідомляйте їх нікому, включно зі службою підтримки.\n\nВони вкрадуть ваші гроші!", "help": "допомога", - "fiat_api": "Фіат API", "disable_exchange": "Вимкнути exchange", "connection_sync": "Підключення та синхронізація", "security_and_backup": "Безпека та резервне копіювання", @@ -662,6 +661,8 @@ "privacy": "Конфіденційність", "display_settings": "Налаштування дисплея", "other_settings": "Інші налаштування", + "disable_fiat": "Вимкнути фиат", + "fiat_api": "Фіат API", "disabled": "Вимкнено", "enabled": "Увімкнено", "tor_only": "Тільки Tor" diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index ae5ffbea5..12655af5a 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -652,7 +652,6 @@ "use_suggested": "使用建议", "do_not_share_warning_text" : "不要與其他任何人分享這些內容,包括支持。\n\n他們會偷你的錢!", "help": "帮助", - "fiat_api": "法币API", "disable_exchange": "禁用交换", "connection_sync": "连接和同步", "security_and_backup": "安全和备份", @@ -661,6 +660,8 @@ "privacy":"隐私", "display_settings": "显示设置", "other_settings": "其他设置", + "disable_fiat": "禁用法令", + "fiat_api": "法币API", "disabled": "禁用", "enabled": "启用", "tor_only": "仅限 Tor" From dac0b02c7dabaaacb59d853fb8d23fe19eaace88 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 8 Dec 2022 00:11:09 +0200 Subject: [PATCH 125/203] Disable updating fiat rate if the option is disabled [skip ci] --- lib/reactions/on_current_fiat_change.dart | 3 ++- lib/reactions/on_current_wallet_change.dart | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/reactions/on_current_fiat_change.dart b/lib/reactions/on_current_fiat_change.dart index 86a5ee881..5170c4576 100644 --- a/lib/reactions/on_current_fiat_change.dart +++ b/lib/reactions/on_current_fiat_change.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/core/fiat_conversion_service.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; @@ -12,7 +13,7 @@ void startCurrentFiatChangeReaction(AppStore appStore, _onCurrentFiatCurrencyChangeDisposer?.reaction.dispose(); _onCurrentFiatCurrencyChangeDisposer = reaction( (_) => settingsStore.fiatCurrency, (FiatCurrency fiatCurrency) async { - if (appStore.wallet == null) { + if (appStore.wallet == null || settingsStore.fiatApiMode == FiatApiMode.disabled) { return; } diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart index cce972368..270415820 100644 --- a/lib/reactions/on_current_wallet_change.dart +++ b/lib/reactions/on_current_wallet_change.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/update_haven_rate.dart'; import 'package:cw_core/transaction_history.dart'; @@ -87,7 +88,7 @@ void startCurrentWalletChangeReaction(AppStore appStore, TransactionHistoryBase, TransactionInfo>? wallet) async { try { - if (wallet == null) { + if (wallet == null || settingsStore.fiatApiMode == FiatApiMode.disabled) { return; } From d2fe7b26e001a82a560625a891bb01f88df89353 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 8 Dec 2022 00:26:19 +0200 Subject: [PATCH 126/203] Remove unused fiat_rate_update.dart [skip ci] --- lib/reactions/fiat_rate_update.dart | 40 ----------------------------- 1 file changed, 40 deletions(-) delete mode 100644 lib/reactions/fiat_rate_update.dart diff --git a/lib/reactions/fiat_rate_update.dart b/lib/reactions/fiat_rate_update.dart deleted file mode 100644 index ff10a176c..000000000 --- a/lib/reactions/fiat_rate_update.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'dart:async'; -import 'package:cake_wallet/core/fiat_conversion_service.dart'; -import 'package:cake_wallet/entities/fiat_api_mode.dart'; -import 'package:cake_wallet/entities/update_haven_rate.dart'; -import 'package:cake_wallet/store/app_store.dart'; -import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; -import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cw_core/wallet_type.dart'; - -Timer? _timer; - -Future startFiatRateUpdate(AppStore appStore, SettingsStore settingsStore, - FiatConversionStore fiatConversionStore) async { - if (_timer != null) { - return; - } - - if (appStore.wallet != null) { - fiatConversionStore.prices[appStore.wallet!.currency] = - await FiatConversionService.fetchPrice( - appStore.wallet!.currency, settingsStore.fiatCurrency); - } - - _timer = Timer.periodic( - Duration(seconds: 30), - (_) async { - try { - if (appStore.wallet!.type == WalletType.haven) { - await updateHavenRate(fiatConversionStore); - } else { - fiatConversionStore.prices[appStore.wallet!.currency] = - settingsStore.fiatApiMode == FiatApiMode.disabled ? 0.0 - : await FiatConversionService.fetchPrice( - appStore.wallet!.currency, settingsStore.fiatCurrency); - } - } catch(e) { - print(e); - } - }); -} From d0c22aa082b5f61ad534544afd0ecf33b286aebc Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 8 Dec 2022 01:21:45 +0200 Subject: [PATCH 127/203] - Fix Change now request missing type - Only send either to or from amount depending on fixed rate - take the trade amount from the response --- lib/exchange/changenow/changenow_exchange_provider.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/exchange/changenow/changenow_exchange_provider.dart b/lib/exchange/changenow/changenow_exchange_provider.dart index ca245923f..ee49855e4 100644 --- a/lib/exchange/changenow/changenow_exchange_provider.dart +++ b/lib/exchange/changenow/changenow_exchange_provider.dart @@ -97,15 +97,17 @@ class ChangeNowExchangeProvider extends ExchangeProvider { apiHeaderKey: apiKey, 'Content-Type': 'application/json'}; final flow = getFlow(isFixedRateMode); + final type = isFixedRateMode ? 'reverse' : 'direct'; final body = { 'fromCurrency': normalizeCryptoCurrency(_request.from), 'toCurrency': normalizeCryptoCurrency(_request.to), 'fromNetwork': networkFor(_request.from), 'toNetwork': networkFor(_request.to), - 'fromAmount': _request.fromAmount, - 'toAmount': _request.toAmount, + if (!isFixedRateMode) 'fromAmount': _request.fromAmount, + if (isFixedRateMode) 'toAmount': _request.toAmount, 'address': _request.address, 'flow': flow, + 'type': type, 'refundAddress': _request.refundAddress }; @@ -151,7 +153,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { refundAddress: refundAddress, extraId: extraId, createdAt: DateTime.now(), - amount: _request.fromAmount, + amount: responseJSON['fromAmount']?.toString() ?? _request.fromAmount, state: TradeState.created); } From a1dd22232b93235dffa06d46fd81a9dba20353b9 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 8 Dec 2022 09:56:04 +0200 Subject: [PATCH 128/203] [skip ci] fix fiat settings display --- lib/src/screens/settings/display_settings_page.dart | 3 ++- lib/view_model/settings/display_settings_view_model.dart | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/src/screens/settings/display_settings_page.dart b/lib/src/screens/settings/display_settings_page.dart index cd413ff45..39123a7eb 100644 --- a/lib/src/screens/settings/display_settings_page.dart +++ b/lib/src/screens/settings/display_settings_page.dart @@ -34,7 +34,8 @@ class DisplaySettingsPage extends BasePage { onValueChange: (_, bool value) { _displaySettingsViewModel.setShouldDisplayBalance(value); }), - if (!isHaven) + //if (!isHaven) it does not work correctly + if(!_displaySettingsViewModel.disabledFiatApiMode) SettingsPickerCell( title: S.current.settings_currency, searchHintText: S.current.search_currency, diff --git a/lib/view_model/settings/display_settings_view_model.dart b/lib/view_model/settings/display_settings_view_model.dart index 4e73b3399..bac6d9994 100644 --- a/lib/view_model/settings/display_settings_view_model.dart +++ b/lib/view_model/settings/display_settings_view_model.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/entities/fiat_api_mode.dart'; part 'display_settings_view_model.g.dart'; @@ -30,6 +31,9 @@ abstract class DisplaySettingsViewModelBase with Store { @computed ThemeBase get theme => _settingsStore.currentTheme; + @computed + bool get disabledFiatApiMode => _settingsStore.fiatApiMode == FiatApiMode.disabled; + @action void setBalanceDisplayMode(BalanceDisplayMode value) => _settingsStore.balanceDisplayMode = value; From 6395d6b2f76a33bab65323ee4f46faf1d6dd3d72 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 8 Dec 2022 14:10:58 +0200 Subject: [PATCH 129/203] - Add Disable fiat API option to advanced privacy settings --- .../advanced_privacy_settings_view_model.dart | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index ef9ab878f..f800e3418 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/view_model/settings/switcher_list_item.dart'; import 'package:cw_core/wallet_type.dart'; @@ -11,15 +12,13 @@ class AdvancedPrivacySettingsViewModel = AdvancedPrivacySettingsViewModelBase abstract class AdvancedPrivacySettingsViewModelBase with Store { AdvancedPrivacySettingsViewModelBase(this.type, this._settingsStore) - : _disableFiat = false, - _addCustomNode = false { + : _addCustomNode = false { settings = [ - // TODO: uncomment when Disable Fiat PR is merged - // SwitcherListItem( - // title: S.current.disable_fiat, - // value: () => _disableFiat, - // onValueChange: (_, bool value) => _disableFiat = value, - // ), + SwitcherListItem( + title: S.current.disable_fiat, + value: () => _settingsStore.fiatApiMode == FiatApiMode.disabled, + onValueChange: (_, bool value) => setFiatMode(value), + ), SwitcherListItem( title: S.current.disable_exchange, value: () => _settingsStore.disableExchange, @@ -37,9 +36,6 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { late List settings; - @observable - bool _disableFiat = false; - @observable bool _addCustomNode = false; @@ -48,4 +44,13 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { @computed bool get addCustomNode => _addCustomNode; + + @action + void setFiatMode(bool value) { + if (value) { + _settingsStore.fiatApiMode = FiatApiMode.disabled; + return; + } + _settingsStore.fiatApiMode = FiatApiMode.enabled; + } } From ce19be56a05d6cb8861e103f1c8778df6256656f Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 8 Dec 2022 17:23:17 +0200 Subject: [PATCH 130/203] - Fix haven and litecoin fee transaction priority issue - Revert removing fiat rate update and use it to update fiat rate periodically if Fiat API is not disabled --- lib/bitcoin/cw_bitcoin.dart | 4 ++ lib/entities/preferences_key.dart | 2 + lib/reactions/bootstrap.dart | 2 + lib/reactions/fiat_rate_update.dart | 40 +++++++++++++++ lib/store/settings_store.dart | 79 ++++++++++++++++++++--------- tool/configure.dart | 1 + 6 files changed, 104 insertions(+), 24 deletions(-) create mode 100644 lib/reactions/fiat_rate_update.dart diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index f224efde6..630ecf27f 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -51,6 +51,10 @@ class CWBitcoin extends Bitcoin { TransactionPriority deserializeBitcoinTransactionPriority(int raw) => BitcoinTransactionPriority.deserialize(raw: raw); + @override + TransactionPriority deserializeLitecoinTransactionPriority(int raw) + => LitecoinTransactionPriority.deserialize(raw: raw); + @override int getFeeRate(Object wallet, TransactionPriority priority) { final bitcoinWallet = wallet as ElectrumWallet; diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 7d1d75000..6d9e93de6 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -22,6 +22,8 @@ class PreferencesKey { 'current_default_settings_migration_version'; static const moneroTransactionPriority = 'current_fee_priority_monero'; static const bitcoinTransactionPriority = 'current_fee_priority_bitcoin'; + static const havenTransactionPriority = 'current_fee_priority_haven'; + static const litecoinTransactionPriority = 'current_fee_priority_litecoin'; static const shouldShowReceiveWarning = 'should_show_receive_warning'; static const shouldShowYatPopup = 'should_show_yat_popup'; static const moneroWalletPasswordUpdateV1Base = 'monero_wallet_update_v1'; diff --git a/lib/reactions/bootstrap.dart b/lib/reactions/bootstrap.dart index a40a17088..4b65ed9d2 100644 --- a/lib/reactions/bootstrap.dart +++ b/lib/reactions/bootstrap.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'package:cake_wallet/reactions/fiat_rate_update.dart'; import 'package:cake_wallet/reactions/on_current_node_change.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/widgets.dart'; @@ -31,4 +32,5 @@ Future bootstrap(GlobalKey navigatorKey) async { appStore, settingsStore, fiatConversionStore); startCurrentFiatChangeReaction(appStore, settingsStore, fiatConversionStore); startOnCurrentNodeChangeReaction(appStore); + startFiatRateUpdate(appStore, settingsStore, fiatConversionStore); } diff --git a/lib/reactions/fiat_rate_update.dart b/lib/reactions/fiat_rate_update.dart new file mode 100644 index 000000000..99a3bc4ae --- /dev/null +++ b/lib/reactions/fiat_rate_update.dart @@ -0,0 +1,40 @@ +import 'dart:async'; +import 'package:cake_wallet/core/fiat_conversion_service.dart'; +import 'package:cake_wallet/entities/fiat_api_mode.dart'; +import 'package:cake_wallet/entities/update_haven_rate.dart'; +import 'package:cake_wallet/store/app_store.dart'; +import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cw_core/wallet_type.dart'; + +Timer? _timer; + +Future startFiatRateUpdate( + AppStore appStore, SettingsStore settingsStore, FiatConversionStore fiatConversionStore) async { + if (_timer != null) { + return; + } + + if (appStore.wallet != null && settingsStore.fiatApiMode == FiatApiMode.enabled) { + fiatConversionStore.prices[appStore.wallet!.currency] = await FiatConversionService.fetchPrice( + appStore.wallet!.currency, settingsStore.fiatCurrency); + } + + _timer = Timer.periodic(Duration(seconds: 30), (_) async { + if (settingsStore.fiatApiMode == FiatApiMode.disabled) { + return; + } + + try { + if (appStore.wallet!.type == WalletType.haven) { + await updateHavenRate(fiatConversionStore); + } else { + fiatConversionStore.prices[appStore.wallet!.currency] = + await FiatConversionService.fetchPrice( + appStore.wallet!.currency, settingsStore.fiatCurrency); + } + } catch (e) { + print(e); + } + }); +} diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 237846495..283fff1e0 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -44,7 +44,9 @@ abstract class SettingsStoreBase with Store { required this.isBitcoinBuyEnabled, required this.actionlistDisplayMode, TransactionPriority? initialBitcoinTransactionPriority, - TransactionPriority? initialMoneroTransactionPriority}) + TransactionPriority? initialMoneroTransactionPriority, + TransactionPriority? initialHavenTransactionPriority, + TransactionPriority? initialLitecoinTransactionPriority}) : nodes = ObservableMap.of(nodes), _sharedPreferences = sharedPreferences, fiatCurrency = initialFiatCurrency, @@ -67,6 +69,14 @@ abstract class SettingsStoreBase with Store { priority[WalletType.bitcoin] = initialBitcoinTransactionPriority; } + if (initialHavenTransactionPriority != null) { + priority[WalletType.haven] = initialHavenTransactionPriority; + } + + if (initialLitecoinTransactionPriority != null) { + priority[WalletType.litecoin] = initialLitecoinTransactionPriority; + } + reaction( (_) => fiatCurrency, (FiatCurrency fiatCurrency) => sharedPreferences.setString( @@ -78,11 +88,25 @@ abstract class SettingsStoreBase with Store { .setBool(PreferencesKey.shouldShowYatPopup, shouldShowYatPopup)); priority.observe((change) { - final key = change.key == WalletType.monero - ? PreferencesKey.moneroTransactionPriority - : PreferencesKey.bitcoinTransactionPriority; + final String? key; + switch (change.key) { + case WalletType.monero: + key = PreferencesKey.moneroTransactionPriority; + break; + case WalletType.bitcoin: + key = PreferencesKey.bitcoinTransactionPriority; + break; + case WalletType.litecoin: + key = PreferencesKey.litecoinTransactionPriority; + break; + case WalletType.haven: + key = PreferencesKey.havenTransactionPriority; + break; + default: + key = null; + } - if (change.newValue != null) { + if (change.newValue != null && key != null) { sharedPreferences.setInt(key, change.newValue!.serialize()); } }); @@ -202,33 +226,39 @@ abstract class SettingsStoreBase with Store { static Future load( {required Box nodeSource, required bool isBitcoinBuyEnabled, - TransactionPriority? initialMoneroTransactionPriority, - TransactionPriority? initialBitcoinTransactionPriority, FiatCurrency initialFiatCurrency = FiatCurrency.usd, BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance}) async { - if (initialBitcoinTransactionPriority == null) { - initialBitcoinTransactionPriority = bitcoin?.getMediumTransactionPriority(); - } - - if (initialMoneroTransactionPriority == null) { - initialMoneroTransactionPriority = monero?.getDefaultTransactionPriority(); - } final sharedPreferences = await getIt.getAsync(); final currentFiatCurrency = FiatCurrency.deserialize(raw: sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey)!); - final savedMoneroTransactionPriority = + + TransactionPriority? moneroTransactionPriority = monero?.deserializeMoneroTransactionPriority( raw: sharedPreferences .getInt(PreferencesKey.moneroTransactionPriority)!); - final savedBitcoinTransactionPriority = + TransactionPriority? bitcoinTransactionPriority = bitcoin?.deserializeBitcoinTransactionPriority(sharedPreferences .getInt(PreferencesKey.bitcoinTransactionPriority)!); - final moneroTransactionPriority = - savedMoneroTransactionPriority ?? initialMoneroTransactionPriority; - final bitcoinTransactionPriority = - savedBitcoinTransactionPriority ?? initialBitcoinTransactionPriority; + + TransactionPriority? havenTransactionPriority; + TransactionPriority? litecoinTransactionPriority; + + if (sharedPreferences.getInt(PreferencesKey.havenTransactionPriority) != null) { + havenTransactionPriority = monero?.deserializeMoneroTransactionPriority( + raw: sharedPreferences.getInt(PreferencesKey.havenTransactionPriority)!); + } + if (sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority) != null) { + litecoinTransactionPriority = bitcoin?.deserializeLitecoinTransactionPriority( + sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority)!); + } + + moneroTransactionPriority ??= monero?.getDefaultTransactionPriority(); + bitcoinTransactionPriority ??= bitcoin?.getMediumTransactionPriority(); + havenTransactionPriority ??= monero?.getDefaultTransactionPriority(); + litecoinTransactionPriority ??= bitcoin?.getLitecoinTransactionPriorityMedium(); + final currentBalanceDisplayMode = BalanceDisplayMode.deserialize( raw: sharedPreferences .getInt(PreferencesKey.currentBalanceDisplayModeKey)!); @@ -249,8 +279,7 @@ abstract class SettingsStoreBase with Store { : ThemeType.bright.index; final savedTheme = ThemeList.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? - legacyTheme ?? - 0); + legacyTheme); final actionListDisplayMode = ObservableList(); actionListDisplayMode.addAll(deserializeActionlistDisplayModes( sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? @@ -296,7 +325,7 @@ abstract class SettingsStoreBase with Store { if (havenNode != null) { nodes[WalletType.haven] = havenNode; } - + return SettingsStore( sharedPreferences: sharedPreferences, nodes: nodes, @@ -314,6 +343,8 @@ abstract class SettingsStoreBase with Store { initialLanguageCode: savedLanguageCode, initialMoneroTransactionPriority: moneroTransactionPriority, initialBitcoinTransactionPriority: bitcoinTransactionPriority, + initialHavenTransactionPriority: havenTransactionPriority, + initialLitecoinTransactionPriority: litecoinTransactionPriority, shouldShowYatPopup: shouldShowYatPopup); } @@ -326,7 +357,7 @@ abstract class SettingsStoreBase with Store { // TransactionPriority? initialBitcoinTransactionPriority, // BalanceDisplayMode initialBalanceDisplayMode = // BalanceDisplayMode.availableBalance}) async { - + // if (initialBitcoinTransactionPriority == null) { // initialBitcoinTransactionPriority = bitcoin?.getMediumTransactionPriority(); // } diff --git a/tool/configure.dart b/tool/configure.dart index 0d3d175c4..5ae5a2111 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -75,6 +75,7 @@ abstract class Bitcoin { List getTransactionPriorities(); List getLitecoinTransactionPriorities(); TransactionPriority deserializeBitcoinTransactionPriority(int raw); + TransactionPriority deserializeLitecoinTransactionPriority(int raw); int getFeeRate(Object wallet, TransactionPriority priority); Future generateNewAddress(Object wallet); Object createBitcoinTransactionCredentials(List outputs, {required TransactionPriority priority, int? feeRate}); From 4b1e9a10ebd84daff704f27c88bf4f8a88cafd45 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 8 Dec 2022 21:14:42 +0200 Subject: [PATCH 131/203] - Rename calculateAmount to fetchRate to be more descriptive - Add Disable Exchange change reaction to save in shared prefs [skip ci] --- lib/exchange/changenow/changenow_exchange_provider.dart | 4 ++-- lib/exchange/exchange_provider.dart | 2 +- lib/exchange/morphtoken/morphtoken_exchange_provider.dart | 2 +- lib/exchange/sideshift/sideshift_exchange_provider.dart | 2 +- lib/exchange/simpleswap/simpleswap_exchange_provider.dart | 2 +- lib/exchange/xmrto/xmrto_exchange_provider.dart | 2 +- lib/store/settings_store.dart | 5 +++++ lib/view_model/exchange/exchange_view_model.dart | 2 +- 8 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/exchange/changenow/changenow_exchange_provider.dart b/lib/exchange/changenow/changenow_exchange_provider.dart index ee49855e4..a9fb7c9ca 100644 --- a/lib/exchange/changenow/changenow_exchange_provider.dart +++ b/lib/exchange/changenow/changenow_exchange_provider.dart @@ -114,7 +114,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { if (isFixedRateMode) { // since we schedule to calculate the rate every 5 seconds we need to ensure that // we have the latest rate id with the given inputs before creating the trade - await calculateAmount( + await fetchRate( from: _request.from, to: _request.to, amount: double.tryParse(_request.toAmount) ?? 0, @@ -208,7 +208,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { } @override - Future calculateAmount( + Future fetchRate( {required CryptoCurrency from, required CryptoCurrency to, required double amount, diff --git a/lib/exchange/exchange_provider.dart b/lib/exchange/exchange_provider.dart index 108256015..763350c94 100644 --- a/lib/exchange/exchange_provider.dart +++ b/lib/exchange/exchange_provider.dart @@ -26,7 +26,7 @@ abstract class ExchangeProvider { required TradeRequest request, required bool isFixedRateMode}); Future findTradeById({required String id}); - Future calculateAmount({ + Future fetchRate({ required CryptoCurrency from, required CryptoCurrency to, required double amount, diff --git a/lib/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/exchange/morphtoken/morphtoken_exchange_provider.dart index 6650d4f3a..a2a72b24f 100644 --- a/lib/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -203,7 +203,7 @@ class MorphTokenExchangeProvider extends ExchangeProvider { } @override - Future calculateAmount( + Future fetchRate( {required CryptoCurrency from, required CryptoCurrency to, required double amount, diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/sideshift/sideshift_exchange_provider.dart index 912ad89c5..98f18f058 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/sideshift/sideshift_exchange_provider.dart @@ -57,7 +57,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { ExchangeProviderDescription.sideShift; @override - Future calculateAmount( + Future fetchRate( {required CryptoCurrency from, required CryptoCurrency to, required double amount, diff --git a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart b/lib/exchange/simpleswap/simpleswap_exchange_provider.dart index 0c1027000..2521c1486 100644 --- a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart +++ b/lib/exchange/simpleswap/simpleswap_exchange_provider.dart @@ -36,7 +36,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { ExchangeProviderDescription.simpleSwap; @override - Future calculateAmount( + Future fetchRate( {required CryptoCurrency from, required CryptoCurrency to, required double amount, diff --git a/lib/exchange/xmrto/xmrto_exchange_provider.dart b/lib/exchange/xmrto/xmrto_exchange_provider.dart index da367e4d4..536754e18 100644 --- a/lib/exchange/xmrto/xmrto_exchange_provider.dart +++ b/lib/exchange/xmrto/xmrto_exchange_provider.dart @@ -194,7 +194,7 @@ class XMRTOExchangeProvider extends ExchangeProvider { } @override - Future calculateAmount( + Future fetchRate( {required CryptoCurrency from, required CryptoCurrency to, required double amount, diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 534ea67e9..e1ff316f4 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -115,6 +115,11 @@ abstract class SettingsStoreBase with Store { (BalanceDisplayMode mode) => sharedPreferences.setInt( PreferencesKey.currentBalanceDisplayModeKey, mode.serialize())); + reaction( + (_) => disableExchange, + (bool disableExchange) => sharedPreferences.setBool( + PreferencesKey.disableExchangeKey, disableExchange)); + this .nodes .observe((change) { diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 80551304f..5c1f696b8 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -311,7 +311,7 @@ abstract class ExchangeViewModelBase with Store { final result = await Future.wait( _tradeAvailableProviders .where((element) => !isFixedRateMode || element.supportsFixedRate) - .map((element) => element.calculateAmount( + .map((element) => element.fetchRate( from: depositCurrency, to: receiveCurrency, amount: amount, From ae1d2a3bec79d2f3ba394232fda84db7e06fd1c2 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 8 Dec 2022 21:33:14 +0200 Subject: [PATCH 132/203] Add validation on node input in advanced privacy settings --- .../new_wallet/advanced_privacy_settings_page.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index ff1c83f90..6c2f996df 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -78,7 +78,14 @@ class _AdvancedPrivacySettingsBodyState extends State Date: Fri, 9 Dec 2022 15:57:45 +0200 Subject: [PATCH 133/203] Update Settings Store attributes within reload function to get latest shared prefs data --- lib/store/settings_store.dart | 92 ++++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 24 deletions(-) diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index ecc5baf8a..75032975f 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -121,7 +121,7 @@ abstract class SettingsStoreBase with Store { this .nodes - .observe((change) { + .observe((change) { if (change.newValue != null && change.key != null) { _saveCurrentNode(change.newValue!, change.key!); } @@ -304,34 +304,78 @@ abstract class SettingsStoreBase with Store { shouldShowYatPopup: shouldShowYatPopup); } - Future reload( - {required Box nodeSource, - FiatCurrency initialFiatCurrency = FiatCurrency.usd, - TransactionPriority? initialMoneroTransactionPriority, - TransactionPriority? initialBitcoinTransactionPriority, - BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance}) async { - if (initialBitcoinTransactionPriority == null) { - initialBitcoinTransactionPriority = bitcoin?.getMediumTransactionPriority(); + Future reload({required Box nodeSource}) async { + + final sharedPreferences = await getIt.getAsync(); + + fiatCurrency = FiatCurrency.deserialize( + raw: sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey)!); + + priority[WalletType.monero] = monero?.deserializeMoneroTransactionPriority( + raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? + priority[WalletType.monero]!; + priority[WalletType.bitcoin] = bitcoin?.deserializeBitcoinTransactionPriority( + sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? + priority[WalletType.bitcoin]!; + // TODO: Add litecoin and haven after CW-118 is merged + + balanceDisplayMode = BalanceDisplayMode.deserialize( + raw: sharedPreferences + .getInt(PreferencesKey.currentBalanceDisplayModeKey)!); + shouldSaveRecipientAddress = + sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? shouldSaveRecipientAddress; + allowBiometricalAuthentication = sharedPreferences + .getBool(PreferencesKey.allowBiometricalAuthenticationKey) ?? + allowBiometricalAuthentication; + disableExchange = sharedPreferences.getBool(PreferencesKey.disableExchangeKey) ?? disableExchange; + final legacyTheme = + (sharedPreferences.getBool(PreferencesKey.isDarkThemeLegacy) ?? false) + ? ThemeType.dark.index + : ThemeType.bright.index; + currentTheme = ThemeList.deserialize( + raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? + legacyTheme); + actionlistDisplayMode = ObservableList(); + actionlistDisplayMode.addAll(deserializeActionlistDisplayModes( + sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? + defaultActionsMode)); + var pinLength = sharedPreferences.getInt(PreferencesKey.currentPinLength); + // If no value + if (pinLength == null || pinLength == 0) { + pinLength = pinCodeLength; + } + pinCodeLength = pinLength; + + languageCode = sharedPreferences.getString(PreferencesKey.currentLanguageCode) ?? languageCode; + shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? shouldShowYatPopup; + + final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); + final bitcoinElectrumServerId = sharedPreferences + .getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); + final litecoinElectrumServerId = sharedPreferences + .getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); + final havenNodeId = sharedPreferences + .getInt(PreferencesKey.currentHavenNodeIdKey); + final moneroNode = nodeSource.get(nodeId); + final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId); + final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId); + final havenNode = nodeSource.get(havenNodeId); + + if (moneroNode != null) { + nodes[WalletType.monero] = moneroNode; } - if (initialMoneroTransactionPriority == null) { - initialMoneroTransactionPriority = monero?.getDefaultTransactionPriority(); + if (bitcoinElectrumServer != null) { + nodes[WalletType.bitcoin] = bitcoinElectrumServer; } - final isBitcoinBuyEnabled = (secrets.wyreSecretKey.isNotEmpty) && - (secrets.wyreApiKey.isNotEmpty) && - (secrets.wyreAccountId.isNotEmpty); + if (litecoinElectrumServer != null) { + nodes[WalletType.litecoin] = litecoinElectrumServer; + } - final settings = await SettingsStoreBase.load( - nodeSource: nodeSource, - isBitcoinBuyEnabled: isBitcoinBuyEnabled, - initialBalanceDisplayMode: initialBalanceDisplayMode, - initialFiatCurrency: initialFiatCurrency, - initialMoneroTransactionPriority: initialMoneroTransactionPriority, - initialBitcoinTransactionPriority: initialBitcoinTransactionPriority); - - getIt.unregister(); - getIt.registerSingleton(settings); + if (havenNode != null) { + nodes[WalletType.haven] = havenNode; + } } Future _saveCurrentNode(Node node, WalletType walletType) async { From 9ef1186c453256de7e3e6a2ac48a0ab0a239e336 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Fri, 9 Dec 2022 17:08:52 +0100 Subject: [PATCH 134/203] Fix issues from code review --- lib/core/auth_service.dart | 26 +-- lib/src/screens/root/root.dart | 12 +- .../screens/wallet_list/wallet_list_page.dart | 157 +++++++++--------- lib/view_model/auth_view_model.dart | 4 +- 4 files changed, 99 insertions(+), 100 deletions(-) diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index 6b167fa40..c493cddcb 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -42,25 +42,27 @@ class AuthService with Store { return decodedPin == pin; } - void saveLastAuthTime(){ + void saveLastAuthTime() { + int timestamp = DateTime.now().millisecondsSinceEpoch; sharedPreferences.setInt(PreferencesKey.lastAuthTimeMilliseconds, timestamp); } - bool requireAuth(){ - final timestamp = sharedPreferences.getInt(PreferencesKey.lastAuthTimeMilliseconds); - final duration = _durationToRequireAuth(timestamp ?? 0); - final requiredPinInterval = getIt.get().pinTimeOutDuration; + bool requireAuth() { + + final timestamp = sharedPreferences.getInt(PreferencesKey.lastAuthTimeMilliseconds); + final duration = _durationToRequireAuth(timestamp ?? 0); + final requiredPinInterval = getIt.get().pinTimeOutDuration; - return duration >= requiredPinInterval.value; - } + return duration >= requiredPinInterval.value; + } - int _durationToRequireAuth(int timestamp){ + int _durationToRequireAuth(int timestamp) { - DateTime before = DateTime.fromMillisecondsSinceEpoch(timestamp); - DateTime now = DateTime.now(); - Duration timeDifference = now.difference(before); + DateTime before = DateTime.fromMillisecondsSinceEpoch(timestamp); + DateTime now = DateTime.now(); + Duration timeDifference = now.difference(before); - return timeDifference.inMinutes; + return timeDifference.inMinutes; } } diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index 8d2b61a65..206f485dd 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'package:cake_wallet/core/auth_service.dart'; -import 'package:cake_wallet/di.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; @@ -14,12 +13,15 @@ class Root extends StatefulWidget { required this.authenticationStore, required this.appStore, required this.child, - required this.navigatorKey}) + required this.navigatorKey, + required this.authService, + }) : super(key: key); final AuthenticationStore authenticationStore; final AppStore appStore; final GlobalKey navigatorKey; + final AuthService authService; final Widget child; @override @@ -30,7 +32,7 @@ class RootState extends State with WidgetsBindingObserver { RootState() : _isInactiveController = StreamController.broadcast(), _isInactive = false, - _requestAuth = getIt.get().requireAuth(), + _requestAuth = true, _postFrameCallback = false; Stream get isInactive => _isInactiveController.stream; @@ -41,7 +43,7 @@ class RootState extends State with WidgetsBindingObserver { @override void initState() { - + _requestAuth = widget.authService.requireAuth(); _isInactiveController = StreamController.broadcast(); _isInactive = false; _postFrameCallback = false; @@ -58,7 +60,7 @@ class RootState extends State with WidgetsBindingObserver { } setState(() { - _requestAuth = getIt.get().requireAuth(); + _requestAuth = widget.authService.requireAuth(); }); if (!_isInactive && diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 5d9650ef2..d76631b3f 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -220,93 +220,88 @@ class WalletListBodyState extends State { } Future _loadWallet(WalletListItem wallet) async { - if(await widget.walletListViewModel.checkIfAuthRequired()){ - await Navigator.of(context).pushNamed(Routes.auth, arguments: - (bool isAuthenticatedSuccessfully, AuthPageState auth) async { - if (!isAuthenticatedSuccessfully) { - return; - } + if (await widget.walletListViewModel.checkIfAuthRequired()) { + await Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { + if (!isAuthenticatedSuccessfully) { + return; + } - try { - auth.changeProcessText( - S.of(context).wallet_list_loading_wallet(wallet.name)); - await widget.walletListViewModel.loadWallet(wallet); - auth.hideProgressText(); - auth.close(); - WidgetsBinding.instance.addPostFrameCallback((_) { - Navigator.of(context).pop(); - }); - } catch (e) { - auth.changeProcessText(S - .of(context) - .wallet_list_failed_to_load(wallet.name, e.toString())); - } - }); - }else{ + try { + auth.changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name)); + await widget.walletListViewModel.loadWallet(wallet); + auth.hideProgressText(); + auth.close(); + WidgetsBinding.instance.addPostFrameCallback((_) { + Navigator.of(context).pop(); + }); + } catch (e) { + auth.changeProcessText( + S.of(context).wallet_list_failed_to_load(wallet.name, e.toString())); + } + }); + } else { try { changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name)); await widget.walletListViewModel.loadWallet(wallet); hideProgressText(); - Navigator.of(context).pop(); + Navigator.of(context).pop(); } catch (e) { - changeProcessText(S - .of(context) - .wallet_list_failed_to_load(wallet.name, e.toString())); + changeProcessText(S.of(context).wallet_list_failed_to_load(wallet.name, e.toString())); } } } Future _removeWallet(WalletListItem wallet) async { - if(widget.walletListViewModel.checkIfAuthRequired()){ - await Navigator.of(context).pushNamed(Routes.auth, arguments: - (bool isAuthenticatedSuccessfully, AuthPageState auth) async { - if (!isAuthenticatedSuccessfully) { - return; - } - _onSuccessfulAuth(wallet, auth); - }); - }else{ + if (widget.walletListViewModel.checkIfAuthRequired()) { + await Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { + if (!isAuthenticatedSuccessfully) { + return; + } + _onSuccessfulAuth(wallet, auth); + }); + } else { _onSuccessfulAuth(wallet, null); } } - _onSuccessfulAuth(WalletListItem wallet, AuthPageState? auth)async{ + void _onSuccessfulAuth(WalletListItem wallet, AuthPageState? auth) async { bool confirmed = false; - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: S.of(context).delete_wallet, - alertContent: S.of(context).delete_wallet_confirm_message(wallet.name), - leftButtonText: S.of(context).cancel, - rightButtonText: S.of(context).delete, - actionLeftButton: () => Navigator.of(context).pop(), - actionRightButton: () { - confirmed = true; - Navigator.of(context).pop(); - }, - ); - }); - - if (confirmed) { - try { - auth != null ? - auth.changeProcessText( - S.of(context).wallet_list_removing_wallet(wallet.name)) - : changeProcessText( S.of(context).wallet_list_removing_wallet(wallet.name)); - await widget.walletListViewModel.remove(wallet); - } catch (e) { - auth != null ? - auth.changeProcessText( - S.of(context).wallet_list_failed_to_remove(wallet.name, e.toString()), - ) - : changeProcessText( - S.of(context).wallet_list_failed_to_remove(wallet.name, e.toString()), + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).delete_wallet, + alertContent: S.of(context).delete_wallet_confirm_message(wallet.name), + leftButtonText: S.of(context).cancel, + rightButtonText: S.of(context).delete, + actionLeftButton: () => Navigator.of(context).pop(), + actionRightButton: () { + confirmed = true; + Navigator.of(context).pop(); + }, ); - } - } + }); - auth?.close(); + if (confirmed) { + try { + auth != null + ? auth.changeProcessText(S.of(context).wallet_list_removing_wallet(wallet.name)) + : changeProcessText(S.of(context).wallet_list_removing_wallet(wallet.name)); + await widget.walletListViewModel.remove(wallet); + } catch (e) { + auth != null + ? auth.changeProcessText( + S.of(context).wallet_list_failed_to_remove(wallet.name, e.toString()), + ) + : changeProcessText( + S.of(context).wallet_list_failed_to_remove(wallet.name, e.toString()), + ); + } + } + + auth?.close(); } void changeProcessText(String text) { @@ -319,16 +314,16 @@ class WalletListBodyState extends State { } ActionPane _actionPane(WalletListItem wallet) => ActionPane( - motion: const ScrollMotion(), - extentRatio: 0.3, - children: [ - SlidableAction( - onPressed: (_) => _removeWallet(wallet), - backgroundColor: Colors.red, - foregroundColor: Colors.white, - icon: CupertinoIcons.delete, - label: S.of(context).delete, - ), - ], - ); + motion: const ScrollMotion(), + extentRatio: 0.3, + children: [ + SlidableAction( + onPressed: (_) => _removeWallet(wallet), + backgroundColor: Colors.red, + foregroundColor: Colors.white, + icon: CupertinoIcons.delete, + label: S.of(context).delete, + ), + ], + ); } diff --git a/lib/view_model/auth_view_model.dart b/lib/view_model/auth_view_model.dart index 42201ddab..d45873230 100644 --- a/lib/view_model/auth_view_model.dart +++ b/lib/view_model/auth_view_model.dart @@ -121,8 +121,8 @@ abstract class AuthViewModelBase with Store { } } - void _saveLastAuthTime(ExecutionState state){ - if(state is ExecutedSuccessfullyState){ + void _saveLastAuthTime(ExecutionState state) { + if(state is ExecutedSuccessfullyState) { _authService.saveLastAuthTime(); } } From 5310c265a77e9facb44e88edfc469ca4f833015a Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 9 Dec 2022 19:41:54 +0200 Subject: [PATCH 135/203] Separate update fiat rate in a function to enhance readability [skip ci] --- lib/reactions/fiat_rate_update.dart | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/reactions/fiat_rate_update.dart b/lib/reactions/fiat_rate_update.dart index 99a3bc4ae..70387be97 100644 --- a/lib/reactions/fiat_rate_update.dart +++ b/lib/reactions/fiat_rate_update.dart @@ -15,26 +15,28 @@ Future startFiatRateUpdate( return; } - if (appStore.wallet != null && settingsStore.fiatApiMode == FiatApiMode.enabled) { - fiatConversionStore.prices[appStore.wallet!.currency] = await FiatConversionService.fetchPrice( - appStore.wallet!.currency, settingsStore.fiatCurrency); - } + _updateFiatRate(appStore, settingsStore, fiatConversionStore); _timer = Timer.periodic(Duration(seconds: 30), (_) async { - if (settingsStore.fiatApiMode == FiatApiMode.disabled) { - return; - } - try { if (appStore.wallet!.type == WalletType.haven) { await updateHavenRate(fiatConversionStore); } else { - fiatConversionStore.prices[appStore.wallet!.currency] = - await FiatConversionService.fetchPrice( - appStore.wallet!.currency, settingsStore.fiatCurrency); + _updateFiatRate(appStore, settingsStore, fiatConversionStore); } } catch (e) { print(e); } }); } + +void _updateFiatRate( + AppStore appStore, + SettingsStore settingsStore, + FiatConversionStore fiatConversionStore, +) async { + if (appStore.wallet != null && settingsStore.fiatApiMode == FiatApiMode.enabled) { + fiatConversionStore.prices[appStore.wallet!.currency] = await FiatConversionService.fetchPrice( + appStore.wallet!.currency, settingsStore.fiatCurrency); + } +} From fde1ea74de2ece5f333c7c90b75075f181f5b2b4 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 9 Dec 2022 19:55:23 +0200 Subject: [PATCH 136/203] Remove duplicate fetching for fiat rate [skip ci] --- lib/reactions/fiat_rate_update.dart | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/lib/reactions/fiat_rate_update.dart b/lib/reactions/fiat_rate_update.dart index 70387be97..04276b567 100644 --- a/lib/reactions/fiat_rate_update.dart +++ b/lib/reactions/fiat_rate_update.dart @@ -15,28 +15,18 @@ Future startFiatRateUpdate( return; } - _updateFiatRate(appStore, settingsStore, fiatConversionStore); - _timer = Timer.periodic(Duration(seconds: 30), (_) async { try { if (appStore.wallet!.type == WalletType.haven) { await updateHavenRate(fiatConversionStore); } else { - _updateFiatRate(appStore, settingsStore, fiatConversionStore); + if (appStore.wallet != null && settingsStore.fiatApiMode == FiatApiMode.enabled) { + fiatConversionStore.prices[appStore.wallet!.currency] = await FiatConversionService.fetchPrice( + appStore.wallet!.currency, settingsStore.fiatCurrency); + } } } catch (e) { print(e); } }); } - -void _updateFiatRate( - AppStore appStore, - SettingsStore settingsStore, - FiatConversionStore fiatConversionStore, -) async { - if (appStore.wallet != null && settingsStore.fiatApiMode == FiatApiMode.enabled) { - fiatConversionStore.prices[appStore.wallet!.currency] = await FiatConversionService.fetchPrice( - appStore.wallet!.currency, settingsStore.fiatCurrency); - } -} From 899e999d78d366b86cbc528c5f0f2f3df0fc2840 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 9 Dec 2022 20:04:44 +0200 Subject: [PATCH 137/203] check nullability of wallet and disable fiat api state before updating rates [skip ci] --- lib/reactions/fiat_rate_update.dart | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/reactions/fiat_rate_update.dart b/lib/reactions/fiat_rate_update.dart index 04276b567..48c61d8ca 100644 --- a/lib/reactions/fiat_rate_update.dart +++ b/lib/reactions/fiat_rate_update.dart @@ -17,13 +17,16 @@ Future startFiatRateUpdate( _timer = Timer.periodic(Duration(seconds: 30), (_) async { try { + if (appStore.wallet == null || settingsStore.fiatApiMode == FiatApiMode.disabled) { + return; + } + if (appStore.wallet!.type == WalletType.haven) { await updateHavenRate(fiatConversionStore); } else { - if (appStore.wallet != null && settingsStore.fiatApiMode == FiatApiMode.enabled) { - fiatConversionStore.prices[appStore.wallet!.currency] = await FiatConversionService.fetchPrice( - appStore.wallet!.currency, settingsStore.fiatCurrency); - } + fiatConversionStore.prices[appStore.wallet!.currency] = + await FiatConversionService.fetchPrice( + appStore.wallet!.currency, settingsStore.fiatCurrency); } } catch (e) { print(e); From 87e72eabdf15196e7605ed1c15ce2b8975fe85bf Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 9 Dec 2022 20:36:51 +0200 Subject: [PATCH 138/203] Fix conflicts with main [skip ci] --- lib/store/settings_store.dart | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index dd574e7c9..96d74a23a 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -364,7 +364,17 @@ abstract class SettingsStoreBase with Store { priority[WalletType.bitcoin] = bitcoin?.deserializeBitcoinTransactionPriority( sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? priority[WalletType.bitcoin]!; - // TODO: Add litecoin and haven after CW-118 is merged + + if (sharedPreferences.getInt(PreferencesKey.havenTransactionPriority) != null) { + priority[WalletType.haven] = monero?.deserializeMoneroTransactionPriority( + raw: sharedPreferences.getInt(PreferencesKey.havenTransactionPriority)!) ?? + priority[WalletType.haven]!; + } + if (sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority) != null) { + priority[WalletType.litecoin] = bitcoin?.deserializeLitecoinTransactionPriority( + sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority)!) ?? + priority[WalletType.litecoin]!; + } balanceDisplayMode = BalanceDisplayMode.deserialize( raw: sharedPreferences From 6836ac6d1ac2374b4586b7ac3bd643909ed14fbe Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Fri, 9 Dec 2022 20:18:36 +0100 Subject: [PATCH 139/203] Fix formatting --- lib/core/auth_service.dart | 14 +++++--------- lib/view_model/auth_view_model.dart | 21 ++++++++++----------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index c493cddcb..569db5700 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -21,8 +21,7 @@ class AuthService with Store { Future canAuthenticate() async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); - final walletName = - sharedPreferences.getString(PreferencesKey.currentWalletName) ?? ''; + final walletName = sharedPreferences.getString(PreferencesKey.currentWalletName) ?? ''; var password = ''; try { @@ -43,26 +42,23 @@ class AuthService with Store { } void saveLastAuthTime() { - int timestamp = DateTime.now().millisecondsSinceEpoch; sharedPreferences.setInt(PreferencesKey.lastAuthTimeMilliseconds, timestamp); } - bool requireAuth() { - + bool requireAuth() { final timestamp = sharedPreferences.getInt(PreferencesKey.lastAuthTimeMilliseconds); - final duration = _durationToRequireAuth(timestamp ?? 0); + final duration = _durationToRequireAuth(timestamp ?? 0); final requiredPinInterval = getIt.get().pinTimeOutDuration; - + return duration >= requiredPinInterval.value; } int _durationToRequireAuth(int timestamp) { - DateTime before = DateTime.fromMillisecondsSinceEpoch(timestamp); DateTime now = DateTime.now(); Duration timeDifference = now.difference(before); - return timeDifference.inMinutes; + return timeDifference.inMinutes; } } diff --git a/lib/view_model/auth_view_model.dart b/lib/view_model/auth_view_model.dart index d45873230..e50f4db0c 100644 --- a/lib/view_model/auth_view_model.dart +++ b/lib/view_model/auth_view_model.dart @@ -14,12 +14,12 @@ part 'auth_view_model.g.dart'; class AuthViewModel = AuthViewModelBase with _$AuthViewModel; abstract class AuthViewModelBase with Store { - AuthViewModelBase(this._authService, this._sharedPreferences, - this._settingsStore, this._biometricAuth) + AuthViewModelBase( + this._authService, this._sharedPreferences, this._settingsStore, this._biometricAuth) : _failureCounter = 0, - state = InitialExecutionState(){ - reaction((_) => state, _saveLastAuthTime); - } + state = InitialExecutionState() { + reaction((_) => state, _saveLastAuthTime); + } static const maxFailedLogins = 3; static const banTimeout = 180; // 3 minutes @@ -30,8 +30,7 @@ abstract class AuthViewModelBase with Store { int get pinLength => _settingsStore.pinCodeLength; - bool get isBiometricalAuthenticationAllowed => - _settingsStore.allowBiometricalAuthentication; + bool get isBiometricalAuthenticationAllowed => _settingsStore.allowBiometricalAuthentication; @observable int _failureCounter; @@ -59,7 +58,7 @@ abstract class AuthViewModelBase with Store { if (isSuccessfulAuthenticated) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - state = ExecutedSuccessfullyState(); + state = ExecutedSuccessfullyState(); _failureCounter = 0; }); } else { @@ -116,14 +115,14 @@ abstract class AuthViewModelBase with Store { state = ExecutedSuccessfullyState(); } } - } catch(e) { + } catch (e) { state = FailureState(e.toString()); } } void _saveLastAuthTime(ExecutionState state) { - if(state is ExecutedSuccessfullyState) { - _authService.saveLastAuthTime(); + if (state is ExecutedSuccessfullyState) { + _authService.saveLastAuthTime(); } } } From 59484e5b9165ed01454bf63438013c64037df21c Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Fri, 9 Dec 2022 20:19:23 +0100 Subject: [PATCH 140/203] Fix formatting --- lib/src/screens/root/root.dart | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index 206f485dd..d217789e8 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -8,15 +8,14 @@ import 'package:cake_wallet/store/authentication_store.dart'; import 'package:cake_wallet/entities/qr_scanner.dart'; class Root extends StatefulWidget { - Root( - {required Key key, - required this.authenticationStore, - required this.appStore, - required this.child, - required this.navigatorKey, - required this.authService, - }) - : super(key: key); + Root({ + required Key key, + required this.authenticationStore, + required this.appStore, + required this.child, + required this.navigatorKey, + required this.authService, + }) : super(key: key); final AuthenticationStore authenticationStore; final AppStore appStore; @@ -30,10 +29,10 @@ class Root extends StatefulWidget { class RootState extends State with WidgetsBindingObserver { RootState() - : _isInactiveController = StreamController.broadcast(), - _isInactive = false, - _requestAuth = true, - _postFrameCallback = false; + : _isInactiveController = StreamController.broadcast(), + _isInactive = false, + _requestAuth = true, + _postFrameCallback = false; Stream get isInactive => _isInactiveController.stream; StreamController _isInactiveController; @@ -63,8 +62,7 @@ class RootState extends State with WidgetsBindingObserver { _requestAuth = widget.authService.requireAuth(); }); - if (!_isInactive && - widget.authenticationStore.state == AuthenticationState.allowed) { + if (!_isInactive && widget.authenticationStore.state == AuthenticationState.allowed) { setState(() => _setInactive(true)); } From ff28dfbb9ca071e57035089b016b48bea07d24ea Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 10 Dec 2022 11:40:04 +0200 Subject: [PATCH 141/203] Rename Change.NOW --- lib/view_model/dashboard/dashboard_view_model.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 284b1fc72..40ea2d78b 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -83,12 +83,12 @@ abstract class DashboardViewModelBase with Store { .toggleDisplayExchange(ExchangeProviderDescription.all)), FilterItem( value: tradeFilterStore.displayChangeNow, - caption: 'Change.NOW', + caption: ExchangeProviderDescription.changeNow.title, onChanged: () => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.changeNow)), FilterItem( value: tradeFilterStore.displaySideShift, - caption: 'SideShift', + caption: ExchangeProviderDescription.sideShift.title, onChanged: () => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.sideShift)), ] From c57507e530d3bff5792f4272842a6a6cf0e20721 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 10 Dec 2022 12:56:37 +0200 Subject: [PATCH 142/203] redesigh checkbox --- .../dashboard/widgets/filter_widget.dart | 13 ++- lib/src/widgets/rounded_checkbox.dart | 91 ------------------- lib/src/widgets/standard_checkbox.dart | 44 ++++++--- 3 files changed, 39 insertions(+), 109 deletions(-) delete mode 100644 lib/src/widgets/rounded_checkbox.dart diff --git a/lib/src/screens/dashboard/widgets/filter_widget.dart b/lib/src/screens/dashboard/widgets/filter_widget.dart index 10bda6798..a3172940f 100644 --- a/lib/src/screens/dashboard/widgets/filter_widget.dart +++ b/lib/src/screens/dashboard/widgets/filter_widget.dart @@ -1,12 +1,12 @@ import 'dart:ui'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/filter_tile.dart'; +import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/alert_background.dart'; import 'package:cake_wallet/src/widgets/alert_close_button.dart'; -import 'package:cake_wallet/src/widgets/rounded_checkbox.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; //import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker; @@ -97,14 +97,13 @@ class FilterWidget extends StatelessWidget { final content = item.onChanged != null ? Observer( builder: (_) => - RoundedCheckboxWidget( + StandardCheckbox( value: item.value.value, caption: item.caption, - onChanged: item.onChanged, - currentTheme: - dashboardViewModel - .settingsStore - .currentTheme, + gradientBackground: true, + borderColor: Theme.of(context).dividerColor, + iconColor: Colors.white, + onChanged: (bool val){}, )) : GestureDetector( onTap: () async { diff --git a/lib/src/widgets/rounded_checkbox.dart b/lib/src/widgets/rounded_checkbox.dart deleted file mode 100644 index 1bdfb267d..000000000 --- a/lib/src/widgets/rounded_checkbox.dart +++ /dev/null @@ -1,91 +0,0 @@ -import 'package:cake_wallet/palette.dart'; -import 'package:flutter/material.dart'; -import 'package:cake_wallet/themes/theme_base.dart'; - -class RoundedCheckboxWidget extends StatelessWidget { - RoundedCheckboxWidget( - {required this.value, - required this.caption, - required this.onChanged, - this.currentTheme}); - - final bool value; - final String caption; - final Function onChanged; - final ThemeBase? currentTheme; - - bool get darkTheme => currentTheme!.type == ThemeType.dark; - - @override - Widget build(BuildContext context) { - - final baseGradient = LinearGradient(colors: [ - Theme.of(context).primaryTextTheme.subtitle1!.color!, - Theme.of(context).primaryTextTheme.subtitle1!.decorationColor!, - ], begin: Alignment.centerLeft, end: Alignment.centerRight); - - final darkThemeGradient = LinearGradient(colors: [ - Palette.blueCraiola, - Palette.blueGreyCraiola, - ], begin: Alignment.topLeft, end: Alignment.bottomRight); - - final gradient = darkTheme ? darkThemeGradient : baseGradient; - - final uncheckedColor = darkTheme - ? Theme.of(context).primaryTextTheme.subtitle1!.decorationColor! - : Colors.white; - - final borderColor = darkTheme - ? Theme.of(context).accentTextTheme.subtitle2!.backgroundColor! - : Colors.transparent; - - final checkedOuterBoxDecoration = - BoxDecoration(shape: BoxShape.circle, gradient: gradient); - final outerBoxDecoration = BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).accentTextTheme.overline!.color!, - border: Border.all(color: borderColor)); - - final checkedInnerBoxDecoration = - BoxDecoration(shape: BoxShape.circle, color: Colors.white); - final innerBoxDecoration = - BoxDecoration(shape: BoxShape.circle, color: uncheckedColor); - - return GestureDetector( - onTap: () => onChanged(), - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - height: 24.0, - width: 24.0, - child: DecoratedBox( - decoration: - value ? checkedOuterBoxDecoration : outerBoxDecoration, - child: Padding( - padding: EdgeInsets.all(value ? 4.0 : 1.0), - child: DecoratedBox( - decoration: - value ? checkedInnerBoxDecoration : innerBoxDecoration, - ), - ), - ), - ), - Padding( - padding: EdgeInsets.only(left: 16), - child: Text( - caption, - style: TextStyle( - color: Theme.of(context).primaryTextTheme.headline6!.color!, - fontSize: 18, - fontFamily: 'Lato', - fontWeight: FontWeight.w500, - decoration: TextDecoration.none), - ), - ) - ], - ), - ); - } -} \ No newline at end of file diff --git a/lib/src/widgets/standard_checkbox.dart b/lib/src/widgets/standard_checkbox.dart index a59364fe1..9202ea7f5 100644 --- a/lib/src/widgets/standard_checkbox.dart +++ b/lib/src/widgets/standard_checkbox.dart @@ -7,11 +7,17 @@ class StandardCheckbox extends StatefulWidget { Key? key, required this.value, this.caption = '', + this.gradientBackground = false, + this.borderColor, + this.iconColor, required this.onChanged}) : super(key: key); final bool value; final String caption; + final bool gradientBackground; + final Color? borderColor; + final Color? iconColor; final Function(bool) onChanged; @override @@ -32,6 +38,31 @@ class StandardCheckboxState extends State { @override Widget build(BuildContext context) { + + final baseGradient = LinearGradient(colors: [ + Theme.of(context).primaryTextTheme.subtitle1!.color!, + Theme.of(context).primaryTextTheme.subtitle1!.decorationColor!, + ], begin: Alignment.centerLeft, end: Alignment.centerRight); + + final boxBorder = Border.all( + color: widget.borderColor ?? Theme.of(context) + .primaryTextTheme + .caption! + .color!, + width: 1.0); + + + final checkedBoxDecoration = BoxDecoration( + gradient: widget.gradientBackground ? baseGradient : null, + border: widget.gradientBackground ? null : boxBorder, + borderRadius: BorderRadius.all( + Radius.circular(8.0))); + + final uncheckedBoxDecoration = BoxDecoration( + border: boxBorder, + borderRadius: BorderRadius.all( + Radius.circular(8.0))); + return GestureDetector( onTap: () { value = !value; @@ -45,20 +76,11 @@ class StandardCheckboxState extends State { Container( height: 24.0, width: 24.0, - decoration: BoxDecoration( - border: Border.all( - color: Theme.of(context) - .primaryTextTheme! - .caption! - .color!, - width: 1.0), - borderRadius: BorderRadius.all( - Radius.circular(8.0)), - color: Theme.of(context).backgroundColor), + decoration: value ? checkedBoxDecoration : uncheckedBoxDecoration, child: value ? Icon( Icons.check, - color: Colors.blue, + color: widget.iconColor ?? Colors.blue, size: 20.0, ) : Offstage(), From b536973077b27058126af54f930d1c3cf93f5013 Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 12 Dec 2022 00:07:05 +0200 Subject: [PATCH 143/203] make checkbox stateless --- .../dashboard/widgets/filter_widget.dart | 2 +- lib/src/screens/exchange/exchange_page.dart | 8 ----- lib/src/widgets/standard_checkbox.dart | 34 ++++--------------- .../dashboard/dashboard_view_model.dart | 6 ++-- 4 files changed, 11 insertions(+), 39 deletions(-) diff --git a/lib/src/screens/dashboard/widgets/filter_widget.dart b/lib/src/screens/dashboard/widgets/filter_widget.dart index a3172940f..411006633 100644 --- a/lib/src/screens/dashboard/widgets/filter_widget.dart +++ b/lib/src/screens/dashboard/widgets/filter_widget.dart @@ -103,7 +103,7 @@ class FilterWidget extends StatelessWidget { gradientBackground: true, borderColor: Theme.of(context).dividerColor, iconColor: Colors.white, - onChanged: (bool val){}, + onChanged: (value) => item.onChanged(), )) : GestureDetector( onTap: () async { diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 744848156..7b73a134b 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -40,7 +40,6 @@ class ExchangePage extends BasePage { final ExchangeViewModel exchangeViewModel; final depositKey = GlobalKey(); final receiveKey = GlobalKey(); - final checkBoxKey = GlobalKey(); final _formKey = GlobalKey(); final _depositAmountFocus = FocusNode(); final _depositAddressFocus = FocusNode(); @@ -339,7 +338,6 @@ class ExchangePage extends BasePage { mainAxisAlignment: MainAxisAlignment.start, children: [ StandardCheckbox( - key: checkBoxKey, value: exchangeViewModel.isFixedRateMode, caption: S.of(context).fixed_rate, onChanged: (value) => @@ -682,12 +680,6 @@ class ExchangePage extends BasePage { } }); - reaction((_) => exchangeViewModel.isFixedRateMode, (bool value) { - if (checkBoxKey.currentState!.value != exchangeViewModel.isFixedRateMode) { - checkBoxKey.currentState!.value = exchangeViewModel.isFixedRateMode; - } - }); - depositAddressController.addListener( () => exchangeViewModel.depositAddress = depositAddressController.text); diff --git a/lib/src/widgets/standard_checkbox.dart b/lib/src/widgets/standard_checkbox.dart index 9202ea7f5..d7b947a7e 100644 --- a/lib/src/widgets/standard_checkbox.dart +++ b/lib/src/widgets/standard_checkbox.dart @@ -2,16 +2,14 @@ import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -class StandardCheckbox extends StatefulWidget { +class StandardCheckbox extends StatelessWidget { StandardCheckbox({ - Key? key, required this.value, this.caption = '', this.gradientBackground = false, this.borderColor, this.iconColor, - required this.onChanged}) - : super(key: key); + required this.onChanged}); final bool value; final String caption; @@ -20,21 +18,7 @@ class StandardCheckbox extends StatefulWidget { final Color? iconColor; final Function(bool) onChanged; - @override - StandardCheckboxState createState() => - StandardCheckboxState(value, caption, onChanged); -} -class StandardCheckboxState extends State { - StandardCheckboxState(this.value, this.caption, this.onChanged); - - bool value; - String caption; - Function(bool) onChanged; - - void changeValue(bool newValue) { - setState(() => value = newValue); - } @override Widget build(BuildContext context) { @@ -45,7 +29,7 @@ class StandardCheckboxState extends State { ], begin: Alignment.centerLeft, end: Alignment.centerRight); final boxBorder = Border.all( - color: widget.borderColor ?? Theme.of(context) + color: borderColor ?? Theme.of(context) .primaryTextTheme .caption! .color!, @@ -53,8 +37,8 @@ class StandardCheckboxState extends State { final checkedBoxDecoration = BoxDecoration( - gradient: widget.gradientBackground ? baseGradient : null, - border: widget.gradientBackground ? null : boxBorder, + gradient: gradientBackground ? baseGradient : null, + border: gradientBackground ? null : boxBorder, borderRadius: BorderRadius.all( Radius.circular(8.0))); @@ -64,11 +48,7 @@ class StandardCheckboxState extends State { Radius.circular(8.0))); return GestureDetector( - onTap: () { - value = !value; - onChanged(value); - setState(() {}); - }, + onTap: () => onChanged(!value), child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, @@ -80,7 +60,7 @@ class StandardCheckboxState extends State { child: value ? Icon( Icons.check, - color: widget.iconColor ?? Colors.blue, + color: iconColor ?? Colors.blue, size: 20.0, ) : Offstage(), diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 40ea2d78b..ac38a43cc 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -61,15 +61,15 @@ abstract class DashboardViewModelBase with Store { FilterItem( value: transactionFilterStore.displayAll, caption: S.current.all_transactions, - onChanged: () => transactionFilterStore.toggleIAll()), + onChanged: transactionFilterStore.toggleIAll), FilterItem( value: transactionFilterStore.displayIncoming, caption: S.current.incoming, - onChanged: () => transactionFilterStore.toggleIncoming()), + onChanged:transactionFilterStore.toggleIncoming), FilterItem( value: transactionFilterStore.displayOutgoing, caption: S.current.outgoing, - onChanged: () => transactionFilterStore.toggleOutgoing()), + onChanged: transactionFilterStore.toggleOutgoing), // FilterItem( // value: () => false, // caption: S.current.transactions_by_date, From 7d08bb0e76265dd28c15d5877a20724895532093 Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 12 Dec 2022 00:37:03 +0200 Subject: [PATCH 144/203] Add SimpleSwap --- lib/view_model/dashboard/dashboard_view_model.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index ac38a43cc..ba0f9f8ff 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -91,6 +91,11 @@ abstract class DashboardViewModelBase with Store { caption: ExchangeProviderDescription.sideShift.title, onChanged: () => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.sideShift)), + FilterItem( + value: tradeFilterStore.displaySimpleSwap, + caption: ExchangeProviderDescription.simpleSwap.title, + onChanged: () => tradeFilterStore + .toggleDisplayExchange(ExchangeProviderDescription.simpleSwap)), ] }, subname = '', From b1120cf2f83a49a75b4d8ac9e8eb0a467ef3b94f Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 12 Dec 2022 14:01:37 +0200 Subject: [PATCH 145/203] fix filter for SideShift --- lib/store/dashboard/trade_filter_store.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/store/dashboard/trade_filter_store.dart b/lib/store/dashboard/trade_filter_store.dart index 4319c3bc7..9c1dc9a9a 100644 --- a/lib/store/dashboard/trade_filter_store.dart +++ b/lib/store/dashboard/trade_filter_store.dart @@ -79,6 +79,8 @@ abstract class TradeFilterStoreBase with Store { .where((item) => (displayXMRTO.value && item.trade.provider == ExchangeProviderDescription.xmrto) || + (displaySideShift.value && + item.trade.provider == ExchangeProviderDescription.sideShift) || (displayChangeNow.value && item.trade.provider == ExchangeProviderDescription.changeNow) || From 2da50776d16629d044211ced3a80456ca9f18c14 Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 12 Dec 2022 14:28:53 +0200 Subject: [PATCH 146/203] code formatting --- .../dashboard/widgets/filter_widget.dart | 198 ++++++++---------- .../exchange_trade/exchange_trade_page.dart | 4 +- .../order_details/order_details_page.dart | 6 +- .../widgets/settings_switcher_cell.dart | 4 +- .../trade_details/trade_details_page.dart | 14 +- .../transaction_details_page.dart | 6 +- .../unspent_coins_details_page.dart | 4 +- .../widgets/unspent_coins_switch_row.dart | 4 +- .../screens/wallet_keys/wallet_keys_page.dart | 4 +- lib/src/widgets/standard_checkbox.dart | 67 +++--- lib/src/widgets/standard_list.dart | 6 +- ...list_card.dart => standard_list_card.dart} | 4 +- ...t_list_row.dart => standard_list_row.dart} | 4 +- ...row.dart => standard_list_status_row.dart} | 4 +- ...ndart_switch.dart => standard_switch.dart} | 8 +- 15 files changed, 151 insertions(+), 186 deletions(-) rename lib/src/widgets/{standart_list_card.dart => standard_list_card.dart} (96%) rename lib/src/widgets/{standart_list_row.dart => standard_list_row.dart} (96%) rename lib/src/widgets/{standart_list_status_row.dart => standard_list_status_row.dart} (95%) rename lib/src/widgets/{standart_switch.dart => standard_switch.dart} (81%) diff --git a/lib/src/screens/dashboard/widgets/filter_widget.dart b/lib/src/screens/dashboard/widgets/filter_widget.dart index 411006633..6831819e4 100644 --- a/lib/src/screens/dashboard/widgets/filter_widget.dart +++ b/lib/src/screens/dashboard/widgets/filter_widget.dart @@ -15,8 +15,7 @@ class FilterWidget extends StatelessWidget { FilterWidget({required this.dashboardViewModel}); final DashboardViewModel dashboardViewModel; - final closeIcon = - Image.asset('assets/images/close.png', color: Palette.darkBlueCraiola); + final closeIcon = Image.asset('assets/images/close.png', color: Palette.darkBlueCraiola); @override Widget build(BuildContext context) { @@ -33,71 +32,55 @@ class FilterWidget extends StatelessWidget { child: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(24)), child: Container( - color: Theme.of(context) - .textTheme! - .bodyText1! - .decorationColor!, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: EdgeInsets.all(24.0), - child: Text( - S.of(context).filters, - style: TextStyle( - color: Theme.of(context).primaryTextTheme - .overline!.color!, - fontSize: 16, - fontFamily: 'Lato', - decoration: TextDecoration.none, - ), - ), + color: Theme.of(context).textTheme!.bodyText1!.decorationColor!, + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Padding( + padding: EdgeInsets.all(24.0), + child: Text( + S.of(context).filters, + style: TextStyle( + color: Theme.of(context).primaryTextTheme.overline!.color!, + fontSize: 16, + fontFamily: 'Lato', + decoration: TextDecoration.none, ), - sectionDivider, - ListView.separated( - padding: EdgeInsets.zero, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: dashboardViewModel.filterItems.length, - separatorBuilder: (context, _) => sectionDivider, - itemBuilder: (_, index1) { - final title = dashboardViewModel.filterItems.keys - .elementAt(index1); - final section = dashboardViewModel - .filterItems.values - .elementAt(index1); - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: EdgeInsets.only( - top: 20, left: 24, right: 24), - child: Text( - title, - style: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .headline6! - .color!, - fontSize: 16, - fontFamily: 'Lato', - fontWeight: FontWeight.bold, - decoration: TextDecoration.none), - ), - ), - ListView.builder( - padding: - EdgeInsets.symmetric(vertical: 8.0), - shrinkWrap: true, - physics: - const NeverScrollableScrollPhysics(), - itemCount: section.length, - itemBuilder: (_, index2) { - final item = section[index2]; - final content = item.onChanged != null - ? Observer( - builder: (_) => - StandardCheckbox( + ), + ), + sectionDivider, + ListView.separated( + padding: EdgeInsets.zero, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: dashboardViewModel.filterItems.length, + separatorBuilder: (context, _) => sectionDivider, + itemBuilder: (_, index1) { + final title = dashboardViewModel.filterItems.keys.elementAt(index1); + final section = dashboardViewModel.filterItems.values.elementAt(index1); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(top: 20, left: 24, right: 24), + child: Text( + title, + style: TextStyle( + color: Theme.of(context).primaryTextTheme!.headline6!.color!, + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.bold, + decoration: TextDecoration.none), + ), + ), + ListView.builder( + padding: EdgeInsets.symmetric(vertical: 8.0), + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: section.length, + itemBuilder: (_, index2) { + final item = section[index2]; + final content = item.onChanged != null + ? Observer( + builder: (_) => StandardCheckbox( value: item.value.value, caption: item.caption, gradientBackground: true, @@ -105,51 +88,48 @@ class FilterWidget extends StatelessWidget { iconColor: Colors.white, onChanged: (value) => item.onChanged(), )) - : GestureDetector( - onTap: () async { - //final List picked = - //await date_rage_picker.showDatePicker( - // context: context, - // initialFirstDate: DateTime.now() - // .subtract(Duration(days: 1)), - // initialLastDate: (DateTime.now()), - // firstDate: DateTime(2015), - // lastDate: DateTime.now() - // .add(Duration(days: 1))); + : GestureDetector( + onTap: () async { + //final List picked = + //await date_rage_picker.showDatePicker( + // context: context, + // initialFirstDate: DateTime.now() + // .subtract(Duration(days: 1)), + // initialLastDate: (DateTime.now()), + // firstDate: DateTime(2015), + // lastDate: DateTime.now() + // .add(Duration(days: 1))); - //if (picked != null && picked.length == 2) { - // dashboardViewModel.transactionFilterStore - // .changeStartDate(picked.first); - // dashboardViewModel.transactionFilterStore - // .changeEndDate(picked.last); - //} - }, - child: Padding( - padding: - EdgeInsets.only(left: 32), - child: Text( - item.caption, - style: TextStyle( - color: Colors.red, - //Theme.of(context).primaryTextTheme.title.color,// - fontSize: 18, - fontFamily: 'Lato', - fontWeight: - FontWeight.w500, - decoration: - TextDecoration.none), + //if (picked != null && picked.length == 2) { + // dashboardViewModel.transactionFilterStore + // .changeStartDate(picked.first); + // dashboardViewModel.transactionFilterStore + // .changeEndDate(picked.last); + //} + }, + child: Padding( + padding: EdgeInsets.only(left: 32), + child: Text( + item.caption, + style: TextStyle( + color: Colors.red, + //Theme.of(context).primaryTextTheme.title.color,// + fontSize: 18, + fontFamily: 'Lato', + fontWeight: FontWeight.w500, + decoration: TextDecoration.none), + ), ), - ), - ); + ); - return FilterTile(child: content); - }, - ) - ], - ); - }, - ), - ]), + return FilterTile(child: content); + }, + ) + ], + ); + }, + ), + ]), ), ), ), @@ -172,4 +152,4 @@ class SectionDivider extends StatelessWidget { color: Theme.of(context).dividerColor, ); } -} \ No newline at end of file +} diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index 7c9fc1be7..e3eb8db96 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -8,7 +8,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart'; import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart'; -import 'package:cake_wallet/src/widgets/standart_list_row.dart'; +import 'package:cake_wallet/src/widgets/standard_list_row.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart'; @@ -194,7 +194,7 @@ class ExchangeTradeState extends State { final item = widget.exchangeTradeViewModel.items[index]; final value = item.data ?? fetchingLabel; - final content = StandartListRow( + final content = AnotherStandardListRow( title: item.title, value: value, valueFontSize: 14, diff --git a/lib/src/screens/order_details/order_details_page.dart b/lib/src/screens/order_details/order_details_page.dart index 2e6ece509..a7eff99b8 100644 --- a/lib/src/screens/order_details/order_details_page.dart +++ b/lib/src/screens/order_details/order_details_page.dart @@ -7,7 +7,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/standart_list_row.dart'; +import 'package:cake_wallet/src/widgets/standard_list_row.dart'; import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart'; class OrderDetailsPage extends BasePage { @@ -57,7 +57,7 @@ class OrderDetailsPageBodyState extends State { if (item is TrackTradeListItem) { return GestureDetector( onTap: item.onTap, - child: StandartListRow( + child: AnotherStandardListRow( title: '${item.title}', value: '${item.value}')); } else { return GestureDetector( @@ -65,7 +65,7 @@ class OrderDetailsPageBodyState extends State { Clipboard.setData(ClipboardData(text: '${item.value}')); showBar(context, S.of(context).copied_to_clipboard); }, - child: StandartListRow( + child: AnotherStandardListRow( title: '${item.title}', value: '${item.value}')); } }); diff --git a/lib/src/screens/settings/widgets/settings_switcher_cell.dart b/lib/src/screens/settings/widgets/settings_switcher_cell.dart index fc99f3297..c1d7fa150 100644 --- a/lib/src/screens/settings/widgets/settings_switcher_cell.dart +++ b/lib/src/screens/settings/widgets/settings_switcher_cell.dart @@ -1,6 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; -import 'package:cake_wallet/src/widgets/standart_switch.dart'; +import 'package:cake_wallet/src/widgets/standard_switch.dart'; class SettingsSwitcherCell extends StandardListRow { SettingsSwitcherCell( @@ -11,6 +11,6 @@ class SettingsSwitcherCell extends StandardListRow { final void Function(BuildContext context, bool value)? onValueChange; @override - Widget buildTrailing(BuildContext context) => StandartSwitch( + Widget buildTrailing(BuildContext context) => StandardSwitch( value: value, onTaped: () => onValueChange?.call(context, !value)); } diff --git a/lib/src/screens/trade_details/trade_details_page.dart b/lib/src/screens/trade_details/trade_details_page.dart index 500d16beb..1bb5d3ec8 100644 --- a/lib/src/screens/trade_details/trade_details_page.dart +++ b/lib/src/screens/trade_details/trade_details_page.dart @@ -1,6 +1,6 @@ import 'package:cake_wallet/src/widgets/standard_list.dart'; -import 'package:cake_wallet/src/widgets/standart_list_card.dart'; -import 'package:cake_wallet/src/widgets/standart_list_status_row.dart'; +import 'package:cake_wallet/src/widgets/standard_list_card.dart'; +import 'package:cake_wallet/src/widgets/standard_list_status_row.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/view_model/trade_details_view_model.dart'; import 'package:flutter/material.dart'; @@ -9,7 +9,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/standart_list_row.dart'; +import 'package:cake_wallet/src/widgets/standard_list_row.dart'; import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart'; import 'package:cake_wallet/src/screens/trade_details/trade_details_list_card.dart'; import 'package:cake_wallet/src/screens/trade_details/trade_details_status_item.dart'; @@ -62,18 +62,18 @@ class TradeDetailsPageBodyState extends State { if (item is TrackTradeListItem) { return GestureDetector( onTap: item.onTap, - child: StandartListRow( + child: AnotherStandardListRow( title: '${item.title}', value: '${item.value}')); } if (item is DetailsListStatusItem) { - return StandartListStatusRow( + return StandardListStatusRow( title: item.title, value: item.value); } if (item is TradeDetailsListCardItem) { - return TradeDatailsStandartListCard( + return TradeDetailsStandardListCard( id: item.id, create: item.createdAt, pair: item.pair, @@ -86,7 +86,7 @@ class TradeDetailsPageBodyState extends State { Clipboard.setData(ClipboardData(text: '${item.value}')); showBar(context, S.of(context).copied_to_clipboard); }, - child: StandartListRow( + child: AnotherStandardListRow( title: '${item.title}', value: '${item.value}')); }); }); diff --git a/lib/src/screens/transaction_details/transaction_details_page.dart b/lib/src/screens/transaction_details/transaction_details_page.dart index 098d65c23..8d3ae8c9e 100644 --- a/lib/src/screens/transaction_details/transaction_details_page.dart +++ b/lib/src/screens/transaction_details/transaction_details_page.dart @@ -6,7 +6,7 @@ import 'package:cake_wallet/view_model/transaction_details_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/widgets/standart_list_row.dart'; +import 'package:cake_wallet/src/widgets/standard_list_row.dart'; import 'package:cake_wallet/src/screens/transaction_details/blockexplorer_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -42,7 +42,7 @@ class TransactionDetailsPage extends BasePage { S.of(context).transaction_details_copied(item.title)); }, child: - StandartListRow(title: '${item.title}:', value: item.value), + AnotherStandardListRow(title: '${item.title}:', value: item.value), ); } @@ -50,7 +50,7 @@ class TransactionDetailsPage extends BasePage { return GestureDetector( onTap: item.onTap, child: - StandartListRow(title: '${item.title}:', value: item.value), + AnotherStandardListRow(title: '${item.title}:', value: item.value), ); } diff --git a/lib/src/screens/unspent_coins/unspent_coins_details_page.dart b/lib/src/screens/unspent_coins/unspent_coins_details_page.dart index b1c4ff01b..74fbcfdd9 100644 --- a/lib/src/screens/unspent_coins/unspent_coins_details_page.dart +++ b/lib/src/screens/unspent_coins/unspent_coins_details_page.dart @@ -5,7 +5,7 @@ import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_details_view_model.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_switch_item.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/src/widgets/standart_list_row.dart'; +import 'package:cake_wallet/src/widgets/standard_list_row.dart'; import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -30,7 +30,7 @@ class UnspentCoinsDetailsPage extends BasePage { final item = unspentCoinsDetailsViewModel.items[index]; if (item is StandartListItem) { - return StandartListRow( + return AnotherStandardListRow( title: '${item.title}:', value: item.value); } diff --git a/lib/src/screens/unspent_coins/widgets/unspent_coins_switch_row.dart b/lib/src/screens/unspent_coins/widgets/unspent_coins_switch_row.dart index 6272469df..734aeb7ee 100644 --- a/lib/src/screens/unspent_coins/widgets/unspent_coins_switch_row.dart +++ b/lib/src/screens/unspent_coins/widgets/unspent_coins_switch_row.dart @@ -1,4 +1,4 @@ -import 'package:cake_wallet/src/widgets/standart_switch.dart'; +import 'package:cake_wallet/src/widgets/standard_switch.dart'; import 'package:flutter/material.dart'; class UnspentCoinsSwitchRow extends StatelessWidget { @@ -33,7 +33,7 @@ class UnspentCoinsSwitchRow extends StatelessWidget { textAlign: TextAlign.left), Padding( padding: EdgeInsets.only(top: 12), - child: StandartSwitch( + child: StandardSwitch( value: switchValue, onTaped: () => onSwitchValueChange(!switchValue)) ) diff --git a/lib/src/screens/wallet_keys/wallet_keys_page.dart b/lib/src/screens/wallet_keys/wallet_keys_page.dart index 942809ac8..f97200e1e 100644 --- a/lib/src/screens/wallet_keys/wallet_keys_page.dart +++ b/lib/src/screens/wallet_keys/wallet_keys_page.dart @@ -6,7 +6,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/standart_list_row.dart'; +import 'package:cake_wallet/src/widgets/standard_list_row.dart'; import 'package:cake_wallet/view_model/wallet_keys_view_model.dart'; class WalletKeysPage extends BasePage { @@ -71,7 +71,7 @@ class WalletKeysPage extends BasePage { Clipboard.setData(ClipboardData(text: item.value)); showBar(context, S.of(context).copied_key_to_clipboard(item.title)); }, - child: StandartListRow( + child: AnotherStandardListRow( title: item.title + ':', value: item.value, ), diff --git a/lib/src/widgets/standard_checkbox.dart b/lib/src/widgets/standard_checkbox.dart index d7b947a7e..d2cd6463d 100644 --- a/lib/src/widgets/standard_checkbox.dart +++ b/lib/src/widgets/standard_checkbox.dart @@ -3,13 +3,13 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class StandardCheckbox extends StatelessWidget { - StandardCheckbox({ - required this.value, - this.caption = '', - this.gradientBackground = false, - this.borderColor, - this.iconColor, - required this.onChanged}); + StandardCheckbox( + {required this.value, + this.caption = '', + this.gradientBackground = false, + this.borderColor, + this.iconColor, + required this.onChanged}); final bool value; final String caption; @@ -18,34 +18,23 @@ class StandardCheckbox extends StatelessWidget { final Color? iconColor; final Function(bool) onChanged; - - @override Widget build(BuildContext context) { - final baseGradient = LinearGradient(colors: [ Theme.of(context).primaryTextTheme.subtitle1!.color!, Theme.of(context).primaryTextTheme.subtitle1!.decorationColor!, ], begin: Alignment.centerLeft, end: Alignment.centerRight); final boxBorder = Border.all( - color: borderColor ?? Theme.of(context) - .primaryTextTheme - .caption! - .color!, - width: 1.0); - + color: borderColor ?? Theme.of(context).primaryTextTheme.caption!.color!, width: 1.0); final checkedBoxDecoration = BoxDecoration( gradient: gradientBackground ? baseGradient : null, border: gradientBackground ? null : boxBorder, - borderRadius: BorderRadius.all( - Radius.circular(8.0))); + borderRadius: BorderRadius.all(Radius.circular(8.0))); - final uncheckedBoxDecoration = BoxDecoration( - border: boxBorder, - borderRadius: BorderRadius.all( - Radius.circular(8.0))); + final uncheckedBoxDecoration = + BoxDecoration(border: boxBorder, borderRadius: BorderRadius.all(Radius.circular(8.0))); return GestureDetector( onTap: () => onChanged(!value), @@ -58,27 +47,23 @@ class StandardCheckbox extends StatelessWidget { width: 24.0, decoration: value ? checkedBoxDecoration : uncheckedBoxDecoration, child: value - ? Icon( - Icons.check, - color: iconColor ?? Colors.blue, - size: 20.0, - ) - : Offstage(), + ? Icon( + Icons.check, + color: iconColor ?? Colors.blue, + size: 20.0, + ) + : Offstage(), ), - if (caption.isNotEmpty) Padding( - padding: EdgeInsets.only(left: 10), - child: Text( - caption, - style: TextStyle( - fontSize: 16.0, - color: Theme.of(context) - .primaryTextTheme! - .headline6! - .color!), - ) - ) + if (caption.isNotEmpty) + Padding( + padding: EdgeInsets.only(left: 10), + child: Text( + caption, + style: TextStyle( + fontSize: 16.0, color: Theme.of(context).primaryTextTheme!.headline6!.color!), + )) ], ), ); } -} \ No newline at end of file +} diff --git a/lib/src/widgets/standard_list.dart b/lib/src/widgets/standard_list.dart index f5abdd900..680cf6edd 100644 --- a/lib/src/widgets/standard_list.dart +++ b/lib/src/widgets/standard_list.dart @@ -1,6 +1,6 @@ import 'package:cake_wallet/palette.dart'; -import 'package:cake_wallet/src/widgets/standart_list_card.dart'; -import 'package:cake_wallet/src/widgets/standart_list_status_row.dart'; +import 'package:cake_wallet/src/widgets/standard_list_card.dart'; +import 'package:cake_wallet/src/widgets/standard_list_status_row.dart'; import 'package:flutter/material.dart'; class StandardListRow extends StatelessWidget { @@ -217,7 +217,7 @@ class SectionStandardList extends StatelessWidget { return Container(); } - if (row is StandartListStatusRow || row is TradeDatailsStandartListCard) { + if (row is StandardListStatusRow || row is TradeDetailsStandardListCard) { return Container(); } diff --git a/lib/src/widgets/standart_list_card.dart b/lib/src/widgets/standard_list_card.dart similarity index 96% rename from lib/src/widgets/standart_list_card.dart rename to lib/src/widgets/standard_list_card.dart index 569a4e51f..7b2ecc2ce 100644 --- a/lib/src/widgets/standart_list_card.dart +++ b/lib/src/widgets/standard_list_card.dart @@ -2,8 +2,8 @@ import 'package:cake_wallet/palette.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/themes/theme_base.dart'; -class TradeDatailsStandartListCard extends StatelessWidget { - TradeDatailsStandartListCard( +class TradeDetailsStandardListCard extends StatelessWidget { + TradeDetailsStandardListCard( {required this.id, required this.create, required this.pair, diff --git a/lib/src/widgets/standart_list_row.dart b/lib/src/widgets/standard_list_row.dart similarity index 96% rename from lib/src/widgets/standart_list_row.dart rename to lib/src/widgets/standard_list_row.dart index 94a4c4c76..e174acc50 100644 --- a/lib/src/widgets/standart_list_row.dart +++ b/lib/src/widgets/standard_list_row.dart @@ -1,8 +1,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -class StandartListRow extends StatelessWidget { - StandartListRow( +class AnotherStandardListRow extends StatelessWidget { + AnotherStandardListRow( {required this.title, required this.value, this.titleFontSize = 14, diff --git a/lib/src/widgets/standart_list_status_row.dart b/lib/src/widgets/standard_list_status_row.dart similarity index 95% rename from lib/src/widgets/standart_list_status_row.dart rename to lib/src/widgets/standard_list_status_row.dart index d97c4f688..f958e83ae 100644 --- a/lib/src/widgets/standart_list_status_row.dart +++ b/lib/src/widgets/standard_list_status_row.dart @@ -3,8 +3,8 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.da import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -class StandartListStatusRow extends StatelessWidget { - StandartListStatusRow({required this.title, required this.value}); +class StandardListStatusRow extends StatelessWidget { + StandardListStatusRow({required this.title, required this.value}); final String title; final String value; diff --git a/lib/src/widgets/standart_switch.dart b/lib/src/widgets/standard_switch.dart similarity index 81% rename from lib/src/widgets/standart_switch.dart rename to lib/src/widgets/standard_switch.dart index 3018fb5b4..929286058 100644 --- a/lib/src/widgets/standart_switch.dart +++ b/lib/src/widgets/standard_switch.dart @@ -1,17 +1,17 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -class StandartSwitch extends StatefulWidget { - const StandartSwitch({required this.value, required this.onTaped}); +class StandardSwitch extends StatefulWidget { + const StandardSwitch({required this.value, required this.onTaped}); final bool value; final VoidCallback onTaped; @override - StandartSwitchState createState() => StandartSwitchState(); + StandardSwitchState createState() => StandardSwitchState(); } -class StandartSwitchState extends State { +class StandardSwitchState extends State { @override Widget build(BuildContext context) { return GestureDetector( From 826ae46b072cde306e6f1f88287cc98c8a5e09a2 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Mon, 12 Dec 2022 18:01:42 +0200 Subject: [PATCH 147/203] - Fix not filling fiat amount - Fix conflicts with master --- lib/src/screens/send/send_page.dart | 3 +-- lib/src/screens/send/widgets/send_card.dart | 14 ++++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index c3f5f24c4..2cd849f34 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -29,12 +29,11 @@ class SendPage extends BasePage { SendPage({ required this.sendViewModel, this.initialPaymentRequest, - }) : _formKey = GlobalKey(),fiatFromSettings = settingsViewModel.fiatCurrency; + }) : _formKey = GlobalKey(); final SendViewModel sendViewModel; final GlobalKey _formKey; final controller = PageController(initialPage: 0); - final FiatCurrency fiatFromSettings; final PaymentRequest? initialPaymentRequest; bool _effectsInstalled = false; diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 41045b451..3be56d409 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -43,8 +43,8 @@ class SendCardState extends State required this.output, required this.sendViewModel, this.initialPaymentRequest}) - : addressController = TextEditingController(text: initialPaymentRequest?.address.toLowerCase()), - cryptoAmountController = TextEditingController(text: initialPaymentRequest?.amount), + : addressController = TextEditingController(), + cryptoAmountController = TextEditingController(), fiatAmountController = TextEditingController(), noteController = TextEditingController(), extractedAddressController = TextEditingController(), @@ -545,8 +545,7 @@ class SendCardState extends State if (output.address.isNotEmpty) { addressController.text = output.address; } - if (output.cryptoAmount.isNotEmpty || - sendViewModel.walletCurrencyName != initialPaymentRequest?.scheme.toLowerCase()) { + if (output.cryptoAmount.isNotEmpty) { cryptoAmountController.text = output.cryptoAmount; } fiatAmountController.text = output.fiatAmount; @@ -640,6 +639,13 @@ class SendCardState extends State extractedAddressController.text = extractedAddress; }); + if (initialPaymentRequest != null && + sendViewModel.walletCurrencyName != initialPaymentRequest!.scheme.toLowerCase()) { + addressController.text = initialPaymentRequest!.address; + cryptoAmountController.text = initialPaymentRequest!.amount; + noteController.text = initialPaymentRequest!.note; + } + _effectsInstalled = true; } From b5ba26adcdc953e1b078799feaa7e7c9ba0df5b3 Mon Sep 17 00:00:00 2001 From: Justin Ehrenhofer Date: Mon, 12 Dec 2022 10:07:37 -0600 Subject: [PATCH 148/203] [CW-276] Privacy settings icon, name, and position --- assets/images/2.0x/privacy_menu.png | Bin 0 -> 1324 bytes assets/images/3.0x/privacy_menu.png | Bin 0 -> 1954 bytes assets/images/privacy_menu.png | Bin 0 -> 548 bytes lib/src/screens/dashboard/wallet_menu.dart | 14 +++++++------- 4 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 assets/images/2.0x/privacy_menu.png create mode 100644 assets/images/3.0x/privacy_menu.png create mode 100644 assets/images/privacy_menu.png diff --git a/assets/images/2.0x/privacy_menu.png b/assets/images/2.0x/privacy_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..488fad1cca5a7d5e970e681895733e9bc69af5b9 GIT binary patch literal 1324 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 m>ksf3{cF&#eqbNVW_to~MWELdBsJs!0000 Navigator.of(context).pushNamed(Routes.addressBook), ), + WalletMenuItem( + title: S.current.privacy_settings, + image: + Image.asset('assets/images/privacy_menu.png', height: 16, width: 16), + handler: () { + Navigator.of(context).pushNamed(Routes.privacyPage); + }), WalletMenuItem( title: S.current.display_settings, image: Image.asset('assets/images/eye_menu.png', From 6c9f9a4d19025c432643610e6da3d9ce424ebc87 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Mon, 12 Dec 2022 19:30:48 +0100 Subject: [PATCH 149/203] [skip ci] fix issue with nullable field in Node adapter --- cw_core/lib/node.dart | 2 +- cw_haven/lib/haven_wallet.dart | 2 +- cw_monero/lib/monero_wallet.dart | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index ff1d6b051..325650224 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -54,7 +54,7 @@ class Node extends HiveObject with Keyable { bool? useSSL; @HiveField(5) - bool trusted; + bool? trusted; bool get isSSL => useSSL ?? false; diff --git a/cw_haven/lib/haven_wallet.dart b/cw_haven/lib/haven_wallet.dart index a4b949d8f..237722cbc 100644 --- a/cw_haven/lib/haven_wallet.dart +++ b/cw_haven/lib/haven_wallet.dart @@ -122,7 +122,7 @@ abstract class HavenWalletBase extends WalletBase Date: Mon, 12 Dec 2022 12:51:28 -0600 Subject: [PATCH 150/203] Move address book above security settings in menu --- lib/src/screens/dashboard/wallet_menu.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/src/screens/dashboard/wallet_menu.dart b/lib/src/screens/dashboard/wallet_menu.dart index 76f87c485..1638c0bc4 100644 --- a/lib/src/screens/dashboard/wallet_menu.dart +++ b/lib/src/screens/dashboard/wallet_menu.dart @@ -21,6 +21,12 @@ class WalletMenu { height: 16, width: 16), handler: () => Navigator.of(context).pushNamed(Routes.walletList), ), + WalletMenuItem( + title: S.current.address_book_menu, + image: Image.asset('assets/images/open_book_menu.png', + height: 16, width: 16), + handler: () => Navigator.of(context).pushNamed(Routes.addressBook), + ), WalletMenuItem( title: S.current.security_and_backup, image: @@ -28,12 +34,6 @@ class WalletMenu { handler: () { Navigator.of(context).pushNamed(Routes.securityBackupPage); }), - WalletMenuItem( - title: S.current.address_book_menu, - image: Image.asset('assets/images/open_book_menu.png', - height: 16, width: 16), - handler: () => Navigator.of(context).pushNamed(Routes.addressBook), - ), WalletMenuItem( title: S.current.privacy_settings, image: From 9ce6c6e01a279e3d1afb4a6f8eea6bdea1220c79 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Mon, 12 Dec 2022 20:34:45 +0100 Subject: [PATCH 151/203] set default value to nullable field --- cw_core/lib/node.dart | 4 ++-- cw_haven/lib/haven_wallet.dart | 2 +- cw_monero/lib/monero_wallet.dart | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 325650224..1322c5b78 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -53,8 +53,8 @@ class Node extends HiveObject with Keyable { @HiveField(4) bool? useSSL; - @HiveField(5) - bool? trusted; + @HiveField(5, defaultValue: false) + bool trusted; bool get isSSL => useSSL ?? false; diff --git a/cw_haven/lib/haven_wallet.dart b/cw_haven/lib/haven_wallet.dart index 237722cbc..a4b949d8f 100644 --- a/cw_haven/lib/haven_wallet.dart +++ b/cw_haven/lib/haven_wallet.dart @@ -122,7 +122,7 @@ abstract class HavenWalletBase extends WalletBase Date: Mon, 12 Dec 2022 22:16:46 +0200 Subject: [PATCH 152/203] Fix fill data condition --- lib/src/screens/send/widgets/send_card.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 3be56d409..082067d95 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -640,7 +640,7 @@ class SendCardState extends State }); if (initialPaymentRequest != null && - sendViewModel.walletCurrencyName != initialPaymentRequest!.scheme.toLowerCase()) { + sendViewModel.walletCurrencyName == initialPaymentRequest!.scheme.toLowerCase()) { addressController.text = initialPaymentRequest!.address; cryptoAmountController.text = initialPaymentRequest!.amount; noteController.text = initialPaymentRequest!.note; From f15bc2821960d6d780d11dec793aa115abda90ed Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Tue, 13 Dec 2022 16:19:31 +0100 Subject: [PATCH 153/203] [skip ci] fix issues from code review --- lib/core/auth_service.dart | 9 ++- lib/di.dart | 10 ++- lib/main.dart | 3 + .../settings/security_backup_page.dart | 62 +++++++++---------- lib/store/settings_store.dart | 9 +-- .../wallet_list/wallet_list_view_model.dart | 32 ++++++---- 6 files changed, 73 insertions(+), 52 deletions(-) diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index 569db5700..54f89437a 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -8,10 +8,15 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/store/settings_store.dart'; class AuthService with Store { - AuthService({required this.secureStorage, required this.sharedPreferences}); + AuthService({ + required this.secureStorage, + required this.sharedPreferences, + required this.settingsStore, + }); final FlutterSecureStorage secureStorage; final SharedPreferences sharedPreferences; + final SettingsStore settingsStore; Future setPassword(String password) async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); @@ -49,7 +54,7 @@ class AuthService with Store { bool requireAuth() { final timestamp = sharedPreferences.getInt(PreferencesKey.lastAuthTimeMilliseconds); final duration = _durationToRequireAuth(timestamp ?? 0); - final requiredPinInterval = getIt.get().pinTimeOutDuration; + final requiredPinInterval = settingsStore.pinTimeOutDuration; return duration >= requiredPinInterval.value; } diff --git a/lib/di.dart b/lib/di.dart index b506700f3..aa6514f0e 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -308,7 +308,10 @@ Future setup( getIt.registerFactory(() => AuthService( secureStorage: getIt.get(), - sharedPreferences: getIt.get())); + sharedPreferences: getIt.get(), + settingsStore: getIt.get(), + ), + ); getIt.registerFactory(() => AuthViewModel( getIt.get(), @@ -393,7 +396,10 @@ Future setup( getIt.registerFactory(() => WalletListViewModel( _walletInfoSource, getIt.get(), - getIt.get())); + getIt.get(), + getIt.get(), + ), + ); getIt.registerFactory(() => WalletListPage(walletListViewModel: getIt.get())); diff --git a/lib/main.dart b/lib/main.dart index 11eee146b..ccabf84fe 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/language_service.dart'; import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/ionia/ionia_category.dart'; @@ -257,6 +258,7 @@ class AppState extends State with SingleTickerProviderStateMixin { Widget build(BuildContext context) { return Observer(builder: (BuildContext context) { final appStore = getIt.get(); + final authService = getIt.get(); final settingsStore = appStore.settingsStore; final statusBarColor = Colors.transparent; final authenticationStore = getIt.get(); @@ -281,6 +283,7 @@ class AppState extends State with SingleTickerProviderStateMixin { appStore: appStore, authenticationStore: authenticationStore, navigatorKey: navigatorKey, + authService: authService, child: MaterialApp( navigatorKey: navigatorKey, debugShowCheckedModeBanner: false, diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index 7040816d9..102a94b36 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -62,40 +62,38 @@ class SecurityBackupPage extends BasePage { })), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), Observer(builder: (_) { - return Column( - children: [ - SettingsSwitcherCell( - title: S.current.settings_allow_biometrical_authentication, - value: _securitySettingsViewModel.allowBiometricalAuthentication, - onValueChange: (BuildContext context, bool value) { - if (value) { - Navigator.of(context).pushNamed(Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { - if (isAuthenticatedSuccessfully) { - if (await _securitySettingsViewModel.biometricAuthenticated()) { - _securitySettingsViewModel - .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); - } - } else { - _securitySettingsViewModel - .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); - } - - auth.close(); - }); + return SettingsSwitcherCell( + title: S.current.settings_allow_biometrical_authentication, + value: _securitySettingsViewModel.allowBiometricalAuthentication, + onValueChange: (BuildContext context, bool value) { + if (value) { + Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { + if (isAuthenticatedSuccessfully) { + if (await _securitySettingsViewModel.biometricAuthenticated()) { + _securitySettingsViewModel + .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); + } } else { - _securitySettingsViewModel.setAllowBiometricalAuthentication(value); + _securitySettingsViewModel + .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); } - }), - SettingsPickerCell( - title: S.current.require_pin_after, - items: PinCodeRequiredDuration.values, - selectedItem: _securitySettingsViewModel.pinCodeRequiredDuration, - onItemSelected: (PinCodeRequiredDuration code) { - _securitySettingsViewModel.setPinCodeRequiredDuration(code); - }, - ), - ], + + auth.close(); + }); + } else { + _securitySettingsViewModel.setAllowBiometricalAuthentication(value); + } + }); + }), + Observer(builder: (_) { + return SettingsPickerCell( + title: S.current.require_pin_after, + items: PinCodeRequiredDuration.values, + selectedItem: _securitySettingsViewModel.pinCodeRequiredDuration, + onItemSelected: (PinCodeRequiredDuration code) { + _securitySettingsViewModel.setPinCodeRequiredDuration(code); + }, ); }), ]), diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 18379c466..b10e0d08d 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -18,7 +18,6 @@ import 'package:cw_core/node.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/entities/action_list_display_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; -import 'package:cake_wallet/.secrets.g.dart' as secrets; part 'settings_store.g.dart'; @@ -169,7 +168,7 @@ abstract class SettingsStoreBase with Store { static const defaultPinLength = 4; static const defaultActionsMode = 11; - static const defaultPinCodeTimeOutDuration = 10; + static const defaultPinCodeTimeOutDuration = PinCodeRequiredDuration.tenminutes; @observable FiatCurrency fiatCurrency; @@ -299,8 +298,10 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? defaultActionsMode)); var pinLength = sharedPreferences.getInt(PreferencesKey.currentPinLength); - final pinCodeTimeOutDuration = PinCodeRequiredDuration.deserialize(raw: sharedPreferences.getInt(PreferencesKey.pinTimeOutDuration) - ?? defaultPinCodeTimeOutDuration); + final timeOutDuration = sharedPreferences.getInt(PreferencesKey.pinTimeOutDuration); + final pinCodeTimeOutDuration = timeOutDuration != null + ? PinCodeRequiredDuration.deserialize(raw: timeOutDuration) + : defaultPinCodeTimeOutDuration; // If no value if (pinLength == null || pinLength == 0) { diff --git a/lib/view_model/wallet_list/wallet_list_view_model.dart b/lib/view_model/wallet_list/wallet_list_view_model.dart index 50908f24e..6d63675ba 100644 --- a/lib/view_model/wallet_list/wallet_list_view_model.dart +++ b/lib/view_model/wallet_list/wallet_list_view_model.dart @@ -15,9 +15,12 @@ part 'wallet_list_view_model.g.dart'; class WalletListViewModel = WalletListViewModelBase with _$WalletListViewModel; abstract class WalletListViewModelBase with Store { - WalletListViewModelBase(this._walletInfoSource, this._appStore, - this._walletLoadingService) - : wallets = ObservableList() { + WalletListViewModelBase( + this._walletInfoSource, + this._appStore, + this._walletLoadingService, + this._authService, + ) : wallets = ObservableList() { _updateList(); } @@ -27,6 +30,7 @@ abstract class WalletListViewModelBase with Store { final AppStore _appStore; final Box _walletInfoSource; final WalletLoadingService _walletLoadingService; + final AuthService _authService; WalletType get currentWalletType => _appStore.wallet!.type; @@ -47,16 +51,20 @@ abstract class WalletListViewModelBase with Store { void _updateList() { wallets.clear(); - wallets.addAll(_walletInfoSource.values.map((info) => WalletListItem( - name: info.name, - type: info.type, - key: info.key, - isCurrent: info.name == _appStore.wallet!.name && - info.type == _appStore.wallet!.type, - isEnabled: availableWalletTypes.contains(info.type)))); + wallets.addAll( + _walletInfoSource.values.map( + (info) => WalletListItem( + name: info.name, + type: info.type, + key: info.key, + isCurrent: info.name == _appStore.wallet!.name && info.type == _appStore.wallet!.type, + isEnabled: availableWalletTypes.contains(info.type), + ), + ), + ); } - bool checkIfAuthRequired(){ - return getIt.get().requireAuth(); + bool checkIfAuthRequired() { + return _authService.requireAuth(); } } From dbf214ee1bd7fc32f744eee24f142d5eb1598ea6 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Tue, 13 Dec 2022 18:26:25 +0100 Subject: [PATCH 154/203] [skip ci] fix issues from code review --- lib/ionia/ionia_gift_card.dart | 2 +- .../ionia/cards/ionia_more_options_page.dart | 13 ++++++------- .../ionia/ionia_custom_redeem_view_model.dart | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/ionia/ionia_gift_card.dart b/lib/ionia/ionia_gift_card.dart index 04b45b907..2ba0fd136 100644 --- a/lib/ionia/ionia_gift_card.dart +++ b/lib/ionia/ionia_gift_card.dart @@ -37,7 +37,7 @@ class IoniaGiftCard { purchaseAmount: element['PurchaseAmount'] as double, actualAmount: element['ActualAmount'] as double, totalTransactionAmount: element['TotalTransactionAmount'] as double, - totalDashTransactionAmount: element['TotalDashTransactionAmount'] != null ? element['TotalDashTransactionAmount'] as double : 0.0, + totalDashTransactionAmount: (element['TotalDashTransactionAmount'] as double?) ?? 0.0, remainingAmount: element['RemainingAmount'] as double, isActive: element['IsActive'] as bool, isEmpty: element['IsEmpty'] as bool, diff --git a/lib/src/screens/ionia/cards/ionia_more_options_page.dart b/lib/src/screens/ionia/cards/ionia_more_options_page.dart index facdfaf32..7d38c5e1e 100644 --- a/lib/src/screens/ionia/cards/ionia_more_options_page.dart +++ b/lib/src/screens/ionia/cards/ionia_more_options_page.dart @@ -31,15 +31,14 @@ class IoniaMoreOptionsPage extends BasePage { height: 10, ), Center( - child: Text( - S.of(context).choose_from_available_options, - style: textMedium( - color: Theme.of(context).primaryTextTheme.headline6!.color!, + child: Text( + S.of(context).choose_from_available_options, + style: textMedium( + color: Theme.of(context).primaryTextTheme.headline6!.color!, + ), ), - )), - SizedBox( - height: 40, ), + SizedBox(height: 40), InkWell( onTap: () async { final amount = await Navigator.of(context) diff --git a/lib/view_model/ionia/ionia_custom_redeem_view_model.dart b/lib/view_model/ionia/ionia_custom_redeem_view_model.dart index 6471c7378..5776443ee 100644 --- a/lib/view_model/ionia/ionia_custom_redeem_view_model.dart +++ b/lib/view_model/ionia/ionia_custom_redeem_view_model.dart @@ -35,7 +35,7 @@ abstract class IoniaCustomRedeemViewModelBase with Store { @action void updateAmount(String text) { - amount = text.isEmpty ? 0 : (double.parse(text.replaceAll(',', '.'))); + amount = double.tryParse(text.replaceAll(',', '.')) ?? 0; } @action From 8a126831374c4fa65de4c7e874968d6eb1095051 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 14 Dec 2022 17:19:45 +0200 Subject: [PATCH 155/203] - Update version to 4.5.3 for cakewallet; 1.2.2 for monero.com - Fix android script to injecting app details --- scripts/android/app_env.sh | 8 ++++---- scripts/android/inject_app_details.sh | 4 ++-- scripts/ios/app_env.sh | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index d361c8dfa..5b704eea1 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -14,14 +14,14 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.2.1" -MONERO_COM_BUILD_NUMBER=32 +MONERO_COM_VERSION="1.2.2" +MONERO_COM_BUILD_NUMBER=33 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.5.1" -CAKEWALLET_BUILD_NUMBER=136 +CAKEWALLET_VERSION="4.5.3" +CAKEWALLET_BUILD_NUMBER=138 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" diff --git a/scripts/android/inject_app_details.sh b/scripts/android/inject_app_details.sh index 6bcdf7239..c700a8c40 100755 --- a/scripts/android/inject_app_details.sh +++ b/scripts/android/inject_app_details.sh @@ -6,6 +6,6 @@ if [ -z "$APP_ANDROID_TYPE" ]; then fi cd ../.. -sed -i "0,/version:/{s/version:.*/version: ${APP_ANDROID_VERSION}+${APP_ANDROID_BUILD_NUMBER}/}" ./pubspec.yaml -sed -i "0,/version:/{s/__APP_PACKAGE__/${APP_ANDROID_PACKAGE}/}" ./android/app/src/main/AndroidManifest.xml +sed -i '' "1,/version:.*/s/version:.*/version: ${APP_ANDROID_VERSION}+${APP_ANDROID_BUILD_NUMBER}/" ./pubspec.yaml +sed -i '' "1,/__APP_PACKAGE__/s/__APP_PACKAGE__/${APP_ANDROID_PACKAGE}/" ./android/app/src/main/AndroidManifest.xml cd scripts/android \ No newline at end of file diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 8bb945680..fbf8233e5 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.2.1" -MONERO_COM_BUILD_NUMBER=29 +MONERO_COM_VERSION="1.2.2" +MONERO_COM_BUILD_NUMBER=30 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.5.1" -CAKEWALLET_BUILD_NUMBER=133 +CAKEWALLET_VERSION="4.5.3" +CAKEWALLET_BUILD_NUMBER=135 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" From de37b25f9265d52187b43d60f0a8704c22e7be25 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 14 Dec 2022 19:19:57 +0200 Subject: [PATCH 156/203] Revert script changes in injecting app details [skip ci] --- scripts/android/inject_app_details.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/android/inject_app_details.sh b/scripts/android/inject_app_details.sh index c700a8c40..15c39bca7 100755 --- a/scripts/android/inject_app_details.sh +++ b/scripts/android/inject_app_details.sh @@ -6,6 +6,6 @@ if [ -z "$APP_ANDROID_TYPE" ]; then fi cd ../.. -sed -i '' "1,/version:.*/s/version:.*/version: ${APP_ANDROID_VERSION}+${APP_ANDROID_BUILD_NUMBER}/" ./pubspec.yaml -sed -i '' "1,/__APP_PACKAGE__/s/__APP_PACKAGE__/${APP_ANDROID_PACKAGE}/" ./android/app/src/main/AndroidManifest.xml +sed -i "0,/version:/{s/version:.*/version: ${APP_ANDROID_VERSION}+${APP_ANDROID_BUILD_NUMBER}/}" ./pubspec.yaml +sed -i "0,/version:/{s/__APP_PACKAGE__/${APP_ANDROID_PACKAGE}/}" ./android/app/src/main/AndroidManifest.xml cd scripts/android \ No newline at end of file From b4aff6746739f71464f9d2985f4a9b1e54e5e5f4 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Wed, 14 Dec 2022 19:21:51 +0200 Subject: [PATCH 157/203] Revert script changes in injecting app details [skip ci] --- scripts/android/inject_app_details.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/android/inject_app_details.sh b/scripts/android/inject_app_details.sh index 15c39bca7..8551dc7d0 100755 --- a/scripts/android/inject_app_details.sh +++ b/scripts/android/inject_app_details.sh @@ -6,6 +6,6 @@ if [ -z "$APP_ANDROID_TYPE" ]; then fi cd ../.. -sed -i "0,/version:/{s/version:.*/version: ${APP_ANDROID_VERSION}+${APP_ANDROID_BUILD_NUMBER}/}" ./pubspec.yaml +sed -i "0,/version:/{s/version:.*/version: ${APP_ANDROID_VERSION}+${APP_ANDROID_BUILD_NUMBER}/}" ./pubspec.yaml sed -i "0,/version:/{s/__APP_PACKAGE__/${APP_ANDROID_PACKAGE}/}" ./android/app/src/main/AndroidManifest.xml -cd scripts/android \ No newline at end of file +cd scripts/android From 853e9264acd84be98aa66508c9f0d65f4017b6d0 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Wed, 14 Dec 2022 19:22:58 +0200 Subject: [PATCH 158/203] Revert changes in injecting app details [skip ci] From 8e01b2d67a56eac8e4378ece3a9c6d72e3e178fd Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 14 Dec 2022 19:27:44 +0200 Subject: [PATCH 159/203] Revert script changes in injecting app details [skip ci] --- scripts/android/inject_app_details.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/android/inject_app_details.sh b/scripts/android/inject_app_details.sh index 8551dc7d0..6bcdf7239 100755 --- a/scripts/android/inject_app_details.sh +++ b/scripts/android/inject_app_details.sh @@ -8,4 +8,4 @@ fi cd ../.. sed -i "0,/version:/{s/version:.*/version: ${APP_ANDROID_VERSION}+${APP_ANDROID_BUILD_NUMBER}/}" ./pubspec.yaml sed -i "0,/version:/{s/__APP_PACKAGE__/${APP_ANDROID_PACKAGE}/}" ./android/app/src/main/AndroidManifest.xml -cd scripts/android +cd scripts/android \ No newline at end of file From 987df055a084e183ab5b7af78e69fbd331272807 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 15 Dec 2022 00:42:04 +0200 Subject: [PATCH 160/203] Return default values for transaction priority instead of throwing an exception --- cw_bitcoin/lib/bitcoin_transaction_priority.dart | 4 ++-- cw_core/lib/monero_transaction_priority.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_transaction_priority.dart b/cw_bitcoin/lib/bitcoin_transaction_priority.dart index d82ea429e..6f7164ec3 100644 --- a/cw_bitcoin/lib/bitcoin_transaction_priority.dart +++ b/cw_bitcoin/lib/bitcoin_transaction_priority.dart @@ -22,7 +22,7 @@ class BitcoinTransactionPriority extends TransactionPriority { case 2: return fast; default: - throw Exception('Unexpected token: $raw for BitcoinTransactionPriority deserialize'); + return medium; } } @@ -73,7 +73,7 @@ class LitecoinTransactionPriority extends BitcoinTransactionPriority { case 2: return fast; default: - throw Exception('Unexpected token: $raw for LitecoinTransactionPriority deserialize'); + return medium; } } diff --git a/cw_core/lib/monero_transaction_priority.dart b/cw_core/lib/monero_transaction_priority.dart index cca887398..5219014c5 100644 --- a/cw_core/lib/monero_transaction_priority.dart +++ b/cw_core/lib/monero_transaction_priority.dart @@ -50,7 +50,7 @@ class MoneroTransactionPriority extends TransactionPriority { case 4: return fastest; default: - throw Exception('Unexpected token: $raw for MoneroTransactionPriority deserialize'); + return automatic; } } From 710de57847d617b6c4b3d508f61d32809100b81e Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 15 Dec 2022 02:00:59 +0200 Subject: [PATCH 161/203] Validate bitcoin's saved transaction priority --- .../lib/bitcoin_transaction_priority.dart | 6 ++++-- cw_core/lib/monero_transaction_priority.dart | 18 +----------------- lib/entities/default_settings_migration.dart | 14 ++++++++++++++ lib/main.dart | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_transaction_priority.dart b/cw_bitcoin/lib/bitcoin_transaction_priority.dart index 6f7164ec3..0573624ea 100644 --- a/cw_bitcoin/lib/bitcoin_transaction_priority.dart +++ b/cw_bitcoin/lib/bitcoin_transaction_priority.dart @@ -13,6 +13,8 @@ class BitcoinTransactionPriority extends TransactionPriority { static const BitcoinTransactionPriority fast = BitcoinTransactionPriority(title: 'Fast', raw: 2); + static const BitcoinTransactionPriority defaultPriority = medium; + static BitcoinTransactionPriority deserialize({required int raw}) { switch (raw) { case 0: @@ -22,7 +24,7 @@ class BitcoinTransactionPriority extends TransactionPriority { case 2: return fast; default: - return medium; + throw Exception('Unexpected token: $raw for BitcoinTransactionPriority deserialize'); } } @@ -73,7 +75,7 @@ class LitecoinTransactionPriority extends BitcoinTransactionPriority { case 2: return fast; default: - return medium; + throw Exception('Unexpected token: $raw for LitecoinTransactionPriority deserialize'); } } diff --git a/cw_core/lib/monero_transaction_priority.dart b/cw_core/lib/monero_transaction_priority.dart index 5219014c5..f5c00ecc7 100644 --- a/cw_core/lib/monero_transaction_priority.dart +++ b/cw_core/lib/monero_transaction_priority.dart @@ -21,22 +21,6 @@ class MoneroTransactionPriority extends TransactionPriority { static const fastest = MoneroTransactionPriority(title: 'Fastest', raw: 4); static const standard = slow; - - static List forWalletType(WalletType type) { - switch (type) { - case WalletType.monero: - return MoneroTransactionPriority.all; - case WalletType.bitcoin: - return [ - MoneroTransactionPriority.slow, - MoneroTransactionPriority.automatic, - MoneroTransactionPriority.fast - ]; - default: - return []; - } - } - static MoneroTransactionPriority deserialize({required int raw}) { switch (raw) { case 0: @@ -50,7 +34,7 @@ class MoneroTransactionPriority extends TransactionPriority { case 4: return fastest; default: - return automatic; + throw Exception('Unexpected token: $raw for MoneroTransactionPriority deserialize'); } } diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 9aff05500..42b49c2ec 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -1,10 +1,12 @@ import 'dart:io' show File, Platform; import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:hive/hive.dart'; +import 'package:share_plus/share_plus.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cw_core/wallet_type.dart'; @@ -139,6 +141,10 @@ Future defaultSettingsMigration( await addOnionNode(nodes); break; + case 19: + await validateBitcoinSavedTransactionPriority(sharedPreferences); + break; + default: break; } @@ -154,6 +160,14 @@ Future defaultSettingsMigration( PreferencesKey.currentDefaultSettingsMigrationVersion, version); } +Future validateBitcoinSavedTransactionPriority(SharedPreferences sharedPreferences) async { + int? savedBitcoinPriority = sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority); + if (!BitcoinTransactionPriority.all.any((element) => element.raw == savedBitcoinPriority)) { + await sharedPreferences.setInt( + PreferencesKey.bitcoinTransactionPriority, BitcoinTransactionPriority.defaultPriority.raw); + } +} + Future addOnionNode(Box nodes) async { final onionNodeUri = "cakexmrl7bonq7ovjka5kuwuyd3f7qnkz6z6s6dmsy3uckwra7bvggyd.onion:18081"; diff --git a/lib/main.dart b/lib/main.dart index eaabb8339..19f89feb3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -129,7 +129,7 @@ Future main() async { exchangeTemplates: exchangeTemplates, transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, - initialMigrationVersion: 18); + initialMigrationVersion: 19); runApp(App()); } catch (e, stacktrace) { runApp(MaterialApp( From eb0ebbac414778aa3a67e80cf296d39469873db6 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 15 Dec 2022 02:05:00 +0200 Subject: [PATCH 162/203] Validate bitcoin's saved transaction priority [skip ci] --- lib/entities/default_settings_migration.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 42b49c2ec..83012b39a 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -161,7 +161,8 @@ Future defaultSettingsMigration( } Future validateBitcoinSavedTransactionPriority(SharedPreferences sharedPreferences) async { - int? savedBitcoinPriority = sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority); + final int? savedBitcoinPriority = + sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority); if (!BitcoinTransactionPriority.all.any((element) => element.raw == savedBitcoinPriority)) { await sharedPreferences.setInt( PreferencesKey.bitcoinTransactionPriority, BitcoinTransactionPriority.defaultPriority.raw); From 586ad210b3208bdfadf0abad26039bf3c71bee73 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 15 Dec 2022 02:29:30 +0200 Subject: [PATCH 163/203] use defined bitcoin instead of direct import to transaction priority --- lib/entities/default_settings_migration.dart | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 83012b39a..3c8d9fbbe 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -1,12 +1,10 @@ import 'dart:io' show File, Platform; import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:hive/hive.dart'; -import 'package:share_plus/share_plus.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cw_core/wallet_type.dart'; @@ -161,11 +159,14 @@ Future defaultSettingsMigration( } Future validateBitcoinSavedTransactionPriority(SharedPreferences sharedPreferences) async { + if (bitcoin == null) { + return; + } final int? savedBitcoinPriority = sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority); - if (!BitcoinTransactionPriority.all.any((element) => element.raw == savedBitcoinPriority)) { + if (!bitcoin!.getTransactionPriorities().any((element) => element.raw == savedBitcoinPriority)) { await sharedPreferences.setInt( - PreferencesKey.bitcoinTransactionPriority, BitcoinTransactionPriority.defaultPriority.raw); + PreferencesKey.bitcoinTransactionPriority, bitcoin!.getMediumTransactionPriority().serialize()); } } From 99c1205d0d34af399e907ee893139fd7ff2feaa9 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 15 Dec 2022 02:36:44 +0200 Subject: [PATCH 164/203] Remove unused variable [skip ci] --- cw_bitcoin/lib/bitcoin_transaction_priority.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_transaction_priority.dart b/cw_bitcoin/lib/bitcoin_transaction_priority.dart index 0573624ea..d82ea429e 100644 --- a/cw_bitcoin/lib/bitcoin_transaction_priority.dart +++ b/cw_bitcoin/lib/bitcoin_transaction_priority.dart @@ -13,8 +13,6 @@ class BitcoinTransactionPriority extends TransactionPriority { static const BitcoinTransactionPriority fast = BitcoinTransactionPriority(title: 'Fast', raw: 2); - static const BitcoinTransactionPriority defaultPriority = medium; - static BitcoinTransactionPriority deserialize({required int raw}) { switch (raw) { case 0: From f9566cf33e6fc2496644b2d6a9b247f79b4afd2d Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 15 Dec 2022 14:14:54 +0200 Subject: [PATCH 165/203] Check whether it needs to request auth or not AFTER the user gets back to the app --- lib/src/screens/root/root.dart | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index 0ab1c23c1..f69a63d04 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -91,14 +91,15 @@ class RootState extends State with WidgetsBindingObserver { return; } - setState(() { - _requestAuth = widget.authService.requireAuth(); - }); - if (!_isInactive && widget.authenticationStore.state == AuthenticationState.allowed) { setState(() => _setInactive(true)); } + break; + case AppLifecycleState.resumed: + setState(() { + _requestAuth = widget.authService.requireAuth(); + }); break; default: break; From 4abda7bb58ae492cd30edf52cb4113f93cb014f3 Mon Sep 17 00:00:00 2001 From: Justin Ehrenhofer Date: Thu, 15 Dec 2022 09:03:04 -0600 Subject: [PATCH 166/203] Lower target confirmation to 2 --- cw_bitcoin/lib/electrum.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index afbc199a5..7449e0790 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -303,7 +303,7 @@ class ElectrumClient { Future> feeRates() async { try { final topDoubleString = await estimatefee(p: 1); - final middleDoubleString = await estimatefee(p: 20); + final middleDoubleString = await estimatefee(p: 2); final bottomDoubleString = await estimatefee(p: 100); final top = (stringDoubleToBitcoinAmount(topDoubleString.toString()) / 1000) From 4c9fd5db6549c6f586b207ae5b844225f2092835 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 15 Dec 2022 18:00:56 +0200 Subject: [PATCH 167/203] Navigate to send screen even if the user does not need to authenticate --- lib/src/screens/root/root.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index 0ab1c23c1..052d4c71b 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -124,6 +124,12 @@ class RootState extends State with WidgetsBindingObserver { launchUri = null; }); }); + } else if (launchUri != null) { + widget.navigatorKey.currentState?.pushNamed( + Routes.send, + arguments: PaymentRequest.fromUri(launchUri), + ); + launchUri = null; } return WillPopScope(onWillPop: () async => false, child: widget.child); From 4be874113047fa981f1f81ae0242c062e9245555 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 15 Dec 2022 18:54:12 +0200 Subject: [PATCH 168/203] Open app in a single instance only and not on top if launched from other apps --- android/app/src/main/AndroidManifestBase.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index cf67a8c26..9f6b65785 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -16,7 +16,7 @@ android:requestLegacyExternalStorage="true"> Date: Thu, 15 Dec 2022 11:48:49 -0600 Subject: [PATCH 169/203] change to 5 this appears to be a more sensible value for medium --- cw_bitcoin/lib/electrum.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index 7449e0790..d856cb2bf 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -303,7 +303,7 @@ class ElectrumClient { Future> feeRates() async { try { final topDoubleString = await estimatefee(p: 1); - final middleDoubleString = await estimatefee(p: 2); + final middleDoubleString = await estimatefee(p: 5); final bottomDoubleString = await estimatefee(p: 100); final top = (stringDoubleToBitcoinAmount(topDoubleString.toString()) / 1000) From 947d1e2f7c03f02f58e8e80cdd7d5ea9d3264122 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 15 Dec 2022 22:15:03 +0200 Subject: [PATCH 170/203] Pump app versions and build numbers [skip ci] --- scripts/android/app_env.sh | 8 ++++---- scripts/ios/app_env.sh | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 5b704eea1..556a78a87 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -14,14 +14,14 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.2.2" -MONERO_COM_BUILD_NUMBER=33 +MONERO_COM_VERSION="1.2.3" +MONERO_COM_BUILD_NUMBER=34 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.5.3" -CAKEWALLET_BUILD_NUMBER=138 +CAKEWALLET_VERSION="4.5.4" +CAKEWALLET_BUILD_NUMBER=139 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index fbf8233e5..f530f718a 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.2.2" -MONERO_COM_BUILD_NUMBER=30 +MONERO_COM_VERSION="1.2.3" +MONERO_COM_BUILD_NUMBER=31 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.5.3" -CAKEWALLET_BUILD_NUMBER=135 +CAKEWALLET_VERSION="4.5.4" +CAKEWALLET_BUILD_NUMBER=136 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" From afd9fe75543eda80e6131bce76d5c56b90cef788 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 16 Dec 2022 14:06:08 +0200 Subject: [PATCH 171/203] add missing default priority for btc and ltc --- lib/ionia/ionia_anypay.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/ionia/ionia_anypay.dart b/lib/ionia/ionia_anypay.dart index f4053094b..2aaaf4994 100644 --- a/lib/ionia/ionia_anypay.dart +++ b/lib/ionia/ionia_anypay.dart @@ -55,7 +55,9 @@ class IoniaAnyPay { address: out.address, formattedCryptoAmount: out.amount, sendAll: false)).toList(), - feeRate: instruction.requiredFeeRate); + feeRate: instruction.requiredFeeRate, + priority: bitcoin!.getBitcoinTransactionPriorityMedium(), + ); case AnyPayChain.ltc: return bitcoin!.createBitcoinTransactionCredentialsRaw( instruction.outputs.map((out) => @@ -64,7 +66,9 @@ class IoniaAnyPay { address: out.address, formattedCryptoAmount: out.amount, sendAll: false)).toList(), - feeRate: instruction.requiredFeeRate); + feeRate: instruction.requiredFeeRate, + priority: bitcoin!.getLitecoinTransactionPriorityMedium(), + ); default: throw Exception('Incorrect transaction chain: ${payment.chain.toUpperCase()}'); } From 6148b91c8a827a65fc35b9370dc6ba9888d7739b Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 16 Dec 2022 14:33:33 +0200 Subject: [PATCH 172/203] Fix Generic Type being enforced to extend Object --- .../screens/settings/widgets/settings_picker_cell.dart | 2 +- lib/src/widgets/picker.dart | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/src/screens/settings/widgets/settings_picker_cell.dart b/lib/src/screens/settings/widgets/settings_picker_cell.dart index 1da2d6fc1..8dd5c8c2c 100644 --- a/lib/src/screens/settings/widgets/settings_picker_cell.dart +++ b/lib/src/screens/settings/widgets/settings_picker_cell.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; -class SettingsPickerCell extends StandardListRow { +class SettingsPickerCell extends StandardListRow { SettingsPickerCell( {required String title, required this.selectedItem, diff --git a/lib/src/widgets/picker.dart b/lib/src/widgets/picker.dart index 36aafe5aa..f26ff3ee2 100644 --- a/lib/src/widgets/picker.dart +++ b/lib/src/widgets/picker.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/alert_background.dart'; import 'package:cake_wallet/src/widgets/alert_close_button.dart'; -class Picker extends StatefulWidget { +class Picker extends StatefulWidget { Picker({ required this.selectedAtIndex, required this.items, @@ -39,7 +39,7 @@ class Picker extends StatefulWidget { _PickerState createState() => _PickerState(items, images, onItemSelected); } -class _PickerState extends State { +class _PickerState extends State> { _PickerState(this.items, this.images, this.onItemSelected); final Function(Item) onItemSelected; @@ -59,7 +59,7 @@ class _PickerState extends State { images = []; for (int i=0;i extends State { child: Padding( padding: EdgeInsets.only(left: image != null ? 12 : 0), child: Text( - // What a hack (item as) ? - widget.displayItem?.call(item as Object) ?? item.toString(), + widget.displayItem?.call(item) ?? item.toString(), style: TextStyle( fontSize: 14, fontFamily: 'Lato', From 7ffb654065add7d4fe668cfd36a5ed0902152952 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 16 Dec 2022 19:21:40 +0200 Subject: [PATCH 173/203] Calculate fee amount from fee rate if available --- cw_bitcoin/lib/electrum_wallet.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index fad546d90..f31db7bb8 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -191,8 +191,10 @@ abstract class ElectrumWalletBase extends WalletBase Date: Sat, 17 Dec 2022 02:24:15 +0200 Subject: [PATCH 174/203] Remove fallback default priority to calculate fee, in order to know if something is wrong from anypay --- lib/ionia/ionia_anypay.dart | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/ionia/ionia_anypay.dart b/lib/ionia/ionia_anypay.dart index 2aaaf4994..f4053094b 100644 --- a/lib/ionia/ionia_anypay.dart +++ b/lib/ionia/ionia_anypay.dart @@ -55,9 +55,7 @@ class IoniaAnyPay { address: out.address, formattedCryptoAmount: out.amount, sendAll: false)).toList(), - feeRate: instruction.requiredFeeRate, - priority: bitcoin!.getBitcoinTransactionPriorityMedium(), - ); + feeRate: instruction.requiredFeeRate); case AnyPayChain.ltc: return bitcoin!.createBitcoinTransactionCredentialsRaw( instruction.outputs.map((out) => @@ -66,9 +64,7 @@ class IoniaAnyPay { address: out.address, formattedCryptoAmount: out.amount, sendAll: false)).toList(), - feeRate: instruction.requiredFeeRate, - priority: bitcoin!.getLitecoinTransactionPriorityMedium(), - ); + feeRate: instruction.requiredFeeRate); default: throw Exception('Incorrect transaction chain: ${payment.chain.toUpperCase()}'); } From ecc556e4e339ca5d22569d458d6ba37c71f204b9 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Mon, 19 Dec 2022 19:37:58 +0200 Subject: [PATCH 175/203] Cache Generated Externals to Improve the runtime of the workflow --- .github/workflows/pr_test_build.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 190b891e1..d2320d8fb 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -34,6 +34,24 @@ jobs: ./install_ndk.sh source ./app_env.sh cakewallet ./app_config.sh + + - name: Cache Externals + id: cache-externals + uses: actions/cache@v3 + with: + path: | + /opt/android/cake_wallet/cw_haven/android/.cxx + /opt/android/cake_wallet/cw_haven/ios/External + /opt/android/cake_wallet/cw_monero/android/.cxx + /opt/android/cake_wallet/cw_haven/ios/External + /opt/android/cake_wallet/cw_shared_external/ios/External + key: externals-cache-key + + - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} + name: Generate Externals + run: | + cd cake_wallet/scripts/android/ + source ./app_env.sh cakewallet ./build_all.sh ./copy_monero_deps.sh From bb197980f49b20d456bd49f259ba6f55ba2e0476 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Mon, 19 Dec 2022 19:41:00 +0200 Subject: [PATCH 176/203] Upload to transfer.sh lastly since its taking more time recently --- .github/workflows/pr_test_build.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index d2320d8fb..06dfa5b65 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -50,7 +50,7 @@ jobs: - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} name: Generate Externals run: | - cd cake_wallet/scripts/android/ + cd /opt/android/cake_wallet/scripts/android/ source ./app_env.sh cakewallet ./build_all.sh ./copy_monero_deps.sh @@ -129,19 +129,19 @@ jobs: # --token ${{ secrets.APP_CENTER_TOKEN }} \ # --quiet - - name: Send Test APK - run: | - cd /opt/android/cake_wallet - var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/$GITHUB_HEAD_REF.apk -H "Max-Days: 10") - curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' - - name: Rename apk file run: | cd /opt/android/cake_wallet/build/app/outputs/apk/release mkdir test-apk - mv app-release.apk test-apk/$GITHUB_HEAD_REF.apk + cp app-release.apk test-apk/$GITHUB_HEAD_REF.apk - name: Upload Artifact uses: kittaakos/upload-artifact-as-is@v0 with: path: /opt/android/cake_wallet/build/app/outputs/apk/release/test-apk/ + + - name: Send Test APK + run: | + cd /opt/android/cake_wallet + var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/$GITHUB_HEAD_REF.apk -H "Max-Days: 10") + curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' From d204669f0869f227357400f378c1cc3627ba1d33 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Mon, 19 Dec 2022 21:50:44 +0200 Subject: [PATCH 177/203] Test Caching --- .github/workflows/pr_test_build.yml | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 06dfa5b65..67cd60aa8 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -43,10 +43,34 @@ jobs: /opt/android/cake_wallet/cw_haven/android/.cxx /opt/android/cake_wallet/cw_haven/ios/External /opt/android/cake_wallet/cw_monero/android/.cxx - /opt/android/cake_wallet/cw_haven/ios/External + /opt/android/cake_wallet/cw_monero/ios/External /opt/android/cake_wallet/cw_shared_external/ios/External key: externals-cache-key + - name: Test Cache + run: | + echo steps.cache-externals.outputs.cache-hit + cd /opt/android/cake_wallet/cw_shared_external/ios + ls + echo "==================================" + echo "==================================" + cd ../../cw_haven/ios + ls + echo "==================================" + echo "==================================" + cd ../android + ls + echo "==================================" + echo "==================================" + cd ../../cw_monero/ios + ls + echo "==================================" + echo "==================================" + cd ../android + ls + echo "==================================" + echo "==================================" + - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} name: Generate Externals run: | From 61ae5bf800508aed1e74b78fdcb7f6d9ec8f38d2 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Mon, 19 Dec 2022 23:32:20 +0200 Subject: [PATCH 178/203] Test Caching --- .github/workflows/pr_test_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 67cd60aa8..b1988b470 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -49,7 +49,7 @@ jobs: - name: Test Cache run: | - echo steps.cache-externals.outputs.cache-hit + echo ${{ steps.cache-externals.outputs.cache-hit }} cd /opt/android/cake_wallet/cw_shared_external/ios ls echo "==================================" From dfa8ad2fe97fa420e87f2fa709442adc7258c1dd Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 20 Dec 2022 14:37:13 +0200 Subject: [PATCH 179/203] Remove testing steps --- .github/workflows/pr_test_build.yml | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index b1988b470..96ac95e49 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -47,30 +47,6 @@ jobs: /opt/android/cake_wallet/cw_shared_external/ios/External key: externals-cache-key - - name: Test Cache - run: | - echo ${{ steps.cache-externals.outputs.cache-hit }} - cd /opt/android/cake_wallet/cw_shared_external/ios - ls - echo "==================================" - echo "==================================" - cd ../../cw_haven/ios - ls - echo "==================================" - echo "==================================" - cd ../android - ls - echo "==================================" - echo "==================================" - cd ../../cw_monero/ios - ls - echo "==================================" - echo "==================================" - cd ../android - ls - echo "==================================" - echo "==================================" - - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} name: Generate Externals run: | From e005e2aed703e56e94e485f5ea771ee70734077d Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 21 Dec 2022 19:15:02 +0200 Subject: [PATCH 180/203] Add Cake Pay Web Card to marketplace --- .../screens/dashboard/widgets/market_place_page.dart | 12 +++++++++++- res/values/strings_de.arb | 4 +++- res/values/strings_en.arb | 4 +++- res/values/strings_es.arb | 4 +++- res/values/strings_fr.arb | 4 +++- res/values/strings_hi.arb | 4 +++- res/values/strings_hr.arb | 4 +++- res/values/strings_it.arb | 4 +++- res/values/strings_ja.arb | 4 +++- res/values/strings_ko.arb | 4 +++- res/values/strings_nl.arb | 4 +++- res/values/strings_pl.arb | 4 +++- res/values/strings_pt.arb | 4 +++- res/values/strings_ru.arb | 4 +++- res/values/strings_uk.arb | 4 +++- res/values/strings_zh.arb | 4 +++- 16 files changed, 56 insertions(+), 16 deletions(-) diff --git a/lib/src/screens/dashboard/widgets/market_place_page.dart b/lib/src/screens/dashboard/widgets/market_place_page.dart index a64a132ad..9ac225634 100644 --- a/lib/src/screens/dashboard/widgets/market_place_page.dart +++ b/lib/src/screens/dashboard/widgets/market_place_page.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:url_launcher/url_launcher.dart'; class MarketPlacePage extends StatelessWidget { @@ -48,6 +49,15 @@ class MarketPlacePage extends StatelessWidget { title: S.of(context).cake_pay_title, subTitle: S.of(context).cake_pay_subtitle, ), + SizedBox(height: 20), + MarketPlaceItem( + onTap: () => launchUrl( + Uri.https("buy.cakepay.com"), + mode: LaunchMode.externalApplication, + ), + title: S.of(context).cake_pay_web_cards_title, + subTitle: S.of(context).cake_pay_web_cards_subtitle, + ), ], ), ), @@ -72,7 +82,7 @@ class MarketPlacePage extends StatelessWidget { buttonAction: () => Navigator.of(context).pop()); }); break; - default: + default: Navigator.of(context).pushNamed(Routes.ioniaWelcomePage); } } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 2b66a1b28..56b7917df 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -539,7 +539,9 @@ "wallet_name_exists": "Wallet mit diesem Namen existiert bereits", "market_place": "Marktplatz", "cake_pay_title": "Cake Pay-Geschenkkarten", - "cake_pay_subtitle": "Geschenkkarten kaufen und sofort einlösen", + "cake_pay_subtitle": "Kaufen Sie ermäßigte Geschenkkarten (nur USA)", + "cake_pay_web_cards_title": "Cake Pay-Webkarten", + "cake_pay_web_cards_subtitle": "Kaufen Sie weltweit Prepaid-Karten und Geschenkkarten", "about_cake_pay": "Mit Cake Pay können Sie ganz einfach Geschenkkarten mit virtuellen Vermögenswerten kaufen, die Sie sofort bei über 150.000 Händlern in den Vereinigten Staaten ausgeben können.", "cake_pay_account_note": "Melden Sie sich nur mit einer E-Mail-Adresse an, um Karten anzuzeigen und zu kaufen. Einige sind sogar mit Rabatt erhältlich!", "already_have_account": "Sie haben bereits ein Konto?", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 92d763cc2..5f312a132 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -539,7 +539,9 @@ "wallet_name_exists": "A wallet with that name already exists. Please choose a different name or rename the other wallet first.", "market_place": "Marketplace", "cake_pay_title": "Cake Pay Gift Cards", - "cake_pay_subtitle": "Buy gift cards and redeem instantly", + "cake_pay_subtitle": "Buy discounted gift cards (USA only)", + "cake_pay_web_cards_title": "Cake Pay Web Cards", + "cake_pay_web_cards_subtitle": "Buy worldwide prepaid cards and gift cards", "about_cake_pay": "Cake Pay allows you to easily buy gift cards with virtual assets, spendable instantly at over 150,000 merchants in the United States.", "cake_pay_account_note": "Sign up with just an email address to see and purchase cards. Some are even available at a discount!", "already_have_account": "Already have an account?", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index df23d994e..2c611a540 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -539,7 +539,9 @@ "wallet_name_exists": "Wallet con ese nombre ya ha existido", "market_place": "Mercado", "cake_pay_title": "Tarjetas de regalo Cake Pay", - "cake_pay_subtitle": "Compra tarjetas de regalo y canjéalas al instante", + "cake_pay_subtitle": "Compre tarjetas de regalo con descuento (solo EE. UU.)", + "cake_pay_web_cards_title": "Tarjetas Web Cake Pay", + "cake_pay_web_cards_subtitle": "Compre tarjetas de prepago y tarjetas de regalo en todo el mundo", "about_cake_pay": "Cake Pay le permite comprar fácilmente tarjetas de regalo con activos virtuales, gastables instantáneamente en más de 150 000 comerciantes en los Estados Unidos.", "cake_pay_account_note": "Regístrese con solo una dirección de correo electrónico para ver y comprar tarjetas. ¡Algunas incluso están disponibles con descuento!", "already_have_account": "¿Ya tienes una cuenta?", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 349bb9dfc..1c4ebf1a8 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -537,7 +537,9 @@ "wallet_name_exists": "Un portefeuille portant ce nom existe déjà", "market_place": "Place de marché", "cake_pay_title": "Cartes cadeaux Cake Pay", - "cake_pay_subtitle": "Achetez des cartes-cadeaux et échangez-les instantanément", + "cake_pay_subtitle": "Achetez des cartes-cadeaux à prix réduit (États-Unis uniquement)", + "cake_pay_web_cards_title": "Cartes Web Cake Pay", + "cake_pay_web_cards_subtitle": "Achetez des cartes prépayées et des cartes-cadeaux dans le monde entier", "about_cake_pay": "Cake Pay vous permet d'acheter facilement des cartes-cadeaux avec des actifs virtuels, utilisables instantanément chez plus de 150 000 marchands aux États-Unis.", "cake_pay_account_note": "Inscrivez-vous avec juste une adresse e-mail pour voir et acheter des cartes. Certaines sont même disponibles à prix réduit !", "already_have_account": "Vous avez déjà un compte ?", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 66d40ddc2..c5c041061 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -539,7 +539,9 @@ "wallet_name_exists": "उस नाम वाला वॉलेट पहले से मौजूद है", "market_place": "मार्केटप्लेस", "cake_pay_title": "केक पे गिफ्ट कार्ड्स", - "cake_pay_subtitle": "उपहार कार्ड खरीदें और तुरंत रिडीम करें", + "cake_pay_subtitle": "रियायती उपहार कार्ड खरीदें (केवल यूएसए)", + "cake_pay_web_cards_title": "केक भुगतान वेब कार्ड", + "cake_pay_web_cards_subtitle": "दुनिया भर में प्रीपेड कार्ड और गिफ्ट कार्ड खरीदें", "about_cake_pay": "केक पे आपको वर्चुअल संपत्ति के साथ आसानी से उपहार कार्ड खरीदने की अनुमति देता है, जिसे संयुक्त राज्य में 150,000 से अधिक व्यापारियों पर तुरंत खर्च किया जा सकता है।", "cake_pay_account_note": "कार्ड देखने और खरीदने के लिए केवल एक ईमेल पते के साथ साइन अप करें। कुछ छूट पर भी उपलब्ध हैं!", "ready_have_account": "क्या आपके पास पहले से ही एक खाता है?", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 5eb394b01..dc9275150 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -539,7 +539,9 @@ "wallet_name_exists": "Novčanik s tim nazivom već postoji", "market_place": "Tržnica", "cake_pay_title": "Cake Pay poklon kartice", - "cake_pay_subtitle": "Kupite darovne kartice i odmah ih iskoristite", + "cake_pay_subtitle": "Kupite darovne kartice s popustom (samo SAD)", + "cake_pay_web_cards_title": "Cake Pay Web kartice", + "cake_pay_web_cards_subtitle": "Kupujte prepaid kartice i poklon kartice diljem svijeta", "about_cake_pay": "Cake Pay vam omogućuje jednostavnu kupnju darovnih kartica s virtualnim sredstvima, koja se trenutno mogu potrošiti kod više od 150 000 trgovaca u Sjedinjenim Državama.", "cake_pay_account_note": "Prijavite se samo s adresom e-pošte da biste vidjeli i kupili kartice. Neke su čak dostupne uz popust!", "already_have_account": "Već imate račun?", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 7ff01753f..e3770f760 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -539,7 +539,9 @@ "wallet_name_exists": "Il portafoglio con quel nome è già esistito", "market_place": "Mercato", "cake_pay_title": "Carte regalo Cake Pay", - "cake_pay_subtitle": "Acquista carte regalo e riscattale all'istante", + "cake_pay_subtitle": "Acquista buoni regalo scontati (solo USA)", + "cake_pay_web_cards_title": "Carte Web Cake Pay", + "cake_pay_web_cards_subtitle": "Acquista carte prepagate e carte regalo in tutto il mondo", "about_cake_pay": "Cake Pay ti consente di acquistare facilmente buoni regalo con asset virtuali, spendibili istantaneamente presso oltre 150.000 commercianti negli Stati Uniti.", "cake_pay_account_note": "Iscriviti con solo un indirizzo email per vedere e acquistare le carte. Alcune sono anche disponibili con uno sconto!", "already_have_account": "Hai già un account?", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 97ccb7160..d699b070e 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -539,7 +539,9 @@ "wallet_name_exists": "その名前のウォレットはすでに存在しています", "market_place": "Marketplace", "cake_pay_title": "ケーキペイギフトカード", - "cake_pay_subtitle": "ギフトカードを購入してすぐに利用できます", + "cake_pay_subtitle": "割引ギフトカードを購入する (米国のみ)", + "cake_pay_web_cards_title": "Cake Pay ウェブカード", + "cake_pay_web_cards_subtitle": "世界中のプリペイド カードとギフト カードを購入する", "about_cake_pay": "Cake Payを使用すると、仮想資産を含むギフトカードを簡単に購入でき、米国内の150,000を超える加盟店ですぐに利用できます。", "cake_pay_account_note": "メールアドレスだけでサインアップして、カードを表示して購入できます。割引価格で利用できるカードもあります!", "already_have_account": "すでにアカウントをお持ちですか?", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 470a1e405..3761f4f93 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -539,7 +539,9 @@ "wallet_name_exists": "해당 이름의 지갑이 이미 존재합니다.", "market_place": "마켓플레이스", "cake_pay_title": "케이크 페이 기프트 카드", - "cake_pay_subtitle": "기프트 카드를 구매하고 즉시 사용", + "cake_pay_subtitle": "할인된 기프트 카드 구매(미국만 해당)", + "cake_pay_web_cards_title": "케이크페이 웹카드", + "cake_pay_web_cards_subtitle": "전 세계 선불 카드 및 기프트 카드 구매", "about_cake_pay": "Cake Pay를 사용하면 미국 내 150,000개 이상의 가맹점에서 즉시 사용할 수 있는 가상 자산이 포함된 기프트 카드를 쉽게 구입할 수 있습니다.", "cake_pay_account_note": "이메일 주소로 가입하면 카드를 보고 구매할 수 있습니다. 일부는 할인된 가격으로 사용 가능합니다!", "already_have_account": "이미 계정이 있습니까?", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index a198f8672..426f9530a 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -539,7 +539,9 @@ "wallet_name_exists": "Portemonnee met die naam bestaat al", "market_place": "Marktplaats", "cake_pay_title": "Cake Pay-cadeaubonnen", - "cake_pay_subtitle": "Koop cadeaubonnen en wissel ze direct in", + "cake_pay_subtitle": "Koop cadeaubonnen met korting (alleen VS)", + "cake_pay_web_cards_title": "Cake Pay-webkaarten", + "cake_pay_web_cards_subtitle": "Koop wereldwijd prepaidkaarten en cadeaubonnen", "about_cake_pay": "Met Cake Pay kunt u eenvoudig cadeaubonnen kopen met virtuele activa, die direct kunnen worden uitgegeven bij meer dan 150.000 handelaren in de Verenigde Staten.", "cake_pay_account_note": "Meld u aan met alleen een e-mailadres om kaarten te bekijken en te kopen. Sommige zijn zelfs met korting verkrijgbaar!", "already_have_account": "Heb je al een account?", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index dc1ffbd84..2baf3cf48 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -539,7 +539,9 @@ "wallet_name_exists": "Portfel o tej nazwie już istnieje", "market_place": "Rynek", "cake_pay_title": "Karty podarunkowe Cake Pay", - "cake_pay_subtitle": "Kup karty podarunkowe i wykorzystaj je natychmiast", + "cake_pay_subtitle": "Kup karty upominkowe ze zniżką (tylko USA)", + "cake_pay_web_cards_title": "Cake Pay Web Cards", + "cake_pay_web_cards_subtitle": "Kupuj na całym świecie karty przedpłacone i karty podarunkowe", "about_cake_pay": "Cake Pay umożliwia łatwe kupowanie kart podarunkowych z wirtualnymi aktywami, które można natychmiast wydać u ponad 150 000 sprzedawców w Stanach Zjednoczonych.", "cake_pay_account_note": "Zarejestruj się, używając tylko adresu e-mail, aby przeglądać i kupować karty. Niektóre są nawet dostępne ze zniżką!", "already_have_account": "Masz już konto?", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 6a128d109..9cb077f1b 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -539,7 +539,9 @@ "wallet_name_exists": "A carteira com esse nome já existe", "market_place": "Mercado", "cake_pay_title": "Cartões de presente de pagamento de bolo", - "cake_pay_subtitle": "Compre vales-presente e resgate instantaneamente", + "cake_pay_subtitle": "Compre vales-presente com desconto (somente nos EUA)", + "cake_pay_web_cards_title": "Cartões Cake Pay Web", + "cake_pay_web_cards_subtitle": "Compre cartões pré-pagos e cartões-presente em todo o mundo", "about_cake_pay": "O Cake Pay permite que você compre facilmente cartões-presente com ativos virtuais, que podem ser gastos instantaneamente em mais de 150.000 comerciantes nos Estados Unidos.", "cake_pay_account_note": "Inscreva-se com apenas um endereço de e-mail para ver e comprar cartões. Alguns estão até com desconto!", "already_have_account": "Já tem uma conta?", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 04a7f0665..3772a0d2c 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -539,7 +539,9 @@ "wallet_name_exists": "Кошелек с таким именем уже существует", "market_place": "Торговая площадка", "cake_pay_title": "Подарочные карты Cake Pay", - "cake_pay_subtitle": "Купите подарочные карты и моментально погасите их", + "cake_pay_subtitle": "Покупайте подарочные карты со скидкой (только для США)", + "cake_pay_web_cards_title": "Веб-карты Cake Pay", + "cake_pay_web_cards_subtitle": "Покупайте карты предоплаты и подарочные карты по всему миру", "about_cake_pay": "Cake Pay позволяет вам легко покупать подарочные карты с виртуальными активами, которые можно мгновенно потратить в более чем 150 000 продавцов в Соединенных Штатах.", "cake_pay_account_note": "Зарегистрируйтесь, указав только адрес электронной почты, чтобы просматривать и покупать карты. Некоторые даже доступны со скидкой!", "already_have_account": "У вас уже есть аккаунт?", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 58d19e636..680633d22 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -538,7 +538,9 @@ "wallet_name_exists": "Гаманець з такою назвою вже існує", "market_place": "Ринок", "cake_pay_title": "Подарункові картки Cake Pay", - "cake_pay_subtitle": "Купуйте подарункові картки та використовуйте їх миттєво", + "cake_pay_subtitle": "Купуйте подарункові картки зі знижкою (тільки для США)", + "cake_pay_web_cards_title": "Веб-картки Cake Pay", + "cake_pay_web_cards_subtitle": "Купуйте передоплачені та подарункові картки по всьому світу", "about_cake_pay": "Cake Pay дозволяє вам легко купувати подарункові картки з віртуальними активами, які можна миттєво витратити в понад 150 000 продавців у Сполучених Штатах.", "cake_pay_account_note": "Зареєструйтеся, використовуючи лише адресу електронної пошти, щоб переглядати та купувати картки. Деякі навіть доступні зі знижкою!", "already_have_account": "Вже є обліковий запис?", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index eb4571943..7d251a68e 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -537,7 +537,9 @@ "wallet_name_exists": "同名的钱包已经存在", "market_place": "市场", "cake_pay_title": "Cake Pay 礼品卡", - "cake_pay_subtitle": "购买礼品卡并立即兑换", + "cake_pay_subtitle": "购买打折礼品卡(仅限美国)", + "cake_pay_web_cards_title": "蛋糕支付网络卡", + "cake_pay_web_cards_subtitle": "购买全球预付卡和礼品卡", "about_cake_pay": "Cake Pay 让您可以轻松购买带有虚拟资产的礼品卡,可立即在美国超过 150,000 家商家消费。", "cake_pay_account_note": "只需使用電子郵件地址註冊即可查看和購買卡片。有些甚至可以打折!", "already_have_account": "已经有账号了?", From 85a70e3b1d65bcfd8c8c8e071cac27fa21c31b3f Mon Sep 17 00:00:00 2001 From: Justin Ehrenhofer Date: Wed, 21 Dec 2022 12:06:47 -0600 Subject: [PATCH 181/203] Contributing instructions for languages and fiat currencies --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index bd74ccfbc..c5f6dc1b2 100644 --- a/README.md +++ b/README.md @@ -76,3 +76,31 @@ We have 24/7 free support. Please contact support@cakewallet.com More instructions to follow For instructions on how to build for Android: please view file `howto-build-android.md` + +# Contributing + +## Improving translations + +Edit the applicable `strings_XX.arb` file in `res/values/` and open a pull request with the changes. + +## Add a new language + +1. Create a new `strings_XX.arb` file in `res/values/`, replacing XX with the language's [ISO 639-1 code](https://en.wikipedia.org/wiki/ISO_639-1). + +2. Edit the strings in this file, replacing XXX below with the translation for each string. + +`"welcome" : "Welcome to",` -> `"welcome" : "XXX",` + +3. Add the language to `lib/entities/language_service.dart` under both `supportedLocales` and `localeCountryCode`. Use the name of the language in the local language and in English in parentheses after for `supportedLocales`. Use the [ISO 3166-1 alpha-3 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) for `localeCountryCode`. You must choose one country, so choose the country with the most native speakers of this language or is otherwise best associated with this language. + +4. Add a relevant flag to `assets/images/flags/XXXX.png`, replacing XXXX with the 3 digit localeCountryCode. The image must be 42x36 pizxels with a 3 pixels of transparent margin on all 4 sides. + +## Add a new fiat currency + +1. Check with [Cake Wallet support](https://guides.cakewallet.com) to see if the desired new fiat currency is available through our fiat API. Not all fiat currencies are. + +2. If the currency is associated strongly with a specific issuing country, map the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code with the applicable [ISO 3166-1 alpha-3 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) in `lib/entities/fiat_currency.dart`. If the currency is used in a whole region or organization, then map with a reasonable interpretation of this (eg: eur countryCode for EUR symbol). + +3. Add the raw mapping underneath in `lib/entities/fiat_currency.dart` following the same format as the others. + +4. Add a flag of the issuing country or organization to `assets/images/flags/XXXX.png`, replacing XXXX with the ISO 3166-1 alpha-3 code used above (eg: `usa.png`, `eur.png`). Do not add this if the flag with the same name already exists. The image must be 42x36 pizxels with a 3 pixels of transparent margin on all 4 sides. From a3afcc19fe119b17b4a63f87cac422ced7d3e333 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 22 Dec 2022 20:00:16 +0200 Subject: [PATCH 182/203] New App Version Cake Wallet v4.5.5 - Monero v1.2.4 --- scripts/android/app_env.sh | 8 ++++---- scripts/ios/app_env.sh | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 556a78a87..979a60e9d 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -14,14 +14,14 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.2.3" -MONERO_COM_BUILD_NUMBER=34 +MONERO_COM_VERSION="1.2.4" +MONERO_COM_BUILD_NUMBER=35 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.5.4" -CAKEWALLET_BUILD_NUMBER=139 +CAKEWALLET_VERSION="4.5.5" +CAKEWALLET_BUILD_NUMBER=140 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index f530f718a..1965d1e41 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.2.3" -MONERO_COM_BUILD_NUMBER=31 +MONERO_COM_VERSION="1.2.4" +MONERO_COM_BUILD_NUMBER=32 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.5.4" -CAKEWALLET_BUILD_NUMBER=136 +CAKEWALLET_VERSION="4.5.5" +CAKEWALLET_BUILD_NUMBER=137 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" From 40270e84c9c6c09ff5710a69a80e17c9f536fbec Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 22 Dec 2022 20:59:40 +0200 Subject: [PATCH 183/203] - Add Cache Dependencies workflow on main branch to be available for all sub branches - Replace static cache key with hash of dependencies pubspec.yaml --- .github/workflows/cache_dependencies.yml | 56 ++++++++++++++++++++++++ .github/workflows/pr_test_build.yml | 2 +- 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/cache_dependencies.yml diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml new file mode 100644 index 000000000..4b7084884 --- /dev/null +++ b/.github/workflows/cache_dependencies.yml @@ -0,0 +1,56 @@ +name: Cache Dependencies + +on: + push: + branches: [ main ] + +jobs: + test: + + runs-on: ubuntu-18.04 + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: '8.x' + + - name: Flutter action + uses: subosito/flutter-action@v1 + with: + flutter-version: '3.3.x' + channel: stable + + - name: Install package dependencies + run: sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang + + - name: Execute Build and Setup Commands + run: | + sudo mkdir -p /opt/android + sudo chown $USER /opt/android + cd /opt/android + git clone https://github.com/cake-tech/cake_wallet.git --branch main + cd cake_wallet/scripts/android/ + ./install_ndk.sh + source ./app_env.sh cakewallet + ./app_config.sh + + - name: Cache Externals + id: cache-externals + uses: actions/cache@v3 + with: + path: | + /opt/android/cake_wallet/cw_haven/android/.cxx + /opt/android/cake_wallet/cw_haven/ios/External + /opt/android/cake_wallet/cw_monero/android/.cxx + /opt/android/cake_wallet/cw_monero/ios/External + /opt/android/cake_wallet/cw_shared_external/ios/External + key: ${{ hashFiles('/opt/android/cake_wallet/cw_haven/pubspec.yaml', '/opt/android/cake_wallet/cw_monero/pubspec.yaml', '/opt/android/cake_wallet/cw_shared_external/pubspec.yaml') }} + + - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} + name: Generate Externals + run: | + cd /opt/android/cake_wallet/scripts/android/ + source ./app_env.sh cakewallet + ./build_all.sh + ./copy_monero_deps.sh diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 96ac95e49..54f716cc2 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -45,7 +45,7 @@ jobs: /opt/android/cake_wallet/cw_monero/android/.cxx /opt/android/cake_wallet/cw_monero/ios/External /opt/android/cake_wallet/cw_shared_external/ios/External - key: externals-cache-key + key: ${{ hashFiles('/opt/android/cake_wallet/cw_haven/pubspec.yaml', '/opt/android/cake_wallet/cw_monero/pubspec.yaml', '/opt/android/cake_wallet/cw_shared_external/pubspec.yaml') }} - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} name: Generate Externals From 0baa0329ac857d7e878f0b9bfe403b79bd802d9f Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 22 Dec 2022 22:54:33 +0200 Subject: [PATCH 184/203] Change key to be of the build scripts hash --- .github/workflows/cache_dependencies.yml | 2 +- .github/workflows/pr_test_build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml index 4b7084884..0887ed07d 100644 --- a/.github/workflows/cache_dependencies.yml +++ b/.github/workflows/cache_dependencies.yml @@ -45,7 +45,7 @@ jobs: /opt/android/cake_wallet/cw_monero/android/.cxx /opt/android/cake_wallet/cw_monero/ios/External /opt/android/cake_wallet/cw_shared_external/ios/External - key: ${{ hashFiles('/opt/android/cake_wallet/cw_haven/pubspec.yaml', '/opt/android/cake_wallet/cw_monero/pubspec.yaml', '/opt/android/cake_wallet/cw_shared_external/pubspec.yaml') }} + key: ${{ hashFiles('/opt/android/cake_wallet/scripts/android/build_monero.sh', '/opt/android/cake_wallet/scripts/android/build_haven.sh') }} - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} name: Generate Externals diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 54f716cc2..83e430a32 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -45,7 +45,7 @@ jobs: /opt/android/cake_wallet/cw_monero/android/.cxx /opt/android/cake_wallet/cw_monero/ios/External /opt/android/cake_wallet/cw_shared_external/ios/External - key: ${{ hashFiles('/opt/android/cake_wallet/cw_haven/pubspec.yaml', '/opt/android/cake_wallet/cw_monero/pubspec.yaml', '/opt/android/cake_wallet/cw_shared_external/pubspec.yaml') }} + key: ${{ hashFiles('/opt/android/cake_wallet/scripts/android/build_monero.sh', '/opt/android/cake_wallet/scripts/android/build_haven.sh') }} - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} name: Generate Externals From 3bcaf06802af3ef6e646631d211cfa390b243f00 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 22 Dec 2022 23:35:56 +0200 Subject: [PATCH 185/203] Change key to be of the build scripts hash --- .github/workflows/cache_dependencies.yml | 2 +- .github/workflows/pr_test_build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml index 0887ed07d..9d49ed3d8 100644 --- a/.github/workflows/cache_dependencies.yml +++ b/.github/workflows/cache_dependencies.yml @@ -45,7 +45,7 @@ jobs: /opt/android/cake_wallet/cw_monero/android/.cxx /opt/android/cake_wallet/cw_monero/ios/External /opt/android/cake_wallet/cw_shared_external/ios/External - key: ${{ hashFiles('/opt/android/cake_wallet/scripts/android/build_monero.sh', '/opt/android/cake_wallet/scripts/android/build_haven.sh') }} + key: ${{ hashFiles('**/build_monero.sh', '**/build_haven.sh') }} - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} name: Generate Externals diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 83e430a32..00fd16199 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -45,7 +45,7 @@ jobs: /opt/android/cake_wallet/cw_monero/android/.cxx /opt/android/cake_wallet/cw_monero/ios/External /opt/android/cake_wallet/cw_shared_external/ios/External - key: ${{ hashFiles('/opt/android/cake_wallet/scripts/android/build_monero.sh', '/opt/android/cake_wallet/scripts/android/build_haven.sh') }} + key: ${{ hashFiles('**/build_monero.sh', '**/build_haven.sh') }} - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} name: Generate Externals From 89028500e7c83b66551c65914faf733f142c04e0 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 23 Dec 2022 23:58:39 +0200 Subject: [PATCH 186/203] extract SectionDivider widget --- .../screens/dashboard/widgets/filter_widget.dart | 13 +------------ .../monero_account_list_page.dart | 7 ++----- lib/src/screens/receive/receive_page.dart | 4 ++-- .../send/widgets/choose_yat_address_alert.dart | 6 ++---- .../screens/wallet_keys/wallet_keys_page.dart | 6 ++---- lib/src/widgets/base_alert_dialog.dart | 16 ++++------------ lib/src/widgets/section_divider.dart | 13 +++++++++++++ 7 files changed, 26 insertions(+), 39 deletions(-) create mode 100644 lib/src/widgets/section_divider.dart diff --git a/lib/src/screens/dashboard/widgets/filter_widget.dart b/lib/src/screens/dashboard/widgets/filter_widget.dart index 6831819e4..dd693777b 100644 --- a/lib/src/screens/dashboard/widgets/filter_widget.dart +++ b/lib/src/screens/dashboard/widgets/filter_widget.dart @@ -1,6 +1,7 @@ import 'dart:ui'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/filter_tile.dart'; +import 'package:cake_wallet/src/widgets/section_divider.dart'; import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:flutter/cupertino.dart'; @@ -141,15 +142,3 @@ class FilterWidget extends StatelessWidget { ); } } - -class SectionDivider extends StatelessWidget { - const SectionDivider(); - - @override - Widget build(BuildContext context) { - return Container( - height: 1, - color: Theme.of(context).dividerColor, - ); - } -} diff --git a/lib/src/screens/monero_accounts/monero_account_list_page.dart b/lib/src/screens/monero_accounts/monero_account_list_page.dart index 99134369e..c565332a0 100644 --- a/lib/src/screens/monero_accounts/monero_account_list_page.dart +++ b/lib/src/screens/monero_accounts/monero_account_list_page.dart @@ -1,4 +1,5 @@ import 'dart:ui'; +import 'package:cake_wallet/src/widgets/section_divider.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -83,11 +84,7 @@ class MoneroAccountListPage extends StatelessWidget { ListView.separated( padding: EdgeInsets.zero, controller: controller, - separatorBuilder: (context, index) => - Container( - height: 1, - color: Theme.of(context).dividerColor, - ), + separatorBuilder: (context, index) => SectionDivider(), itemCount: accounts.length ?? 0, itemBuilder: (context, index) { final account = accounts[index]; diff --git a/lib/src/screens/receive/receive_page.dart b/lib/src/screens/receive/receive_page.dart index 6f6b4e31c..4344139ac 100644 --- a/lib/src/screens/receive/receive_page.dart +++ b/lib/src/screens/receive/receive_page.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; +import 'package:cake_wallet/src/widgets/section_divider.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; @@ -135,8 +136,7 @@ class ReceivePage extends BasePage { Observer( builder: (_) => ListView.separated( padding: EdgeInsets.all(0), - separatorBuilder: (context, _) => Container( - height: 1, color: Theme.of(context).dividerColor), + separatorBuilder: (context, _) => SectionDivider(), shrinkWrap: true, physics: NeverScrollableScrollPhysics(), itemCount: addressListViewModel.items.length, diff --git a/lib/src/screens/send/widgets/choose_yat_address_alert.dart b/lib/src/screens/send/widgets/choose_yat_address_alert.dart index 93785743d..dae6c5ad7 100644 --- a/lib/src/screens/send/widgets/choose_yat_address_alert.dart +++ b/lib/src/screens/send/widgets/choose_yat_address_alert.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/src/widgets/cake_scrollbar.dart'; +import 'package:cake_wallet/src/widgets/section_divider.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/base_alert_dialog.dart'; @@ -70,10 +71,7 @@ class ChooseYatAddressButtonsState extends State { controller: controller, padding: EdgeInsets.all(0), itemCount: itemCount, - separatorBuilder: (_, __) => Container( - height: 1, - color: Theme.of(context).dividerColor, - ), + separatorBuilder: (_, __) => SectionDivider(), itemBuilder: (context, index) { final address = addresses[index]; diff --git a/lib/src/screens/wallet_keys/wallet_keys_page.dart b/lib/src/screens/wallet_keys/wallet_keys_page.dart index f97200e1e..b690cadda 100644 --- a/lib/src/screens/wallet_keys/wallet_keys_page.dart +++ b/lib/src/screens/wallet_keys/wallet_keys_page.dart @@ -1,4 +1,5 @@ import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cake_wallet/src/widgets/section_divider.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; @@ -57,10 +58,7 @@ class WalletKeysPage extends BasePage { height: 1, padding: EdgeInsets.only(left: 24), color: Theme.of(context).accentTextTheme!.headline6!.backgroundColor!, - child: Container( - height: 1, - color: Theme.of(context).dividerColor, - ), + child: SectionDivider(), ), itemCount: walletKeysViewModel.items.length, itemBuilder: (BuildContext context, int index) { diff --git a/lib/src/widgets/base_alert_dialog.dart b/lib/src/widgets/base_alert_dialog.dart index 70370e227..861d1ba9d 100644 --- a/lib/src/widgets/base_alert_dialog.dart +++ b/lib/src/widgets/base_alert_dialog.dart @@ -1,4 +1,5 @@ import 'dart:ui'; +import 'package:cake_wallet/src/widgets/section_divider.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; @@ -76,10 +77,7 @@ class BaseAlertDialog extends StatelessWidget { ), )), ), - Container( - width: 1, - color: Theme.of(context).dividerColor, - ), + SectionDivider(), Expanded( child: TextButton( onPressed: actionRight, @@ -140,10 +138,7 @@ class BaseAlertDialog extends StatelessWidget { isDividerExists ? Padding( padding: EdgeInsets.only(top: 16, bottom: 8), - child: Container( - height: 1, - color: Theme.of(context).dividerColor, - ), + child: SectionDivider(), ) : Offstage(), Padding( @@ -152,10 +147,7 @@ class BaseAlertDialog extends StatelessWidget { ) ], ), - Container( - height: 1, - color: Theme.of(context).dividerColor, - ), + SectionDivider(), actionButtons(context) ], ), diff --git a/lib/src/widgets/section_divider.dart b/lib/src/widgets/section_divider.dart new file mode 100644 index 000000000..bef85f975 --- /dev/null +++ b/lib/src/widgets/section_divider.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; + +class SectionDivider extends StatelessWidget { + const SectionDivider(); + + @override + Widget build(BuildContext context) { + return Container( + height: 1, + color: Theme.of(context).dividerColor, + ); + } +} \ No newline at end of file From d893562dad502b69c8dd2f3f196d34f1845f6fcc Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 24 Dec 2022 01:09:54 +0200 Subject: [PATCH 187/203] update localization --- .../dashboard/widgets/filter_widget.dart | 25 +++++++++---------- res/values/strings_de.arb | 2 +- res/values/strings_en.arb | 2 +- res/values/strings_es.arb | 2 +- res/values/strings_fr.arb | 2 +- res/values/strings_hi.arb | 2 +- res/values/strings_hr.arb | 2 +- res/values/strings_it.arb | 2 +- res/values/strings_ja.arb | 2 +- res/values/strings_ko.arb | 2 +- res/values/strings_nl.arb | 2 +- res/values/strings_pl.arb | 2 +- res/values/strings_pt.arb | 2 +- res/values/strings_ru.arb | 2 +- res/values/strings_uk.arb | 2 +- res/values/strings_zh.arb | 2 +- 16 files changed, 27 insertions(+), 28 deletions(-) diff --git a/lib/src/screens/dashboard/widgets/filter_widget.dart b/lib/src/screens/dashboard/widgets/filter_widget.dart index dd693777b..86682dcbc 100644 --- a/lib/src/screens/dashboard/widgets/filter_widget.dart +++ b/lib/src/screens/dashboard/widgets/filter_widget.dart @@ -108,19 +108,18 @@ class FilterWidget extends StatelessWidget { // .changeEndDate(picked.last); //} }, - child: Padding( - padding: EdgeInsets.only(left: 32), - child: Text( - item.caption, - style: TextStyle( - color: Colors.red, - //Theme.of(context).primaryTextTheme.title.color,// - fontSize: 18, - fontFamily: 'Lato', - fontWeight: FontWeight.w500, - decoration: TextDecoration.none), - ), - ), + // child: Padding( + // padding: EdgeInsets.only(left: 32), + // child: Text( + // item.caption, + // style: TextStyle( + // color: Theme.of(context).primaryTextTheme.title.color, + // fontSize: 18, + // fontFamily: 'Lato', + // fontWeight: FontWeight.w500, + // decoration: TextDecoration.none), + // ), + // ), ); return FilterTile(child: content); diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index bb01cdaba..152d3226e 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -48,7 +48,7 @@ "outgoing" : "Ausgehend", "transactions_by_date" : "Transaktionen nach Datum", "trades" : "Börsen", - "filters" : "Filtern nach", + "filter_by": "Filtern nach", "today" : "Heute", "yesterday" : "Gestern", "received" : "Empfangen", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 8cd6a3942..62306776f 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -48,7 +48,7 @@ "outgoing" : "Outgoing", "transactions_by_date" : "Transactions by date", "trades" : "Trades", - "filters" : "Filter by", + "filter_by": "Filter by", "today" : "Today", "yesterday" : "Yesterday", "received" : "Received", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 63fca7fbf..ef3eb6e06 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -48,7 +48,7 @@ "outgoing" : "Saliente", "transactions_by_date" : "Transacciones por fecha", "trades" : "Cambios", - "filters" : "Filtrado por", + "filter_by": "Filtrado por", "today" : "Hoy", "yesterday" : "Ayer", "received" : "Recibido", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index dc975ac24..2cd961cc1 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -46,7 +46,7 @@ "outgoing" : "Sortantes", "transactions_by_date" : "Transactions par date", "trades" : "Échanges", - "filters" : "Filtrer par", + "filter_by": "Filtrer par", "today" : "Aujourd'hui", "yesterday" : "Hier", "received" : "Reçus", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 7cb5ff132..947e1574f 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -48,7 +48,7 @@ "outgoing" : "निवर्तमान", "transactions_by_date" : "तारीख से लेन-देन", "trades" : "ट्रेडों", - "filters" : "के द्वारा छनित", + "filter_by": "के द्वारा छनित", "today" : "आज", "yesterday" : "बिता कल", "received" : "प्राप्त किया", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index b2696a3df..432cf8fd0 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -48,7 +48,7 @@ "outgoing" : "Odlazno", "transactions_by_date" : "Transakcije prema datumu", "trades" : "Razmjene", - "filters" : "Filtrirati po", + "filter_by": "Filtrirati po", "today" : "Danas", "yesterday" : "Jučer", "received" : "Primljeno", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index cb68d9ea6..218c6e33b 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -48,7 +48,7 @@ "outgoing" : "In uscita", "transactions_by_date" : "Transazioni per data", "trades" : "Scambi", - "filters" : "Filtrirati po", + "filter_by": "Filtrirati po", "today" : "Oggi", "yesterday" : "Ieri", "received" : "Ricevuto", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index f0d595c6e..6770d7f0c 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -48,7 +48,7 @@ "outgoing" : "発信", "transactions_by_date" : "日付ごとの取引", "trades" : "取引", - "filters" : "でフィルタリング", + "filter_by": "でフィルタリング", "today" : "今日", "yesterday" : "昨日", "received" : "受け取った", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index f4d289287..bef8c3477 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -48,7 +48,7 @@ "outgoing" : "나가는", "transactions_by_date" : "날짜 별 거래", "trades" : "거래", - "filters" : "필터링 기준", + "filter_by": "필터링 기준", "today" : "오늘", "yesterday" : "어제", "received" : "받았습니다", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 06c075092..706986be6 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -48,7 +48,7 @@ "outgoing" : "Uitgaande", "transactions_by_date" : "Transacties op datum", "trades" : "Trades", - "filters" : "Filteren op", + "filter_by": "Filteren op", "today" : "Vandaag", "yesterday" : "Gisteren", "received" : "Ontvangen", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 64e5f508b..1f708df9e 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -48,7 +48,7 @@ "outgoing" : "Towarzyski", "transactions_by_date" : "Transakcje według daty", "trades" : "Transakcje", - "filters" : "Filtruj według", + "filter_by": "Filtruj według", "today" : "Dzisiaj", "yesterday" : "Wczoraj", "received" : "Odebrane", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index b23aa20e8..909ce87e6 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -48,7 +48,7 @@ "outgoing" : "Enviadas", "transactions_by_date" : "Transações por data", "trades" : "Trocas", - "filters" : "Filtrar por", + "filter_by": "Filtrar por", "today" : "Hoje", "yesterday" : "Ontem", "received" : "Recebida", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 40f6ccdf0..f9376e6f1 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -48,7 +48,7 @@ "outgoing" : "Исходящие", "transactions_by_date" : "Сортировать по дате", "trades" : "Сделки", - "filters" : "Фильтровать по", + "filter_by": "Фильтровать по", "today" : "Сегодня", "yesterday" : "Вчера", "received" : "Полученные", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 9108c700d..030573c32 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -48,7 +48,7 @@ "outgoing" : "Вихідні", "transactions_by_date" : "Сортувати по даті", "trades" : "Торгові операції", - "filters" : "Фільтрувати по", + "filter_by": "Фільтрувати по", "today" : "Сьогодні", "yesterday" : "Вчора", "received" : "Отримані", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 4683bb068..b49880b21 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -48,7 +48,7 @@ "outgoing" : "发送", "transactions_by_date" : "按日期交易", "trades" : "交易", - "filters" : "过滤", + "filter_by": "过滤", "today" : "今天", "yesterday" : "昨天", "received" : "已收到", From ca79052914ca72253fd8e0e4b7b859f28ef96b71 Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 26 Dec 2022 20:41:21 +0200 Subject: [PATCH 188/203] PR fixes --- .../dashboard/widgets/filter_widget.dart | 2 +- lib/store/dashboard/trade_filter_store.dart | 91 +++++++++---------- .../dashboard/transaction_filter_store.dart | 56 +++++------- .../dashboard/dashboard_view_model.dart | 16 ++-- lib/view_model/dashboard/filter_item.dart | 2 +- 5 files changed, 79 insertions(+), 88 deletions(-) diff --git a/lib/src/screens/dashboard/widgets/filter_widget.dart b/lib/src/screens/dashboard/widgets/filter_widget.dart index 86682dcbc..cf6650301 100644 --- a/lib/src/screens/dashboard/widgets/filter_widget.dart +++ b/lib/src/screens/dashboard/widgets/filter_widget.dart @@ -82,7 +82,7 @@ class FilterWidget extends StatelessWidget { final content = item.onChanged != null ? Observer( builder: (_) => StandardCheckbox( - value: item.value.value, + value: item.value(), caption: item.caption, gradientBackground: true, borderColor: Theme.of(context).dividerColor, diff --git a/lib/store/dashboard/trade_filter_store.dart b/lib/store/dashboard/trade_filter_store.dart index 9c1dc9a9a..87fa749a9 100644 --- a/lib/store/dashboard/trade_filter_store.dart +++ b/lib/store/dashboard/trade_filter_store.dart @@ -8,60 +8,61 @@ part'trade_filter_store.g.dart'; class TradeFilterStore = TradeFilterStoreBase with _$TradeFilterStore; abstract class TradeFilterStoreBase with Store { - TradeFilterStoreBase(); + TradeFilterStoreBase() : displayXMRTO = true, + displayChangeNow = true, + displaySideShift = true, + displayMorphToken = true, + displaySimpleSwap = true; - Observable displayXMRTO = Observable(true); - Observable displayAllTrades = Observable(true); - Observable displayChangeNow = Observable(true); - Observable displaySideShift = Observable(true); - Observable displayMorphToken = Observable(true); - Observable displaySimpleSwap = Observable(true); + @observable + bool displayXMRTO; + + @observable + bool displayChangeNow; + + @observable + bool displaySideShift; + + @observable + bool displayMorphToken; + + @observable + bool displaySimpleSwap; + + @computed + bool get displayAllTrades => displayChangeNow && displaySideShift && displaySimpleSwap; @action void toggleDisplayExchange(ExchangeProviderDescription provider) { switch (provider) { case ExchangeProviderDescription.changeNow: - displayAllTrades.value = false; - displayChangeNow.value = !displayChangeNow.value; - if (displayChangeNow.value && displaySideShift.value && displaySimpleSwap.value) { - displayAllTrades.value = true; - } + displayChangeNow = !displayChangeNow; break; case ExchangeProviderDescription.sideShift: - displayAllTrades.value = false; - displaySideShift.value = !displaySideShift.value; - if (displayChangeNow.value && displaySideShift.value && displaySimpleSwap.value) { - displayAllTrades.value = true; - } + displaySideShift = !displaySideShift; break; case ExchangeProviderDescription.simpleSwap: - displayAllTrades.value = false; - displaySimpleSwap.value = !displaySimpleSwap.value; - if (displayChangeNow.value && displaySideShift.value && displaySimpleSwap.value) { - displayAllTrades.value = true; - } + displaySimpleSwap = !displaySimpleSwap; break; case ExchangeProviderDescription.xmrto: - displayXMRTO.value = !displayXMRTO.value; + displayXMRTO = !displayXMRTO; break; case ExchangeProviderDescription.morphToken: - displayMorphToken.value = !displayMorphToken.value; + displayMorphToken = !displayMorphToken; break; case ExchangeProviderDescription.all: - displayAllTrades.value = !displayAllTrades.value; - if (displayAllTrades.value) { - displayChangeNow.value = true; - displaySideShift.value = true; - displayXMRTO.value = true; - displayMorphToken.value = true; - displaySimpleSwap.value = true; - } - if (!displayAllTrades.value) { - displayChangeNow.value = false; - displaySideShift.value = false; - displayXMRTO.value = false; - displayMorphToken.value = false; - displaySimpleSwap.value = false; + if (displayAllTrades) { + displayChangeNow = false; + displaySideShift = false; + displayXMRTO = false; + displayMorphToken = false; + displaySimpleSwap = false; + } else { + displayChangeNow = true; + displaySideShift = true; + displayXMRTO = true; + displayMorphToken = true; + displaySimpleSwap = true; } break; } @@ -70,24 +71,22 @@ abstract class TradeFilterStoreBase with Store { List filtered({required List trades, required WalletBase wallet}) { final _trades = trades.where((item) => item.trade.walletId == wallet.id).toList(); - final needToFilter = !displayChangeNow.value || !displaySideShift.value - || !displayXMRTO.value || !displayMorphToken.value - || !displaySimpleSwap.value; + final needToFilter = !displayAllTrades; return needToFilter ? _trades .where((item) => - (displayXMRTO.value && + (displayXMRTO && item.trade.provider == ExchangeProviderDescription.xmrto) || - (displaySideShift.value && + (displaySideShift && item.trade.provider == ExchangeProviderDescription.sideShift) || - (displayChangeNow.value && + (displayChangeNow && item.trade.provider == ExchangeProviderDescription.changeNow) || - (displayMorphToken.value && + (displayMorphToken && item.trade.provider == ExchangeProviderDescription.morphToken) - ||(displaySimpleSwap.value && + ||(displaySimpleSwap && item.trade.provider == ExchangeProviderDescription.simpleSwap)) .toList() diff --git a/lib/store/dashboard/transaction_filter_store.dart b/lib/store/dashboard/transaction_filter_store.dart index 4198f7d8c..95264a23d 100644 --- a/lib/store/dashboard/transaction_filter_store.dart +++ b/lib/store/dashboard/transaction_filter_store.dart @@ -10,11 +10,14 @@ class TransactionFilterStore = TransactionFilterStoreBase with _$TransactionFilterStore; abstract class TransactionFilterStoreBase with Store { - TransactionFilterStoreBase(); + TransactionFilterStoreBase() : displayIncoming = true, + displayOutgoing = true; - Observable displayAll = Observable(true); - Observable displayIncoming = Observable(true); - Observable displayOutgoing = Observable(true); + @observable + bool displayIncoming; + + @observable + bool displayOutgoing; @observable DateTime? startDate; @@ -22,40 +25,30 @@ abstract class TransactionFilterStoreBase with Store { @observable DateTime? endDate; + @computed + bool get displayAll => displayIncoming && displayOutgoing; + @action - void toggleIAll() { - displayAll.value = (!displayAll.value); - if (displayAll.value) { - displayOutgoing.value = true; - displayIncoming.value = true; - } - if (!displayAll.value) { - displayOutgoing.value = false; - displayIncoming.value = false; + void toggleAll() { + if (displayAll) { + displayOutgoing = false; + displayIncoming = false; + } else { + displayOutgoing = true; + displayIncoming = true; } } + @action void toggleIncoming() { - displayIncoming.value = (!displayIncoming.value); - if (displayIncoming.value && displayOutgoing.value) { - displayAll.value = true; - } - if (!displayIncoming.value || !displayOutgoing.value) { - displayAll.value = false; - } + displayIncoming = !displayIncoming; } @action void toggleOutgoing() { - displayOutgoing.value = (!displayOutgoing.value); - if (displayIncoming.value && displayOutgoing.value) { - displayAll.value = true; - } - if (!displayIncoming.value || !displayOutgoing.value) { - displayAll.value = false; - } + displayOutgoing = !displayOutgoing; } @action @@ -66,8 +59,7 @@ abstract class TransactionFilterStoreBase with Store { List filtered({required List transactions}) { var _transactions = []; - final needToFilter = !displayOutgoing.value || - !displayIncoming.value || + final needToFilter = !displayAll || (startDate != null && endDate != null); if (needToFilter) { @@ -79,11 +71,11 @@ abstract class TransactionFilterStoreBase with Store { && (endDate?.isAfter(item.transaction.date) ?? false); } - if (allowed && (!displayOutgoing.value || !displayIncoming.value)) { - allowed = (displayOutgoing.value && + if (allowed && (!displayAll)) { + allowed = (displayOutgoing && item.transaction.direction == TransactionDirection.outgoing) || - (displayIncoming.value && + (displayIncoming && item.transaction.direction == TransactionDirection.incoming); } diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index ba0f9f8ff..57720d92f 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -59,15 +59,15 @@ abstract class DashboardViewModelBase with Store { filterItems = { S.current.transactions: [ FilterItem( - value: transactionFilterStore.displayAll, + value: () => transactionFilterStore.displayAll, caption: S.current.all_transactions, - onChanged: transactionFilterStore.toggleIAll), + onChanged: transactionFilterStore.toggleAll), FilterItem( - value: transactionFilterStore.displayIncoming, + value: () => transactionFilterStore.displayIncoming, caption: S.current.incoming, onChanged:transactionFilterStore.toggleIncoming), FilterItem( - value: transactionFilterStore.displayOutgoing, + value: () => transactionFilterStore.displayOutgoing, caption: S.current.outgoing, onChanged: transactionFilterStore.toggleOutgoing), // FilterItem( @@ -77,22 +77,22 @@ abstract class DashboardViewModelBase with Store { ], S.current.trades: [ FilterItem( - value: tradeFilterStore.displayAllTrades, + value: () => tradeFilterStore.displayAllTrades, caption: S.current.all_trades, onChanged: () => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.all)), FilterItem( - value: tradeFilterStore.displayChangeNow, + value: () => tradeFilterStore.displayChangeNow, caption: ExchangeProviderDescription.changeNow.title, onChanged: () => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.changeNow)), FilterItem( - value: tradeFilterStore.displaySideShift, + value: () => tradeFilterStore.displaySideShift, caption: ExchangeProviderDescription.sideShift.title, onChanged: () => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.sideShift)), FilterItem( - value: tradeFilterStore.displaySimpleSwap, + value: () => tradeFilterStore.displaySimpleSwap, caption: ExchangeProviderDescription.simpleSwap.title, onChanged: () => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.simpleSwap)), diff --git a/lib/view_model/dashboard/filter_item.dart b/lib/view_model/dashboard/filter_item.dart index 8bc0f0bf1..0944e899c 100644 --- a/lib/view_model/dashboard/filter_item.dart +++ b/lib/view_model/dashboard/filter_item.dart @@ -6,7 +6,7 @@ class FilterItem { required this.caption, required this.onChanged}); - Observable value; + bool Function() value; String caption; Function onChanged; } \ No newline at end of file From dec818a27a3f054c6b386e56bf661b85d9ae9d9f Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 26 Dec 2022 21:18:52 +0200 Subject: [PATCH 189/203] fix localisation key name --- lib/src/screens/dashboard/widgets/filter_widget.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/screens/dashboard/widgets/filter_widget.dart b/lib/src/screens/dashboard/widgets/filter_widget.dart index cf6650301..8dcc1b5c3 100644 --- a/lib/src/screens/dashboard/widgets/filter_widget.dart +++ b/lib/src/screens/dashboard/widgets/filter_widget.dart @@ -38,7 +38,7 @@ class FilterWidget extends StatelessWidget { Padding( padding: EdgeInsets.all(24.0), child: Text( - S.of(context).filters, + S.of(context).filter_by, style: TextStyle( color: Theme.of(context).primaryTextTheme.overline!.color!, fontSize: 16, From daa9fc4acc77e38f9919e9877cb78f7483a6b742 Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 28 Dec 2022 14:00:59 +0200 Subject: [PATCH 190/203] minor fixes --- .../dashboard/widgets/filter_widget.dart | 40 ++----------------- .../exchange_trade/exchange_trade_page.dart | 4 +- .../monero_account_list_page.dart | 3 +- .../order_details/order_details_page.dart | 6 +-- lib/src/screens/receive/receive_page.dart | 2 +- .../widgets/choose_yat_address_alert.dart | 2 +- .../trade_details/trade_details_page.dart | 6 +-- .../transaction_details_page.dart | 6 +-- .../unspent_coins_details_page.dart | 4 +- .../screens/wallet_keys/wallet_keys_page.dart | 6 +-- lib/src/widgets/base_alert_dialog.dart | 6 +-- .../{standard_list_row.dart => list_row.dart} | 4 +- 12 files changed, 28 insertions(+), 61 deletions(-) rename lib/src/widgets/{standard_list_row.dart => list_row.dart} (96%) diff --git a/lib/src/screens/dashboard/widgets/filter_widget.dart b/lib/src/screens/dashboard/widgets/filter_widget.dart index 8dcc1b5c3..17df0bc5e 100644 --- a/lib/src/screens/dashboard/widgets/filter_widget.dart +++ b/lib/src/screens/dashboard/widgets/filter_widget.dart @@ -20,7 +20,7 @@ class FilterWidget extends StatelessWidget { @override Widget build(BuildContext context) { - const sectionDivider = SectionDivider(); + const sectionDivider = const SectionDivider(); return AlertBackground( child: Stack( alignment: Alignment.center, @@ -79,8 +79,7 @@ class FilterWidget extends StatelessWidget { itemCount: section.length, itemBuilder: (_, index2) { final item = section[index2]; - final content = item.onChanged != null - ? Observer( + final content = Observer( builder: (_) => StandardCheckbox( value: item.value(), caption: item.caption, @@ -88,40 +87,7 @@ class FilterWidget extends StatelessWidget { borderColor: Theme.of(context).dividerColor, iconColor: Colors.white, onChanged: (value) => item.onChanged(), - )) - : GestureDetector( - onTap: () async { - //final List picked = - //await date_rage_picker.showDatePicker( - // context: context, - // initialFirstDate: DateTime.now() - // .subtract(Duration(days: 1)), - // initialLastDate: (DateTime.now()), - // firstDate: DateTime(2015), - // lastDate: DateTime.now() - // .add(Duration(days: 1))); - - //if (picked != null && picked.length == 2) { - // dashboardViewModel.transactionFilterStore - // .changeStartDate(picked.first); - // dashboardViewModel.transactionFilterStore - // .changeEndDate(picked.last); - //} - }, - // child: Padding( - // padding: EdgeInsets.only(left: 32), - // child: Text( - // item.caption, - // style: TextStyle( - // color: Theme.of(context).primaryTextTheme.title.color, - // fontSize: 18, - // fontFamily: 'Lato', - // fontWeight: FontWeight.w500, - // decoration: TextDecoration.none), - // ), - // ), - ); - + )); return FilterTile(child: content); }, ) diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index e3eb8db96..5aacf3f1f 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -8,7 +8,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart'; import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart'; -import 'package:cake_wallet/src/widgets/standard_list_row.dart'; +import 'package:cake_wallet/src/widgets/list_row.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart'; @@ -194,7 +194,7 @@ class ExchangeTradeState extends State { final item = widget.exchangeTradeViewModel.items[index]; final value = item.data ?? fetchingLabel; - final content = AnotherStandardListRow( + final content = ListRow( title: item.title, value: value, valueFontSize: 14, diff --git a/lib/src/screens/monero_accounts/monero_account_list_page.dart b/lib/src/screens/monero_accounts/monero_account_list_page.dart index c565332a0..7fe15948f 100644 --- a/lib/src/screens/monero_accounts/monero_account_list_page.dart +++ b/lib/src/screens/monero_accounts/monero_account_list_page.dart @@ -84,7 +84,8 @@ class MoneroAccountListPage extends StatelessWidget { ListView.separated( padding: EdgeInsets.zero, controller: controller, - separatorBuilder: (context, index) => SectionDivider(), + separatorBuilder: (context, index) => + const SectionDivider(), itemCount: accounts.length ?? 0, itemBuilder: (context, index) { final account = accounts[index]; diff --git a/lib/src/screens/order_details/order_details_page.dart b/lib/src/screens/order_details/order_details_page.dart index a7eff99b8..0784c7008 100644 --- a/lib/src/screens/order_details/order_details_page.dart +++ b/lib/src/screens/order_details/order_details_page.dart @@ -7,7 +7,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/standard_list_row.dart'; +import 'package:cake_wallet/src/widgets/list_row.dart'; import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart'; class OrderDetailsPage extends BasePage { @@ -57,7 +57,7 @@ class OrderDetailsPageBodyState extends State { if (item is TrackTradeListItem) { return GestureDetector( onTap: item.onTap, - child: AnotherStandardListRow( + child: ListRow( title: '${item.title}', value: '${item.value}')); } else { return GestureDetector( @@ -65,7 +65,7 @@ class OrderDetailsPageBodyState extends State { Clipboard.setData(ClipboardData(text: '${item.value}')); showBar(context, S.of(context).copied_to_clipboard); }, - child: AnotherStandardListRow( + child: ListRow( title: '${item.title}', value: '${item.value}')); } }); diff --git a/lib/src/screens/receive/receive_page.dart b/lib/src/screens/receive/receive_page.dart index 4344139ac..71ee578a0 100644 --- a/lib/src/screens/receive/receive_page.dart +++ b/lib/src/screens/receive/receive_page.dart @@ -136,7 +136,7 @@ class ReceivePage extends BasePage { Observer( builder: (_) => ListView.separated( padding: EdgeInsets.all(0), - separatorBuilder: (context, _) => SectionDivider(), + separatorBuilder: (context, _) => const SectionDivider(), shrinkWrap: true, physics: NeverScrollableScrollPhysics(), itemCount: addressListViewModel.items.length, diff --git a/lib/src/screens/send/widgets/choose_yat_address_alert.dart b/lib/src/screens/send/widgets/choose_yat_address_alert.dart index dae6c5ad7..5d937a571 100644 --- a/lib/src/screens/send/widgets/choose_yat_address_alert.dart +++ b/lib/src/screens/send/widgets/choose_yat_address_alert.dart @@ -71,7 +71,7 @@ class ChooseYatAddressButtonsState extends State { controller: controller, padding: EdgeInsets.all(0), itemCount: itemCount, - separatorBuilder: (_, __) => SectionDivider(), + separatorBuilder: (_, __) => const SectionDivider(), itemBuilder: (context, index) { final address = addresses[index]; diff --git a/lib/src/screens/trade_details/trade_details_page.dart b/lib/src/screens/trade_details/trade_details_page.dart index 1bb5d3ec8..1958a7d58 100644 --- a/lib/src/screens/trade_details/trade_details_page.dart +++ b/lib/src/screens/trade_details/trade_details_page.dart @@ -9,7 +9,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/standard_list_row.dart'; +import 'package:cake_wallet/src/widgets/list_row.dart'; import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart'; import 'package:cake_wallet/src/screens/trade_details/trade_details_list_card.dart'; import 'package:cake_wallet/src/screens/trade_details/trade_details_status_item.dart'; @@ -62,7 +62,7 @@ class TradeDetailsPageBodyState extends State { if (item is TrackTradeListItem) { return GestureDetector( onTap: item.onTap, - child: AnotherStandardListRow( + child: ListRow( title: '${item.title}', value: '${item.value}')); } @@ -86,7 +86,7 @@ class TradeDetailsPageBodyState extends State { Clipboard.setData(ClipboardData(text: '${item.value}')); showBar(context, S.of(context).copied_to_clipboard); }, - child: AnotherStandardListRow( + child: ListRow( title: '${item.title}', value: '${item.value}')); }); }); diff --git a/lib/src/screens/transaction_details/transaction_details_page.dart b/lib/src/screens/transaction_details/transaction_details_page.dart index 8d3ae8c9e..1b79ceeb0 100644 --- a/lib/src/screens/transaction_details/transaction_details_page.dart +++ b/lib/src/screens/transaction_details/transaction_details_page.dart @@ -6,7 +6,7 @@ import 'package:cake_wallet/view_model/transaction_details_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/widgets/standard_list_row.dart'; +import 'package:cake_wallet/src/widgets/list_row.dart'; import 'package:cake_wallet/src/screens/transaction_details/blockexplorer_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -42,7 +42,7 @@ class TransactionDetailsPage extends BasePage { S.of(context).transaction_details_copied(item.title)); }, child: - AnotherStandardListRow(title: '${item.title}:', value: item.value), + ListRow(title: '${item.title}:', value: item.value), ); } @@ -50,7 +50,7 @@ class TransactionDetailsPage extends BasePage { return GestureDetector( onTap: item.onTap, child: - AnotherStandardListRow(title: '${item.title}:', value: item.value), + ListRow(title: '${item.title}:', value: item.value), ); } diff --git a/lib/src/screens/unspent_coins/unspent_coins_details_page.dart b/lib/src/screens/unspent_coins/unspent_coins_details_page.dart index 74fbcfdd9..d8ce24d88 100644 --- a/lib/src/screens/unspent_coins/unspent_coins_details_page.dart +++ b/lib/src/screens/unspent_coins/unspent_coins_details_page.dart @@ -5,7 +5,7 @@ import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_details_view_model.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_switch_item.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/src/widgets/standard_list_row.dart'; +import 'package:cake_wallet/src/widgets/list_row.dart'; import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -30,7 +30,7 @@ class UnspentCoinsDetailsPage extends BasePage { final item = unspentCoinsDetailsViewModel.items[index]; if (item is StandartListItem) { - return AnotherStandardListRow( + return ListRow( title: '${item.title}:', value: item.value); } diff --git a/lib/src/screens/wallet_keys/wallet_keys_page.dart b/lib/src/screens/wallet_keys/wallet_keys_page.dart index b690cadda..e81ec7d2a 100644 --- a/lib/src/screens/wallet_keys/wallet_keys_page.dart +++ b/lib/src/screens/wallet_keys/wallet_keys_page.dart @@ -7,7 +7,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/standard_list_row.dart'; +import 'package:cake_wallet/src/widgets/list_row.dart'; import 'package:cake_wallet/view_model/wallet_keys_view_model.dart'; class WalletKeysPage extends BasePage { @@ -58,7 +58,7 @@ class WalletKeysPage extends BasePage { height: 1, padding: EdgeInsets.only(left: 24), color: Theme.of(context).accentTextTheme!.headline6!.backgroundColor!, - child: SectionDivider(), + child: const SectionDivider(), ), itemCount: walletKeysViewModel.items.length, itemBuilder: (BuildContext context, int index) { @@ -69,7 +69,7 @@ class WalletKeysPage extends BasePage { Clipboard.setData(ClipboardData(text: item.value)); showBar(context, S.of(context).copied_key_to_clipboard(item.title)); }, - child: AnotherStandardListRow( + child: ListRow( title: item.title + ':', value: item.value, ), diff --git a/lib/src/widgets/base_alert_dialog.dart b/lib/src/widgets/base_alert_dialog.dart index 861d1ba9d..effbbc562 100644 --- a/lib/src/widgets/base_alert_dialog.dart +++ b/lib/src/widgets/base_alert_dialog.dart @@ -77,7 +77,7 @@ class BaseAlertDialog extends StatelessWidget { ), )), ), - SectionDivider(), + const SectionDivider(), Expanded( child: TextButton( onPressed: actionRight, @@ -138,7 +138,7 @@ class BaseAlertDialog extends StatelessWidget { isDividerExists ? Padding( padding: EdgeInsets.only(top: 16, bottom: 8), - child: SectionDivider(), + child: const SectionDivider(), ) : Offstage(), Padding( @@ -147,7 +147,7 @@ class BaseAlertDialog extends StatelessWidget { ) ], ), - SectionDivider(), + const SectionDivider(), actionButtons(context) ], ), diff --git a/lib/src/widgets/standard_list_row.dart b/lib/src/widgets/list_row.dart similarity index 96% rename from lib/src/widgets/standard_list_row.dart rename to lib/src/widgets/list_row.dart index e174acc50..40824fe59 100644 --- a/lib/src/widgets/standard_list_row.dart +++ b/lib/src/widgets/list_row.dart @@ -1,8 +1,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -class AnotherStandardListRow extends StatelessWidget { - AnotherStandardListRow( +class ListRow extends StatelessWidget { + ListRow( {required this.title, required this.value, this.titleFontSize = 14, From d9ec7978b689d392fe9cd2a613be930025dfa05b Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 28 Dec 2022 22:20:37 +0200 Subject: [PATCH 191/203] Add test variables to workflow for external PR support --- .github/workflows/pr_test_build.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 00fd16199..3a439c556 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -8,6 +8,9 @@ jobs: test: runs-on: ubuntu-18.04 + env: + STORE_PASS: test@cake_wallet + KEY_PASS: test@cake_wallet steps: - uses: actions/checkout@v2 @@ -63,12 +66,12 @@ jobs: - name: Generate KeyStore run: | cd /opt/android/cake_wallet/android/app - keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass ${{ secrets.STORE_PASS }} -keypass ${{ secrets.KEY_PASS }} + keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS - name: Generate key properties run: | cd /opt/android/cake_wallet - flutter packages pub run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=${{ secrets.STORE_PASS }} keyPassword=${{ secrets.KEY_PASS }} + flutter packages pub run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=$STORE_PASS keyPassword=$KEY_PASS - name: Generate localization run: | @@ -141,6 +144,7 @@ jobs: path: /opt/android/cake_wallet/build/app/outputs/apk/release/test-apk/ - name: Send Test APK + continue-on-error: true run: | cd /opt/android/cake_wallet var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/$GITHUB_HEAD_REF.apk -H "Max-Days: 10") From 033560cf3ac777f4be7afef6e63581d77398782a Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 29 Dec 2022 03:52:40 +0200 Subject: [PATCH 192/203] Test upgrading haven repo --- scripts/android/build_haven.sh | 2 +- scripts/ios/build_haven.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/android/build_haven.sh b/scripts/android/build_haven.sh index 6d22f7778..5f3c9e50a 100755 --- a/scripts/android/build_haven.sh +++ b/scripts/android/build_haven.sh @@ -1,7 +1,7 @@ #!/bin/sh . ./config.sh -HAVEN_VERSION=tags/v2.2.2 +HAVEN_VERSION=tags/v3.0.0 HAVEN_SRC_DIR=${WORKDIR}/haven git clone https://github.com/haven-protocol-org/haven-main.git ${HAVEN_SRC_DIR} diff --git a/scripts/ios/build_haven.sh b/scripts/ios/build_haven.sh index cc79d7a26..3199e3286 100755 --- a/scripts/ios/build_haven.sh +++ b/scripts/ios/build_haven.sh @@ -4,7 +4,7 @@ HAVEN_URL="https://github.com/haven-protocol-org/haven-main.git" HAVEN_DIR_PATH="${EXTERNAL_IOS_SOURCE_DIR}/haven" -HAVEN_VERSION=tags/v2.2.2 +HAVEN_VERSION=tags/v3.0.0 BUILD_TYPE=release PREFIX=${EXTERNAL_IOS_DIR} DEST_LIB_DIR=${EXTERNAL_IOS_LIB_DIR}/haven From 17751f236336a6736548298cd5d86328c164200e Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 29 Dec 2022 16:02:09 +0200 Subject: [PATCH 193/203] Fix haven currencies not getting serialized --- cw_core/lib/crypto_currency.dart | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index 42e72d2eb..3ee2b5e15 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -67,6 +67,22 @@ class CryptoCurrency extends EnumerableItem with Serializable { CryptoCurrency.stx, ]; + static const havenCurrencies = [ + xag, + xau, + xaud, + xbtc, + xcad, + xchf, + xcny, + xeur, + xgbp, + xjpy, + xnok, + xnzd, + xusd, + ]; + static const xmr = CryptoCurrency(title: 'XMR', iconPath: 'assets/images/monero_icon.png', fullName: 'Monero', raw: 0, name: 'xmr'); static const ada = CryptoCurrency(title: 'ADA', iconPath: 'assets/images/ada_icon.png', fullName: 'Cardano', raw: 1, name: 'ada'); static const bch = CryptoCurrency(title: 'BCH', iconPath: 'assets/images/bch_icon.png',fullName: 'Bitcoin Cash', raw: 2, name: 'bch'); @@ -134,16 +150,16 @@ class CryptoCurrency extends EnumerableItem with Serializable { static const stx = CryptoCurrency(title: 'STX', iconPath: 'assets/images/stx_icon.png', raw: 61, name: 'stx'); static final Map _rawCurrencyMap = - all.fold>({}, (acc, item) { - acc.addAll({item.raw: item}); - return acc; - }); + [...all, ...havenCurrencies].fold>({}, (acc, item) { + acc.addAll({item.raw: item}); + return acc; + }); static final Map _nameCurrencyMap = - all.fold>({}, (acc, item) { - acc.addAll({item.name: item}); - return acc; - }); + [...all, ...havenCurrencies].fold>({}, (acc, item) { + acc.addAll({item.name: item}); + return acc; + }); static CryptoCurrency deserialize({required int raw}) { From 286269a9e8e2c7d4f10a672211ad6972df395770 Mon Sep 17 00:00:00 2001 From: john_r365 <67366109+johnr365@users.noreply.github.com> Date: Sat, 31 Dec 2022 20:03:24 +0000 Subject: [PATCH 194/203] Changes to language file section of README.md --- README.md | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c5f6dc1b2..f485ca244 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,24 @@ For instructions on how to build for Android: please view file `howto-build-andr Edit the applicable `strings_XX.arb` file in `res/values/` and open a pull request with the changes. +## Current list of language files: + +- English +- Spanish +- French +- German +- Italian +- Portugese +- Dutch +- Polish +- Croatian +- Russian +- Ukranian +- Hindi +- Japanese +- Chinese +- Korean + ## Add a new language 1. Create a new `strings_XX.arb` file in `res/values/`, replacing XX with the language's [ISO 639-1 code](https://en.wikipedia.org/wiki/ISO_639-1). @@ -91,9 +109,15 @@ Edit the applicable `strings_XX.arb` file in `res/values/` and open a pull reque `"welcome" : "Welcome to",` -> `"welcome" : "XXX",` -3. Add the language to `lib/entities/language_service.dart` under both `supportedLocales` and `localeCountryCode`. Use the name of the language in the local language and in English in parentheses after for `supportedLocales`. Use the [ISO 3166-1 alpha-3 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) for `localeCountryCode`. You must choose one country, so choose the country with the most native speakers of this language or is otherwise best associated with this language. +3. For strings where there is a variable, denoted by a $ symbol and braces, such as ${status}, the string in braces should not be translated. For example, when editing line 106: -4. Add a relevant flag to `assets/images/flags/XXXX.png`, replacing XXXX with the 3 digit localeCountryCode. The image must be 42x36 pizxels with a 3 pixels of transparent margin on all 4 sides. +"time" : "${minutes}m ${seconds}s" + +The only parts to be translated, if needed, are the values m and s after the variables. + +4. Add the language to `lib/entities/language_service.dart` under both `supportedLocales` and `localeCountryCode`. Use the name of the language in the local language and in English in parentheses after for `supportedLocales`. Use the [ISO 3166-1 alpha-3 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) for `localeCountryCode`. You must choose one country, so choose the country with the most native speakers of this language or is otherwise best associated with this language. + +5. Add a relevant flag to `assets/images/flags/XXXX.png`, replacing XXXX with the 3 digit localeCountryCode. The image must be 42x36 pizxels with a 3 pixels of transparent margin on all 4 sides. ## Add a new fiat currency @@ -103,4 +127,4 @@ Edit the applicable `strings_XX.arb` file in `res/values/` and open a pull reque 3. Add the raw mapping underneath in `lib/entities/fiat_currency.dart` following the same format as the others. -4. Add a flag of the issuing country or organization to `assets/images/flags/XXXX.png`, replacing XXXX with the ISO 3166-1 alpha-3 code used above (eg: `usa.png`, `eur.png`). Do not add this if the flag with the same name already exists. The image must be 42x36 pizxels with a 3 pixels of transparent margin on all 4 sides. +4. Add a flag of the issuing country or organization to `assets/images/flags/XXXX.png`, replacing XXXX with the ISO 3166-1 alpha-3 code used above (eg: `usa.png`, `eur.png`). Do not add this if the flag with the same name already exists. The image must be 42x36 pizxels with a 3 pixels of transparent margin on all 4 sides. \ No newline at end of file From 993e8b7ebf763450aabb8574bc7c65f4e94813c9 Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 3 Jan 2023 23:59:08 +0200 Subject: [PATCH 195/203] fix disappearance of pending transaction --- cw_bitcoin/lib/electrum_transaction_history.dart | 6 ++---- cw_bitcoin/lib/electrum_transaction_info.dart | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/cw_bitcoin/lib/electrum_transaction_history.dart b/cw_bitcoin/lib/electrum_transaction_history.dart index f8662eb95..9174fb3f8 100644 --- a/cw_bitcoin/lib/electrum_transaction_history.dart +++ b/cw_bitcoin/lib/electrum_transaction_history.dart @@ -72,7 +72,7 @@ abstract class ElectrumTransactionHistoryBase txs.entries.forEach((entry) { final val = entry.value; - if (val is Map) { + if (val is Map) { final tx = ElectrumTransactionInfo.fromJson(val, walletInfo.type); _updateOrInsert(tx); } @@ -85,9 +85,6 @@ abstract class ElectrumTransactionHistoryBase } void _updateOrInsert(ElectrumTransactionInfo transaction) { - if (transaction.id == null) { - return; - } if (transactions[transaction.id] == null) { transactions[transaction.id] = transaction; @@ -98,6 +95,7 @@ abstract class ElectrumTransactionHistoryBase originalTx?.height = transaction.height; originalTx?.date ??= transaction.date; originalTx?.isPending = transaction.isPending; + originalTx?.direction = transaction.direction; } } } diff --git a/cw_bitcoin/lib/electrum_transaction_info.dart b/cw_bitcoin/lib/electrum_transaction_info.dart index 6e85a2f88..8d6ef0fea 100644 --- a/cw_bitcoin/lib/electrum_transaction_info.dart +++ b/cw_bitcoin/lib/electrum_transaction_info.dart @@ -228,9 +228,7 @@ class ElectrumTransactionInfo extends TransactionInfo { m['id'] = id; m['height'] = height; m['amount'] = amount; - // FIX-ME: Hardcoded value - // m['direction'] = direction.index; - m['direction'] = 0; + m['direction'] = direction.index; m['date'] = date.millisecondsSinceEpoch; m['isPending'] = isPending; m['confirmations'] = confirmations; From 38b21e325410c429b7f2e754df84a225c75ea6b0 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 4 Jan 2023 20:39:36 +0200 Subject: [PATCH 196/203] new version - cake wallet: v4.5.6 - monero: v1.2.5 --- scripts/android/app_env.sh | 8 ++++---- scripts/ios/app_env.sh | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 979a60e9d..c74d97c0f 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -14,14 +14,14 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.2.4" -MONERO_COM_BUILD_NUMBER=35 +MONERO_COM_VERSION="1.2.5" +MONERO_COM_BUILD_NUMBER=36 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.5.5" -CAKEWALLET_BUILD_NUMBER=140 +CAKEWALLET_VERSION="4.5.6" +CAKEWALLET_BUILD_NUMBER=141 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 1965d1e41..8588bfcb2 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.2.4" -MONERO_COM_BUILD_NUMBER=32 +MONERO_COM_VERSION="1.2.5" +MONERO_COM_BUILD_NUMBER=33 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.5.5" -CAKEWALLET_BUILD_NUMBER=137 +CAKEWALLET_VERSION="4.5.6" +CAKEWALLET_BUILD_NUMBER=138 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" From 7551181b09be0fe8a9d511f5d5324ed3ac898a95 Mon Sep 17 00:00:00 2001 From: rosedaler <121954045+maddymodd@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:39:08 -0500 Subject: [PATCH 197/203] Add thai language localization file --- lib/entities/language_service.dart | 6 +- res/values/strings_th.arb | 678 +++++++++++++++++++++++++++++ 2 files changed, 682 insertions(+), 2 deletions(-) create mode 100644 res/values/strings_th.arb diff --git a/lib/entities/language_service.dart b/lib/entities/language_service.dart index 7dccc59c0..3b5f68eb5 100644 --- a/lib/entities/language_service.dart +++ b/lib/entities/language_service.dart @@ -18,7 +18,8 @@ class LanguageService { 'uk': 'Українська (Ukrainian)', 'zh': '中文 (Chinese)', 'hr': 'Hrvatski (Croatian)', - 'it': 'Italiano (Italian)' + 'it': 'Italiano (Italian)', + 'th': 'ภาษาไทย (Thai)' }; static const Map localeCountryCode = { @@ -36,7 +37,8 @@ class LanguageService { 'uk': 'ukr', 'zh': 'chn', 'hr': 'hrv', - 'it': 'ita' + 'it': 'ita', + 'th': 'tha' }; static final list = {}; diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb new file mode 100644 index 000000000..f39025e3d --- /dev/null +++ b/res/values/strings_th.arb @@ -0,0 +1,678 @@ +{ + "welcome" : "ยินดีต้อนรับสู่", + "cake_wallet" : "Cake Wallet", + "first_wallet_text" : "กระเป๋าสตางค์ที่สวยงามสำหรับ Monero, Bitcoin, Litecoin และ Haven", + "please_make_selection" : "โปรดเลือกตามด้านล่างเพื่อสร้างหรือกู้กระเป๋าของคุณ", + "create_new" : "สร้างกระเป๋าใหม่", + "restore_wallet" : "กู้กระเป๋า", + + "monero_com": "Monero.com ของ Cake Wallet", + "monero_com_wallet_text": "กระเป๋าสตางค์ที่สวยงามสำหรับ Monero", + + "haven_app": "Haven ของ Cake Wallet", + "haven_app_wallet_text": "กระเป๋าสตางค์ที่สวยงามสำหรับ Haven", + + "accounts" : "บัญชี", + "edit" : "แก้ไข", + "account" : "บัญชี", + "add" : "เพิ่ม", + + + "address_book" : "สมุดที่อยู่", + "contact" : "ผู้ติดต่อ", + "please_select" : "โปรดเลือก:", + "cancel" : "ยกเลิก", + "ok" : "ตกลง", + "contact_name" : "ชื่อผู้ติดต่อ", + "reset" : "รีเซ็ต", + "save" : "บันทึก", + "address_remove_contact" : "ลบผู้ติดต่อ", + "address_remove_content" : "คุณแน่ใจหรือว่าต้องการลบผู้ติดต่อที่เลือก?", + + + "authenticated" : "ได้รับการยืนยันสิทธิ์", + "authentication" : "การยืนยันสิทธิ์", + "failed_authentication" : "การยืนยันสิทธิ์ล้มเหลว ${state_error}", + + + "wallet_menu" : "เมนู", + "Blocks_remaining" : "${status} บล็อกที่เหลืออยู่", + "please_try_to_connect_to_another_node" : "โปรดลองเชื่อมต่อกับโหนดอื่น", + "xmr_hidden" : "ซ่อน", + "xmr_available_balance" : "ยอดคงเหลือที่สามารถใช้งานได้", + "xmr_full_balance" : "ยอดคงเหลือแบบเต็ม", + "send" : "ส่ง", + "receive" : "รับ", + "transactions" : "ธุรกรรม", + "incoming" : "ขาเข้า", + "outgoing" : "ขาออก", + "transactions_by_date" : "ธุรกรรมตามวันที่", + "trades" : "การซื้อขาย", + "filter_by": "กรองตาม", + "today" : "วันนี้", + "yesterday" : "เมื่อวาน", + "received" : "รับ", + "sent" : "ส่ง", + "pending" : " (อยู่ระหว่างดำเนินการ)", + "rescan" : "สแกนใหม่", + "reconnect" : "เชื่อมต่อใหม่", + "wallets" : "กระเป๋า", + "show_seed" : "แสดงซีด", + "show_keys" : "แสดงซีด/คีย์", + "address_book_menu" : "สมุดที่อยู่", + "reconnection" : "เชื่อมต่อใหม่", + "reconnect_alert_text" : "คุณแน่ใจหรือไม่ว่าต้องการเชื่อมต่อใหม่?", + + + "exchange" : "แลกเปลี่ยน", + "clear" : "ล้าง", + "refund_address" : "ที่อยู่สำหรับส่งคืน", + "change_exchange_provider" : "เปลี่ยนผู้ให้บริการแลกเปลี่ยน", + "you_will_send" : "แปลงจาก", + "you_will_get" : "แปลงเป็น", + "amount_is_guaranteed" : "จำนวนที่จะได้รับมีการรับประกัน", + "amount_is_estimate" : "จำนวนที่จะได้รับเป็นการประมาณการ", + "powered_by" : "พัฒนาขึ้นโดย ${title}", + "error" : "ข้อผิดพลาด", + "estimated" : "ประมาณการ", + "min_value" : "ขั้นต่ำ: ${value} ${currency}", + "max_value" : "ขั้นสูง: ${value} ${currency}", + "change_currency" : "เปลี่ยนสกุลเงิน", + "overwrite_amount" : "เขียนทับจำนวน", + "qr_payment_amount" : "QR code นี้มีจำนวนการชำระเงิน คุณต้องการเขียนทับค่าปัจจุบันหรือไม่?", + + "copy_id" : "คัดลอก ID", + "exchange_result_write_down_trade_id" : "โปรดคัดลอกหรือบันทึก ID ของการซื้อขายเพื่อดำเนินการต่อไป", + "trade_id" : "ID การซื้อขาย:", + "copied_to_clipboard" : "คัดลอกไปยังหน่วยความจำของคอมพิวเตอร์", + "saved_the_trade_id" : "ฉันได้บันทึก ID ของการซื้อขายแล้ว", + "fetching" : "กำลังโหลด", + "id" : "ID: ", + "amount" : "จำนวน: ", + "payment_id" : "ID การชำระเงิน: ", + "status" : "สถานะ: ", + "offer_expires_in" : "ข้อเสนอจะหมดอายุใน: ", + "trade_is_powered_by" : "การซื้อขายนี้จัดสร้างโดย ${provider}", + "copy_address" : "คัดลอกที่อยู่", + "exchange_result_confirm" : "โดยกดปุ่มยืนยัน, คุณจะส่ง ${fetchingLabel} ${from} จากกระเป๋าของคุณที่เรียกว่า ${walletName} ไปยังที่อยู่ที่แสดงข้างล่าง หรือคุณสามารถส่งจากกระเป๋าภายนอกไปยังที่อยู่/รหัส QR ด้านล่าง\n\nโปรดกดปุ่มยืนยันเพื่อดำเนินการต่อหรือกลับไปเปลี่ยนจำนวน", + "exchange_result_description" : "คุณต้องส่งอย่างน้อย ${fetchingLabel} ${from} ไปยังที่อยู่ที่แสดงบนหน้าถัดไป หากคุณส่งจำนวนน้อยกว่า ${fetchingLabel} ${from} อาจจะไม่ถูกแปลงและอาจไม่ถูกเรียกคืน", + "exchange_result_write_down_ID" : "*โปรดคัดลอกหรือเขียนรหัสของคุณด้านบน", + "confirm" : "ยืนยัน", + "confirm_sending" : "ยืนยันการส่ง", + "commit_transaction_amount_fee" : "ยืนยันธุรกรรม\nจำนวน: ${amount}\nค่าธรรมเนียม: ${fee}", + "sending" : "กำลังส่ง", + "transaction_sent" : "ธุรกรรมถูกส่ง!", + "expired" : "หมดอายุ", + "time" : "${minutes}m ${seconds}s", + "send_xmr" : "ส่ง XMR", + "exchange_new_template" : "เทมเพลทใหม่", + + "faq" : "คำถามที่พบบ่อย", + + + "enter_your_pin" : "ใส่ PIN ของคุณ", + "loading_your_wallet" : "กำลังโหลดกระเป๋าของคุณ", + + + "new_wallet" : "กระเป๋าใหม่", + "wallet_name" : "ชื่อกระเป๋า", + "continue_text" : "ดำเนินการต่อ", + "choose_wallet_currency" : "โปรดเลือกสกุลเงินของกระเป๋า:", + + + "node_new" : "โหนดใหม่", + "node_address" : "ที่อยู่โหนด", + "node_port" : "พอร์ตโหนด", + "login" : "เข้าสู่ระบบ", + "password" : "รหัสผ่าน", + "nodes" : "โหนด", + "node_reset_settings_title" : "รีเซ็ตการตั้งค่า", + "nodes_list_reset_to_default_message" : "คุณแน่ใจหรือว่าต้องการรีเซ็ตการตั้งค่าเป็นค่าเริ่มต้น?", + "change_current_node" : "คุณแน่ใจหรือว่าต้องการเปลี่ยนโหนดปัจจุบันเป็น ${node}?", + "change" : "เปลี่ยน", + "remove_node" : "ลบโหนด", + "remove_node_message" : "คุณแน่ใจหรือว่าต้องการลบโหนดที่เลือก?", + "remove" : "ลบ", + "delete" : "ลบ", + "add_new_node" : "เพิ่มโหนดใหม่", + "change_current_node_title" : "เปลี่ยนโหนดปัจจุบัน", + "node_test" : "ทดสอบ", + "node_connection_successful" : "เชื่อมต่อสำเร็จ", + "node_connection_failed" : "เชื่อมต่อล้มเหลว", + "new_node_testing" : "การทดสอบโหนดใหม่", + + + "use" : "สลับไปที่ ", + "digit_pin" : "-หลัก PIN", + + + "share_address" : "แชร์ที่อยู่", + "receive_amount" : "จำนวน", + "subaddresses" : "ที่อยู่ย่อย", + "addresses" : "ที่อยู่", + "scan_qr_code" : "สแกน QR code เพื่อรับที่อยู่", + "qr_fullscreen" : "แตะเพื่อเปิดหน้าจอ QR code แบบเต็มจอ", + "rename" : "เปลี่ยนชื่อ", + "choose_account" : "เลือกบัญชี", + "create_new_account" : "สร้างบัญชีใหม่", + "accounts_subaddresses" : "บัญชีและที่อยู่ย่อย", + + + "restore_restore_wallet" : "กู้กระเป๋า", + "restore_title_from_seed_keys" : "กู้จาก seed/keys", + "restore_description_from_seed_keys" : "เรียกกระเป๋าของคุณกลับมาจาก seed/keys ที่คุณได้บันทึกไว้ในที่ปลอดภัย", + "restore_next" : "ถัดไป", + "restore_title_from_backup" : "กู้จากการสำรองข้อมูล", + "restore_description_from_backup" : "คุณสามารถกู้แอพ Cake Wallet ทั้งหมดจากไฟล์สำรองข้อมูลของคุณ", + "restore_seed_keys_restore" : "กู้จาก Seed/Keys", + "restore_title_from_seed" : "กู้จาก seed", + "restore_description_from_seed" : "กู้กระเป๋าของคุณจากรหัสผสมของ 25 คำหรือ 13 คำ", + "restore_title_from_keys" : "กู้จาก keys", + "restore_description_from_keys" : "กู้กระเป๋าของคุณจากการกดปุ่มที่สร้างขึ้นจาก private keys ของคุณที่บันทึกไว้", + "restore_wallet_name" : "ชื่อกระเป๋า", + "restore_address" : "ที่อยู่", + "restore_view_key_private" : "คีย์สำหรับดู (ส่วนตัว)", + "restore_spend_key_private" : "คีย์สำหรับใช้ (ส่วนตัว)", + "restore_recover" : "กู้", + "restore_wallet_restore_description" : "คำอธิบายการกู้กระเป๋า", + "restore_new_seed" : "ซีดใหม่", + "restore_active_seed" : "ซีดที่ใช้งานอยู่", + "restore_bitcoin_description_from_seed" : "กู้กระเป๋าของคุณจากรหัสผสมของ 24 คำ", + "restore_bitcoin_description_from_keys" : "กู้กระเป๋าของคุณจากสตริง WIF ที่สร้างขึ้นจากคีย์ส่วนตัวของคุณ", + "restore_bitcoin_title_from_keys" : "กู้จาก WIF", + "restore_from_date_or_blockheight" : "โปรดป้อนวันที่หลายวันก่อนที่คุณสร้างกระเป๋านี้ หรือหากคุณรู้ความสูงของบล็อก (blockheight) โปรดป้อนมันแทน", + + + "seed_reminder" : "โปรดเขียนข้อมูลนี้ลงสมุดเพื่อความปลอดภัยหากคุณสูญเสียหรือล้างโทรศัพท์ของคุณ", + "seed_title" : "Seed", + "seed_share" : "แบ่งปัน seed", + "copy" : "คัดลอก", + + + "seed_language_choose" : "โปรดเลือกภาษาของ seed:", + "seed_choose" : "เลือกภาษาของ seed", + "seed_language_next" : "ถัดไป", + "seed_language_english" : "อังกฤษ", + "seed_language_chinese" : "จีน", + "seed_language_dutch" : "ดัตช์", + "seed_language_german" : "เยอรมัน", + "seed_language_japanese" : "ญี่ปุ่น", + "seed_language_portuguese" : "โปรตุเกส", + "seed_language_russian" : "รัสเซีย", + "seed_language_spanish" : "สเปน", + "seed_language_french" : "ฝรั่งเศส", + "seed_language_italian" : "อิตาลี", + + + "send_title" : "ส่ง", + "send_your_wallet" : "กระเป๋าของคุณ", + "send_address" : "ที่อยู่ ${cryptoCurrency}", + "send_payment_id" : "ID การชำระเงิน (ไม่จำเป็น)", + "all" : "ทั้งหมด", + "send_error_minimum_value" : "จำนวนขั้นต่ำของจำนวนเงินคือ 0.01", + "send_error_currency" : "สกุลเงินสามารถเป็นเลขเท่านั้น", + "send_estimated_fee" : "ค่าธรรมเนียมที่คาดการณ์:", + "send_priority" : "ในขณะนี้ค่าธรรมเนียมถูกตั้งค่าเป็นความสำคัญ ${transactionPriority} \nความสำคัญของธุรกรรมสามารถปรับได้ในการตั้งค่า", + "send_creating_transaction" : "กำลังสร้างธุรกรรม", + "send_templates" : "แม่แบบ", + "send_new" : "ใหม่", + "send_amount" : "จำนวน:", + "send_fee" : "ค่าธรรมเนียม:", + "send_name" : "ชื่อ", + "send_got_it" : "เข้าใจ", + "send_sending" : "กำลังส่ง...", + "send_success" : "คุณได้ส่ง ${crypto} เรียบร้อยแล้ว", + + + "settings_title" : "การตั้งค่า", + "settings_nodes" : "จุดเชื่อมต่อ", + "settings_current_node" : "จุดเชื่อมต่อปัจจุบัน", + "settings_wallets" : "กระเป๋าสตางค์", + "settings_display_balance" : "แสดงยอดคงเหลือ", + "settings_currency" : "สกุลเงิน", + "settings_fee_priority" : "ความสำคัญของค่าธรรมเนียม", + "settings_save_recipient_address" : "บันทึกที่อยู่ผู้รับ", + "settings_personal" : "ส่วนตัว", + "settings_change_pin" : "เปลี่ยน PIN", + "settings_change_language" : "เปลี่ยนภาษา", + "settings_allow_biometrical_authentication" : "อนุญาตให้ใช้การยืนยันตัวตนทางระบบชีวภาพ", + "settings_dark_mode" : "โหมดดำ", + "settings_transactions" : "ธุรกรรม", + "settings_trades" : "การซื้อขาย", + "settings_display_on_dashboard_list" : "แสดงบนรายการแดชบอร์ด", + "settings_all" : "ทั้งหมด", + "settings_only_trades" : "เฉพาะการซื้อขาย", + "settings_only_transactions" : "เฉพาะธุรกรรม", + "settings_none" : "ไม่มี", + "settings_support" : "สนับสนุน", + "settings_terms_and_conditions" : "ข้อกำหนดและเงื่อนไข", + "pin_is_incorrect" : "PIN ไม่ถูกต้อง", + + + "setup_pin" : "ตั้งค่า PIN", + "enter_your_pin_again" : "ใส่ PIN ของคุณอีกครั้ง", + "setup_successful" : "การตั้งค่า PIN ของคุณสำเร็จแล้ว!", + + "wallet_keys" : "ซีดของกระเป๋า/คีย์", + "wallet_seed" : "ซีดของกระเป๋า", + "private_key" : "คีย์ส่วนตัว", + "public_key" : "คีย์สาธารณะ", + "view_key_private" : "คีย์มุมมอง (ส่วนตัว)", + "view_key_public" : "คีย์มุมมอง (สาธารณะ)", + "spend_key_private" : "คีย์จ่าย (ส่วนตัว)", + "spend_key_public" : "คีย์จ่าย (สาธารณะ)", + "copied_key_to_clipboard" : "คัดลอก ${key} ไปยัง Clipboard แล้ว" + + + "new_subaddress_title" : "ที่อยู่ใหม่", + "new_subaddress_label_name" : "ชื่อป้ายกำกับ", + "new_subaddress_create" : "สร้าง", + + "address_label" : "ป้ายกำกับที่อยู่", + + "subaddress_title" : "รายการที่อยู่ย่อย", + + "trade_details_title" : "รายละเอียดการแลกเปลี่ยน", + "trade_details_id" : "รหัส", + "trade_details_state" : "สถานะ", + "trade_details_fetching" : "กำลังเรียกข้อมูล", + "trade_details_provider" : "ผู้ให้บริการ", + "trade_details_created_at" : "สร้างเมื่อ", + "trade_details_pair" : "คู่", + "trade_details_copied" : "${title} คัดลอกไปยัง Clipboard" + + + "trade_history_title" : "ประวัติการซื้อขาย", + + + "transaction_details_title" : "รายละเอียดการทำรายการ", + "transaction_details_transaction_id" : "ไอดีการทำรายการ", + "transaction_details_date" : "วันที่", + "transaction_details_height" : "ความสูง", + "transaction_details_amount" : "จำนวน", + "transaction_details_fee" : "ค่าธรรมเนียม", + "transaction_details_copied" : "${title} ถูกคัดลอกไปยังคลิปบอร์ด", + "transaction_details_recipient_address" : "ที่อยู่ผู้รับ", + + + "wallet_list_title" : "กระเป๋า Monero", + "wallet_list_create_new_wallet" : "สร้างกระเป๋าใหม่", + "wallet_list_restore_wallet" : "กู้กระเป๋า", + "wallet_list_load_wallet" : "โหลดกระเป๋า", + "wallet_list_loading_wallet" : "กำลังโหลดกระเป๋า ${wallet_name}", + "wallet_list_failed_to_load" : "ไม่สามารถโหลดกระเป๋า ${wallet_name} ได้ ${error}", + "wallet_list_removing_wallet" : "กำลังลบกระเป๋า ${wallet_name}", + "wallet_list_failed_to_remove" : "ไม่สามารถลบกระเป๋า ${wallet_name} ได้ ${error}", + + + "widgets_address" : "ที่อยู่", + "widgets_restore_from_blockheight" : "กู้คืนจากระดับบล็อก", + "widgets_restore_from_date" : "กู้คืนจากวันที่", + "widgets_or" : "หรือ", + "widgets_seed" : "ซีด", + + + "router_no_route" : "ไม่มีเส้นทางที่กำหนดไว้สำหรับ ${name}", + + + "error_text_account_name" : "ชื่อบัญชีสามารถเป็นเพียงตัวอักษรหรือตัวเลขเท่านั้น\nและต้องมีความยาวระหว่าง 1 ถึง 15 ตัวอักษร", + "error_text_contact_name" : "ชื่อผู้ติดต่อไม่สามารถมีสัญลักษณ์ ` , '\" ได้\nและต้องมีความยาวระหว่าง 1 ถึง 32 ตัวอักษร", + "error_text_address" : "ที่อยู่กระเป๋าจะต้องสอดคล้องกับประเภท\nของเหรียญคริปโตเนียม", + "error_text_node_address" : "โปรดป้อนที่อยู่ iPv4", + "error_text_node_port" : "พอร์ตโหนดสามารถมีตัวเลขเท่านั้นระหว่าง 0 ถึง 65535", + "error_text_payment_id" : "Payment ID สามารถมีขนาดระหว่าง 16 ถึง 64 ตัวอักษรตามแบบ hex", + "error_text_xmr" : "มูลค่า XMR ไม่สามารถเกินยอดคงเหลือได้\nจำนวนสตริงทศนิยมต้องน้อยกว่าหรือเท่ากับ 12", + "error_text_fiat" : "มูลค่าของจำนวนเงินไม่สามารถเกินยอดคงเหลือได้\nจำนวนสตริงทศนิยมต้องน้อยกว่าหรือเท่ากับ 2", + "error_text_subaddress_name" : "ชื่อสำหรับที่อยู่ย่อยจะต้องประกอบด้วยตัวอักษร ตัวเลข และสัญลักษณ์ _ - และมีความยาวระหว่าง 1 ถึง 20 ตัวอักษร", + "error_text_amount" : "จำนวนจะต้องประกอบด้วยตัวเลขเท่านั้น", + "error_text_wallet_name" : "ชื่อกระเป๋าสตางค์จะต้องประกอบด้วยตัวอักษร ตัวเลข และสัญลักษณ์ _ - และมีความยาวระหว่าง 1 ถึง 33 ตัวอักษร", + "error_text_keys" : "คีย์ของกระเป๋าสตางค์จะต้องประกอบด้วยตัวอักษรฐาน 16 จำนวน 64 ตัว", + "error_text_crypto_currency" : "จำนวนทศนิยมจะต้องน้อยกว่าหรือเท่ากับ 12", + "error_text_minimal_limit" : "การซื้อขายกับ ${provider} ไม่สามารถดำเนินการได้ จำนวนน้อยกว่าขั้นต่ำ: ${min} ${currency}", + "error_text_maximum_limit" : "การซื้อขายกับ ${provider} ไม่สามารถดำเนินการได้ จำนวนมากกว่าขั้นสูง: ${max} ${currency}", + "error_text_limits_loading_failed" : "การซื้อขายกับ ${provider} ไม่สามารถดำเนินการได้ ไม่สามารถโหลดขอบเขตได้", + "error_text_template" : "ชื่อแม่แบบและที่อยู่ไม่สามารถมีสัญลักษณ์ ` , '\" และต้องมีความยาวระหว่าง 1 ถึง 106 ตัวอักษร", + + + "auth_store_ban_timeout" : "หมดเวลาห้าม", + "auth_store_banned_for" : "ถูกห้ามสำหรับ ", + "auth_store_banned_minutes" : " นาที", + "auth_store_incorrect_password" : "รหัสผ่านไม่ถูกต้อง", + "wallet_store_monero_wallet" : "กระเป๋า Monero", + "wallet_restoration_store_incorrect_seed_length" : "ความยาวของซีดไม่ถูกต้อง", + + + "full_balance" : "ยอดคงเหลือทั้งหมด", + "available_balance" : "ยอดคงเหลือที่ใช้งานได้", + "hidden_balance" : "ยอดคงเหลือซ่อนอยู่", + + + "sync_status_syncronizing" : "กำลังซิงโครไนซ์", + "sync_status_syncronized" : "ซิงโครไนซ์แล้ว", + "sync_status_not_connected" : "ไม่ได้เชื่อมต่อ", + "sync_status_starting_sync" : "กำลังเริ่มซิงโครไนซ์", + "sync_status_failed_connect" : "การเชื่อมต่อล้มเหลว", + "sync_status_connecting" : "กำลังเชื่อมต่อ", + "sync_status_connected" : "เชื่อมต่อแล้ว", + "sync_status_attempting_sync" : "พยายามซิงโครไนซ์", + + + "transaction_priority_slow" : "ช้า", + "transaction_priority_regular" : "ปกติ", + "transaction_priority_medium" : "ปานกลาง", + "transaction_priority_fast" : "เร็ว", + "transaction_priority_fastest" : "เร็วที่สุด", + + + "trade_for_not_created" : "การแลกเปลี่ยนสำหรับ ${title} ยังไม่ได้ถูกสร้างขึ้น", + "trade_not_created" : "การแลกเปลี่ยนยังไม่ได้ถูกสร้าง", + "trade_id_not_found" : "ไม่พบการแลกเปลี่ยน ${tradeId} ของ ${title}", + "trade_not_found" : "ไม่พบการแลกเปลี่ยน", + + + "trade_state_pending" : "รอดำเนินการ", + "trade_state_confirming" : "กำลังยืนยัน", + "trade_state_trading" : "กำลังแลกเปลี่ยน", + "trade_state_traded" : "ถูกแลกเปลี่ยน", + "trade_state_complete" : "เสร็จสมบูรณ์", + "trade_state_to_be_created" : "จะถูกสร้าง", + "trade_state_unpaid" : "ยังไม่ได้จ่าย", + "trade_state_underpaid" : "จ่ายไม่ครบ", + "trade_state_paid_unconfirmed" : "จ่ายแล้วแต่ยังไม่ได้ยืนยัน", + "trade_state_paid" : "จ่ายแล้ว", + "trade_state_btc_sent" : "ส่ง BTC แล้ว", + "trade_state_timeout" : "เวลาหมด", + "trade_state_created" : "ถูกสร้าง", + "trade_state_finished" : "เสร็จสิ้น", + + "change_language" : "เปลี่ยนภาษา", + "change_language_to" : "เปลี่ยนภาษาเป็น ${language}?", + + "paste" : "วาง", + "restore_from_seed_placeholder" : "โปรดป้อนหรือวาง seed ของคุณที่นี่", + "add_new_word" : "เพิ่มคำใหม่", + "incorrect_seed" : "ข้อความที่ป้อนไม่ถูกต้อง", + + "biometric_auth_reason" : "สแกนลายนิ้วมือของคุณเพื่อยืนยันตัวตน", + "version" : "เวอร์ชัน ${currentVersion}", + + "openalias_alert_title" : "พบที่อยู่", + "openalias_alert_content" : "คุณกำลังจะส่งเงินไปยัง\n${recipient_name}", + + "card_address" : "ที่อยู่:", + "buy" : "ซื้อ", + "sell": "ขาย", + + "placeholder_transactions" : "ธุรกรรมของคุณจะปรากฏที่นี่", + "placeholder_contacts" : "รายชื่อผู้ติดต่อของคุณจะปรากฏที่นี่", + + "template" : "แบบฟอร์ม", + "confirm_delete_template" : "การดำเนินการนี้จะลบแบบฟอร์มนี้ คุณต้องการดำเนินการต่อหรือไม่?", + "confirm_delete_wallet" : "การดำเนินการนี้จะลบกระเป๋านี้ คุณต้องการดำเนินการต่อหรือไม่?", + + "picker_description" : "ในการเลือก ChangeNOW หรือ MorphToken โปรดเปลี่ยนคู่แลกเปลี่ยนก่อน", + + "change_wallet_alert_title" : "เปลี่ยนกระเป๋าปัจจุบัน", + "change_wallet_alert_content" : "คุณต้องการเปลี่ยนกระเป๋าปัจจุบันเป็น ${wallet_name} หรือไม่?", + + "creating_new_wallet" : "กำลังสร้างกระเป๋าใหม่", + "creating_new_wallet_error" : "ข้อผิดพลาด: ${description}", + + "seed_alert_title" : "ความสนใจ", + "seed_alert_content" : "Seed เป็นเพียงวิธีเดียวที่จะกู้กระเป๋าของคุณ คุณได้เขียนมันขึ้นลงกระดาษหรือไม่?", + "seed_alert_back" : "กลับ", + "seed_alert_yes" : "ใช่ ฉันได้เขียน", + + "exchange_sync_alert_content" : "โปรดรอจนกว่ากระเป๋าของคุณจะถูกซิงค์", + + "pre_seed_title" : "สำคัญ", + "pre_seed_description" : "บนหน้าถัดไปคุณจะเห็นชุดของคำ ${words} คำ นี่คือ seed ของคุณที่ไม่ซ้ำใดๆ และเป็นความลับเพียงของคุณ และนี่คือเพียงวิธีเดียวที่จะกู้กระเป๋าของคุณในกรณีที่สูญหายหรือมีปัญหา มันเป็นความรับผิดชอบของคุณเพื่อเขียนมันลงบนกระดาษและจัดเก็บไว้ในที่ปลอดภัยนอกแอป Cake Wallet", + "pre_seed_button_text" : "ฉันเข้าใจ แสดง seed ของฉัน", + + "xmr_to_error" : "ข้อผิดพลาด XMR.TO", + "xmr_to_error_description" : "จำนวนไม่ถูกต้อง จำกัดขั้นสูง 8 หลักหลังจุดทศนิยม", + + "provider_error" : "ข้อผิดพลาด ${provider}", + + "use_ssl" : "ใช้ SSL", + "trusted" : "มั่นคง", + + "color_theme" : "ธีมสี", + "light_theme" : "สว่าง", + "bright_theme" : "สดใส", + "dark_theme" : "เข้ม", + "enter_your_note" : "ใส่บันทึกของคุณ...", + "note_optional" : "บันทึก (ไม่จำเป็น)", + "note_tap_to_change" : "หมายเหตุ (กดเพื่อเปลี่ยน)", + "view_in_block_explorer" : "ดูใน Block Explorer", + "view_transaction_on" : "ดูการทำธุรกรรมบน ", + "transaction_key" : "รหัสธุรกรรม", + "confirmations" : "การยืนยัน", + "recipient_address" : "ที่อยู่ผู้รับ", + + "extra_id" : "ไอดีเพิ่มเติม:", + "destination_tag" : "แท็กปลายทาง:", + "memo" : "หมายเหตุ:", + + "backup" : "สำรองข้อมูล", + "change_password" : "เปลี่ยนรหัสผ่าน", + "backup_password" : "รหัสผ่านสำรองข้อมูล", + "write_down_backup_password" : "โปรดจดรหัสผ่านสำรองข้อมูลของคุณลงบนกระดาษ ซึ่งจะใช้ในการนำเข้าไฟล์สำรองข้อมูลของคุณ", + "export_backup" : "ส่งออกข้อมูลสำรอง", + "save_backup_password" : "โปรดตรวจสอบให้แน่ใจว่าคุณได้บันทึกรหัสผ่านสำรองข้อมูลแล้ว คุณจะไม่สามารถนำเข้าไฟล์สำรองข้อมูลของคุณโดยไม่ใช้รหัสผ่านนั้น", + "backup_file" : "ไฟล์สำรองข้อมูล", + + "edit_backup_password" : "แก้ไขรหัสผ่านสำรอง", + "save_backup_password_alert" : "บันทึกรหัสผ่านสำรอง", + "change_backup_password_alert" : "ไฟล์สำรองที่ผ่านมาจะไม่สามารถนำเข้าด้วยรหัสผ่านสำรองใหม่ได้ รหัสผ่านสำรองใหม่จะถูกใช้เฉพาะสำหรับไฟล์สำรองใหม่ คุณแน่ใจหรือว่าต้องการเปลี่ยนรหัสผ่านสำรอง?", + + "enter_backup_password" : "ป้อนรหัสผ่านสำรองที่นี่", + "select_backup_file" : "เลือกไฟล์สำรอง", + "import" : "นำเข้า", + "please_select_backup_file" : "โปรดเลือกไฟล์สำรองและป้อนรหัสผ่านสำรอง", + + "fixed_rate": "อัตราคงที่", + "fixed_rate_alert": "คุณจะสามารถป้อนจำนวนที่ได้รับเมื่อเลือกโหมดอัตราคงที่ คุณต้องการสลับไปที่โหมดอัตราคงที่?", + + "xlm_extra_info": "โปรดอย่าลืมระบุ Memo ID ในขณะที่ส่งธุรกรรม XLM สำหรับการแลกเปลี่ยน", + "xrp_extra_info": "โปรดอย่าลืมระบุ Destination Tag ในขณะที่ส่งธุรกรรม XRP สำหรับการแลกเปลี่ยน", + + "exchange_incorrect_current_wallet_for_xmr" : "หากคุณต้องการแลกเปลี่ยน XMR จากยอดคงเหลือ Monero ใน Cake Wallet ของคุณ กรุณาเปลี่ยนเป็นกระเป๋า Monero ก่อน", + "confirmed" : "ได้รับการยืนยัน", + "unconfirmed" : "ยังไม่ได้รับการยืนยัน", + "displayable" : "สามารถแสดงได้", + + "submit_request" : "ส่งคำขอ", + + "buy_alert_content" : "ในปัจจุบันเรารองรับการซื้อ Bitcoin และ Litecoin เท่านั้น หากต้องการซื้อ Bitcoin หรือ Litecoin โปรดสร้างหรือเปลี่ยนเป็นกระเป๋า Bitcoin หรือ Litecoin ของคุณ", + "sell_alert_content" : "ในปัจจุบันเรารองรับการขาย Bitcoin เท่านั้น หากต้องการขาย Bitcoin โปรดสร้างหรือเปลี่ยนเป็นกระเป๋า Bitcoin ของคุณ", + + "outdated_electrum_wallet_description" : "กระเป๋า Bitcoin ใหม่ที่สร้างใน Cake มี seed ขนาด 24 คำ ซึ่งจำเป็นต้องสร้างกระเป๋า Bitcoin ใหม่และโอนทุกเงินของคุณไปยังกระเป๋าใหม่ขนาด 24 คำ และหยุดใช้กระเป๋าที่มี seed ขนาด 12 คำ กรุณาทำด่วนเพื่อรักษาเงินของคุณ", + "understand" : "ฉันเข้าใจ", + + "apk_update" : "ปรับปรุง APK", + + "buy_bitcoin" : "ซื้อ Bitcoin", + "buy_with" : "ซื้อด้วย", + "moonpay_alert_text" : "มูลค่าของจำนวนต้องมากกว่าหรือเท่ากับ ${minAmount} ${fiatCurrency}", + + "outdated_electrum_wallet_receive_warning": "หากกระเป๋านี้มีซีดีที่มี 12 คำและถูกสร้างขึ้นใน Cake อย่าโอน Bitcoin เข้ากระเป๋านี้ ทุกจำนวน BTC ที่โอนเข้ากระเป๋านี้อาจสูญหาย สร้างกระเป๋าใหม่ที่มีซีดีที่มี 24 คำ (กดที่เมนูที่มุมขวาบนแล้วเลือก Wallets และเลือก Create New Wallet จากนั้นเลือก Bitcoin) และย้าย BTC ไปที่นั้นทันที กระเป๋า BTC ที่มีซีดีที่มี 24 คำของ Cake ปลอดภัย", + "do_not_show_me": "อย่าแสดงข้อความนี้อีก", + + "unspent_coins_title" : "เหรียญที่ไม่ได้ใช้", + "unspent_coins_details_title" : "รายละเอียดเหรียญที่ไม่ได้ใช้", + "freeze" : "ดักจับ", + "frozen" : "ถูกดักจับ", + "coin_control" : "การควบคุมเหรียญ (ตัวเลือก)", + + "address_detected" : "ตรวจพบที่อยู่", + "address_from_domain" : "ที่อยู่นี้มาจาก ${domain} บน Unstoppable Domains", + + "add_receiver" : "เพิ่มผู้รับอื่น ๆ (ตัวเลือก)", + + "manage_yats" : "จัดการ Yats", + "yat_alert_title" : "ส่งและรับเหรียญออนไลน์ง่ายขึ้นด้วย Yat", + "yat_alert_content" : "ผู้ใช้งาน Cake Wallet สามารถส่งและรับเหรียญออนไลน์ทุกเหรียญที่ชื่นชอบของพวกเขาได้ง่ายขึ้นด้วยชื่อผู้ใช้งานที่พิเศษที่ระบุด้วยอีโมจิ", + "get_your_yat" : "รับ Yat ของคุณ", + "connect_an_existing_yat" : "เชื่อมต่อ Yat ที่มีอยู่", + "connect_yats": "เชื่อมต่อ Yats", + "yat_address" : "ที่อยู่ Yat", + "yat" : "Yat", + "address_from_yat" : "ที่อยู่นี้มาจาก ${emoji} บน Yat", + "yat_error" : "ข้อผิดพลาดของ Yat", + "yat_error_content" : "ไม่มีที่อยู่ที่เชื่อมต่อกับ Yat นี้ ลองใช้ Yat อื่น", + "choose_address" : "\n\nโปรดเลือกที่อยู่:", + "yat_popup_title" : "ที่อยู่กระเป๋าของคุณสามารถถูกอัปโหลดเป็นอิโมจิ", + "yat_popup_content" : "ขณะนี้คุณสามารถส่งและรับเหรียญคริปโตใน Cake Wallet ด้วย Yat ของคุณ - ชื่อผู้ใช้ที่สั้นมีอิโมจิ คุณสามารถจัดการ Yat ได้ทุกเวลาบนหน้าจอการตั้งค่า", + "second_intro_title" : "อิโมจิที่อยู่เดียวที่จะควบคุมพวกเขาทั้งหมด", + "second_intro_content" : "Yat ของคุณเป็นอิโมจิที่อยู่เดียวที่จะแทนที่ทุกที่อยู่และเลขฐานสิบหกของคุณสำหรับเหรียญคริปโตทุกชนิด", + "third_intro_title" : "Yat ปฏิบัติตนอย่างดีกับผู้อื่น", + "third_intro_content" : "Yat อาศัยอยู่นอก Cake Wallet ด้วย ที่อยู่กระเป๋าใดๆ ทั่วโลกสามารถแทนด้วย Yat ได้อีกด้วย!" + "learn_more" : "ศึกษาเพิ่มเติม", + "search": "ค้นหา", + "search_language": "ค้นหาภาษา", + "search_currency": "ค้นหาสกุลเงิน", + "new_template" : "แม่แบบใหม่", + "electrum_address_disclaimer": "เราสร้างที่อยู่ใหม่ทุกครั้งที่คุณใช้หนึ่งอย่าง แต่ที่อยู่เก่ายังสามารถใช้ได้ต่อไป", + "wallet_name_exists": "กระเป๋าที่มีชื่อนี้มีอยู่แล้ว โปรดเลือกชื่ออื่นหรือเปลี่ยนชื่อกระเป๋าอื่นก่อน", + "market_place": "ตลาดพื้นที่", + "cake_pay_title": "บัตรของขวัญ Cake Pay", + "cake_pay_subtitle": "ซื้อบัตรของขวัญราคาถูก (สำหรับสหรัฐอเมริกาเท่านั้น)", + "cake_pay_web_cards_title": "Cake Pay Web Cards", + "cake_pay_web_cards_subtitle": "ซื้อบัตรพร้อมเงินระดับโลกและบัตรของขวัญ", + "about_cake_pay": "Cake Pay ช่วยให้คุณสามารถซื้อบัตรของขวัญง่ายๆ ด้วยการใช้สินทรัพย์อนุกรม ซื้อใช้ได้ทันทีกับมากกว่า 150,000 ร้านค้าในสหรัฐอเมริกา", + "cake_pay_account_note": "ลงทะเบียนด้วยอีเมลเพียงอย่างเดียวเพื่อดูและซื้อบัตร บางบัตรอาจมีส่วนลด!", + "already_have_account": "มีบัญชีอยู่แล้ว?", + "create_account": "สร้างบัญชี", + "privacy_policy": "นโยบายความเป็นส่วนตัว", + "welcome_to_cakepay": "ยินดีต้อนรับสู่ Cake Pay!", + "sign_up": "สมัครสมาชิก", + "forgot_password": "ลืมรหัสผ่าน", + "reset_password": "รีเซ็ตรหัสผ่าน", + "gift_cards": "บัตรของขวัญ", + "setup_your_debit_card": "ตั้งค่าบัตรเดบิตของคุณ", + "no_id_required": "ไม่จำเป็นต้องใช้บัตรประจำตัว ฝากเงินและใช้งานได้ทุกที่", + "how_to_use_card": "วิธีใช้บัตรนี้", + "purchase_gift_card": "ซื้อบัตรของขวัญ", + "verification": "การตรวจสอบ", + "fill_code": "โปรดกรอกรหัสยืนยันที่ส่งไปยังอีเมลของคุณ", + "dont_get_code": "ไม่ได้รับรหัส?", + "resend_code": "โปรดส่งอีกครั้ง", + "debit_card": "บัตรเดบิต", + "cakepay_prepaid_card": "บัตรเดบิตเติมเงินของ CakePay", + "no_id_needed": "ไม่จำเป็นต้องใช้บัตรประชาชน!", + "frequently_asked_questions": "คำถามที่พบบ่อย", + "debit_card_terms": "การเก็บรักษาและใช้หมายเลขบัตรจ่ายเงิน (และข้อมูลประจำตัวที่เกี่ยวข้องกับหมายเลขบัตรจ่ายเงิน) ในกระเป๋าดิจิทัลนี้ จะต้องยึดถือข้อกำหนดและเงื่อนไขของข้อตกลงผู้ใช้บัตรของผู้ถือบัตรที่เกี่ยวข้องกับบัตรผู้ถือบัตร ซึ่งจะมีผลตั้งแต่เวลานั้น", + "please_reference_document": "โปรดอ้างอิงเอกสารด้านล่างสำหรับข้อมูลเพิ่มเติม", + "cardholder_agreement": "ข้อตกลงผู้ใช้บัตร", + "e_sign_consent": "การยอมรับ E-Sign", + "agree_and_continue": "ยอมรับและดำเนินการต่อ", + "email_address": "ที่อยู่อีเมล", + "agree_to": "การสร้างบัญชีของคุณยอมรับเงื่อนไขของ", + "and": "และ", + "enter_code": "กรอกรหัส", + "congratulations": "ขอแสดงความยินดี!", + "you_now_have_debit_card": "ขณะนี้คุณมีบัตรเดบิต", + "min_amount": "จำนวนขั้นต่ำ: ${value}", + "max_amount": "จำนวนสูงสุด: ${value}", + "enter_amount": "กรอกจำนวน", + "billing_address_info": "ถ้าถูกร้องขอที่อยู่สำหรับการวางบิล ให้ใช้ที่อยู่จัดส่งของคุณ", + "order_physical_card": "สั่งซื้อบัตรดิบิต", + "add_value": "เพิ่มมูลค่า", + "activate": "เปิดใช้งาน", + "get_a": "รับ " + "digital_and_physical_card": "บัตรเดบิตดิจิตอลและบัตรพื้นฐาน", + "get_card_note": "ที่คุณสามารถเติมเงินด้วยสกุลเงินดิจิตอล ไม่จำเป็นต้องใส่ข้อมูลเพิ่มเติม!", + "signup_for_card_accept_terms": "ลงทะเบียนสำหรับบัตรและยอมรับเงื่อนไข", + "add_fund_to_card": "เพิ่มเงินสำรองไว้บนบัตร (ถึง ${value})", + "use_card_info_two": "เงินจะถูกแปลงค่าเป็นดอลลาร์สหรัฐเมื่อถือไว้ในบัญชีสำรองเงิน ไม่ใช่สกุลเงินดิจิตอล", + "use_card_info_three": "ใช้บัตรดิจิตอลออนไลน์หรือผ่านวิธีการชำระเงินแบบไม่ต้องใช้บัตรกระดาษ", + "hide_details" : "ซ่อนรายละเอียด", + "show_details" : "แสดงรายละเอียด", + "upto": "สูงสุด ${value}", + "discount": "ประหยัด ${value}%", + "gift_card_amount": "จำนวนบัตรของขวัญ", + "bill_amount": "จำนวนบิล", + "you_pay": "คุณจ่าย", + "tip": "เพิ่มค่าตอบแทน:", + "custom": "กำหนดเอง", + "by_cake_pay": "โดย Cake Pay", + "expires": "หมดอายุ", + "mm": "เดือน", + "yy": "ปี", + "online": "ออนไลน์", + "offline": "ออฟไลน์", + "gift_card_number": "หมายเลขบัตรของขวัญ", + "pin_number": "หมายเลข PIN", + "total_saving": "ประหยัดรวม", + "last_30_days": "30 วันล่าสุด", + "avg_savings": "ประหยัดเฉลี่ย", + "view_all": "ดูทั้งหมด", + "active_cards": "บัตรที่ใช้งานได้", + "delete_account": "ลบบัญชี", + "cards": "บัตร", + "active": "ทำงาน", + "redeemed": "แลกของขวัญ", + "gift_card_balance_note": "บัตรของขวัญที่มียอดคงเหลือจะปรากฏที่นี่", + "gift_card_redeemed_note": "บัตรของขวัญที่คุณแลกไปแล้วจะปรากฏที่นี่", + "logout": "ออกจากระบบ", + "add_tip": "เพิ่มคำแนะนำ", + "percentageOf": "${amount} ของ", + "is_percentage": "เป็น", + "search_category": "ค้นหาหมวดหมู่", + "mark_as_redeemed": "ทำเครื่องหมายว่าเคยใช้แล้ว", + "more_options": "ตัวเลือกเพิ่มเติม", + "awaiting_payment_confirmation": "รอการยืนยันการชำระเงิน", + "transaction_sent_notice": "ถ้าหน้าจอไม่ขึ้นหลังจาก 1 นาทีแล้ว ให้ตรวจสอบ block explorer และอีเมลของคุณ", + "agree": "ยอมรับ", + "in_store": "ในร้าน", + "generating_gift_card": "กำลังสร้างบัตรของขวัญ", + "payment_was_received": "การชำระเงินของคุณได้รับการรับทราบแล้ว", + "proceed_after_one_minute": "หากหน้าจอไม่ดำเนินการหลังจาก 1 นาทีโปรดตรวจสอบอีเมลของคุณ", + "order_id": "เลขที่ออร์เดอร์", + "gift_card_is_generated": "บัตรของขวัญถูกสร้างขึ้น", + "open_gift_card": "เปิดบัตรของขวัญ", + "contact_support": "ติดต่อฝ่ายสนับสนุน", + "gift_cards_unavailable": "บัตรของขวัญจะมีจำหน่ายเฉพาะกับ Monero, Bitcoin, และ Litecoin เท่านั้นในขณะนี้", + "introducing_cake_pay": "ยินดีต้อนรับสู่ Cake Pay!", + "cake_pay_learn_more": "ซื้อและเบิกบัตรของขวัญในแอพพลิเคชันทันที!\nกระแทกขวาไปซ้ายเพื่อเรียนรู้เพิ่มเติม", + "automatic": "อัตโนมัติ", + "fixed_pair_not_supported": "คู่ความสัมพันธ์ที่ถูกกำหนดไว้นี้ไม่สนับสนุนกับหุ้นที่เลือก", + "variable_pair_not_supported": "คู่ความสัมพันธ์ที่เปลี่ยนแปลงได้นี้ไม่สนับสนุนกับหุ้นที่เลือก", + "none_of_selected_providers_can_exchange": "ไม่มีผู้ให้บริการที่เลือกที่สามารถแลกเปลี่ยนนี้ได้", + "choose_one": "เลือกหนึ่งรายการ", + "choose_from_available_options": "เลือกจากตัวเลือกที่มีอยู่:", + "custom_redeem_amount": "จำนวนรับคืนที่กำหนดเอง", + "add_custom_redemption": "เพิ่มการรับคืนที่กำหนดเอง", + "remaining": "เหลืออยู่", + "delete_wallet": "ลบกระเป๋า", + "delete_wallet_confirm_message" : "คุณแน่ใจหรือว่าต้องการลบกระเป๋า${wallet_name}?", + "low_fee": "ค่าธรรมเนียมต่ำ", + "low_fee_alert": "ขณะนี้คุณกำลังใช้ค่าธรรมเนียมของเครือข่ายที่มีความสำคัญต่ำ ซึ่งอาจทำให้เกิดการรอนาน ราคาที่แตกต่างกัน หรือยกเลิกการซื้อขาย เราแนะนำให้กำหนดค่าธรรมเนียมที่สูงขึ้นเพื่อประสบการณ์ที่ดีขึ้น", + "ignor": "ละเว้น", + "use_suggested": "ใช้ที่แนะนำ", + "do_not_share_warning_text" : "อย่าแชร์ข้อมูลนี้กับใครอื่น รวมถึงฝ่ายสนับสนุนด้วย\n\nการเงินของคุณอาจถูกขโมยโดยไม่หวังดี!", + "help": "ช่วยเหลือ", + "all_transactions": "การทำธุรกรรมทั้งหมด", + "all_trades": "การซื้อขายทั้งหมด", + "connection_sync": "การเชื่อมต่อและการซิงค์", + "security_and_backup": "ความปลอดภัยและการสำรองข้อมูล", + "create_backup": "สร้างการสำรองข้อมูล", + "privacy_settings": "การตั้งค่าความเป็นส่วนตัว", + "privacy": "ความเป็นส่วนตัว", + "display_settings": "การตั้งค่าการแสดงผล", + "other_settings": "การตั้งค่าอื่น ๆ", + "require_pin_after": "ต้องการ PIN หลังจาก", + "always": "เสมอ", + "minutes_to_pin_code": "${minute} นาที", + "disable_exchange": "ปิดใช้งานการแลกเปลี่ยน", + "advanced_privacy_settings": "การตั้งค่าความเป็นส่วนตัวขั้นสูง", + "settings_can_be_changed_later" : "การตั้งค่านี้สามารถเปลี่ยนแปลงได้ภายหลังในการตั้งค่าแอพฯ", + "add_custom_node" : "เพิ่มจุดโหนดแบบกำหนดเอง", + "disable_fiat" : "ปิดใช้งานสกุลเงินตรา", + "fiat_api" : "API สกุลเงินตรา", + "disabled" : "ปิดใช้งาน", + "enabled" : "เปิดใช้งาน", + "tor_only" : "Tor เท่านั้น", + "unmatched_currencies" : "สกุลเงินของกระเป๋าปัจจุบันของคุณไม่ตรงกับของ QR ที่สแกน" +} From 768320003c568d60478fd4d61cf159aef89cb81c Mon Sep 17 00:00:00 2001 From: Mathias Herberts Date: Thu, 5 Jan 2023 22:39:32 +0100 Subject: [PATCH 198/203] Fixed FR translations. Added localized strings in contact list --- .../screens/contact/contact_list_page.dart | 4 +-- res/values/strings_en.arb | 4 ++- res/values/strings_fr.arb | 28 ++++++++++--------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 7cd7a0157..0065b9281 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -72,10 +72,10 @@ class ContactListPage extends BasePage { dividerThemeColor: Theme.of(context).primaryTextTheme.caption!.decorationColor!, sectionTitleBuilder: (_, int sectionIndex) { - var title = 'Contacts'; + var title = S.current.contact_list_contacts; if (sectionIndex == 0) { - title = 'My wallets'; + title = S.current.contact_list_wallets; } return Container( diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 548ba35c0..e9a0c4d49 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -677,5 +677,7 @@ "disabled": "Disabled", "enabled": "Enabled", "tor_only": "Tor only", - "unmatched_currencies": "Your current wallet's currency does not match that of the scanned QR" + "unmatched_currencies": "Your current wallet's currency does not match that of the scanned QR", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 2168e31a2..99fbcd282 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -534,7 +534,7 @@ "search_currency": "Rechercher une devise", "new_template" : "Nouveau Modèle", "electrum_address_disclaimer": "Nous générons de nouvelles adresses à chaque fois que vous en utilisez une, mais les adresses précédentes continuent à fonctionner", - "wallet_name_exists": "Un portefeuille portant ce nom existe déjà", + "wallet_name_exists": "Un portefeuille (wallet) portant ce nom existe déjà", "market_place": "Place de marché", "cake_pay_title": "Cartes cadeaux Cake Pay", "cake_pay_subtitle": "Achetez des cartes-cadeaux à prix réduit (États-Unis uniquement)", @@ -562,7 +562,7 @@ "cakepay_prepaid_card": "Carte de débit prépayée Cake Pay", "no_id_needed": "Aucune pièce d'identité nécessaire !", "frequently_asked_questions": "Foire aux questions", - "debit_card_terms": "Le stockage et l'utilisation de votre numéro de carte de paiement (et des informations d'identification correspondant à votre numéro de carte de paiement) dans ce portefeuille numérique sont soumis aux conditions générales de l'accord du titulaire de carte applicable avec l'émetteur de la carte de paiement, en vigueur à partir de de temps en temps.", + "debit_card_terms": "Le stockage et l'utilisation de votre numéro de carte de paiement (et des informations d'identification correspondant à votre numéro de carte de paiement) dans ce portefeuille numérique peuvent être soumis aux conditions générales de l'accord du titulaire de carte parfois en vigueur avec l'émetteur de la carte de paiement.", "please_reference_document": "Veuillez vous référer aux documents ci-dessous pour plus d'informations.", "cardholder_agreement": "Contrat de titulaire de carte", "e_sign_consent": "Consentement de signature électronique", @@ -595,7 +595,7 @@ "gift_card_amount": "Montant de la carte-cadeau", "bill_amount": "Montant de la facture", "you_pay": "Vous payez", - "tip": "Astuce :", + "tip": "Pourboire :", "custom": "personnalisé", "by_cake_pay": "par Cake Pay", "expire": "Expire", @@ -617,7 +617,7 @@ "gift_card_balance_note": "Les cartes-cadeaux avec un solde restant apparaîtront ici", "gift_card_redeemed_note": "Les cartes-cadeaux que vous avez utilisées apparaîtront ici", "logout": "Déconnexion", - "add_tip": "Ajouter une astuce", + "add_tip": "Ajouter un pourboire", "percentageOf": "sur ${amount}", "is_percentage": "est", "search_category": "Catégorie de recherche", @@ -646,16 +646,16 @@ "custom_redeem_amount": "Montant d'échange personnalisé", "add_custom_redemption": "Ajouter un remboursement personnalisé", "remaining": "restant", - "delete_wallet": "Supprimer le portefeuille", - "delete_wallet_confirm_message" : "Êtes-vous sûr de vouloir supprimer le portefeuille ${wallet_name}?", + "delete_wallet": "Supprimer le portefeuille (wallet)", + "delete_wallet_confirm_message" : "Êtes-vous sûr de vouloir supprimer le portefeuille (wallet) ${wallet_name}?", "low_fee": "Frais modiques", "low_fee_alert": "Vous utilisez actuellement une priorité de frais de réseau peu élevés. Cela pourrait entraîner de longues attentes, des taux différents ou des transactions annulées. Nous vous recommandons de fixer des frais plus élevés pour une meilleure expérience.", "ignor": "Ignorer", "use_suggested": "Utilisation suggérée", - "do_not_share_warning_text" : "Ne les partagez avec personne d'autre, y compris avec l'assistance.\n\nVos fonds peuvent et seront volés!", - "help": "aider", + "do_not_share_warning_text" : "Ne les partagez avec personne, y compris avec l'assistance.\n\nVos fonds seraient inmanquablement volés !", + "help": "aide", "all_transactions": "Toutes transactions", - "all_trades": "Tous métiers", + "all_trades": "Tous échanges", "connection_sync": "Connexion et synchronisation", "security_and_backup": "Sécurité et sauvegarde", "create_backup": "Créer une sauvegarde", @@ -663,17 +663,19 @@ "privacy": "Confidentialité", "display_settings": "Paramètres d'affichage", "other_settings": "Autres paramètres", - "require_pin_after": "NIP requis après", + "require_pin_after": "Code PIN requis après", "always": "toujours", "minutes_to_pin_code": "${minute} minutes", "disable_exchange": "Désactiver l'échange", "advanced_privacy_settings": "Paramètres de confidentialité avancés", "settings_can_be_changed_later": "Ces paramètres peuvent être modifiés ultérieurement dans les paramètres de l'application", "add_custom_node": "Ajouter un nouveau nœud personnalisé", - "disable_fiat": "Désactiver fiat", + "disable_fiat": "Désactiver les montants en fiat", "fiat_api": "Fiat API", - "disabled": "Handicapé", + "disabled": "Désactivé", "enabled": "Activé", "tor_only": "Tor uniquement", - "unmatched_currencies": "La devise de votre portefeuille actuel ne correspond pas à celle du QR scanné" + "unmatched_currencies": "La devise de votre portefeuille (wallet) actuel ne correspond pas à celle du QR code scanné", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "Mes portefeuilles (wallets)" } From de4ecefd20e5e950fa9366c3bd4658de44a919ba Mon Sep 17 00:00:00 2001 From: Mathias Herberts Date: Thu, 5 Jan 2023 22:44:19 +0100 Subject: [PATCH 199/203] Added localized strings in contact list --- res/values/strings_de.arb | 4 +++- res/values/strings_es.arb | 4 +++- res/values/strings_hi.arb | 4 +++- res/values/strings_hr.arb | 4 +++- res/values/strings_it.arb | 4 +++- res/values/strings_ja.arb | 4 +++- res/values/strings_ko.arb | 4 +++- res/values/strings_nl.arb | 4 +++- res/values/strings_pl.arb | 4 +++- res/values/strings_pt.arb | 4 +++- res/values/strings_ru.arb | 4 +++- res/values/strings_uk.arb | 4 +++- res/values/strings_zh.arb | 4 +++- 13 files changed, 39 insertions(+), 13 deletions(-) diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 3382b73f8..a5076f289 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -677,5 +677,7 @@ "disabled": "Deaktiviert", "enabled": "Ermöglicht", "tor_only": "Nur Tor", - "unmatched_currencies": "Die Währung Ihres aktuellen Wallets stimmt nicht mit der des gescannten QR überein" + "unmatched_currencies": "Die Währung Ihres aktuellen Wallets stimmt nicht mit der des gescannten QR überein", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index db0a813b4..12cf47469 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -677,5 +677,7 @@ "disabled": "Desactivado", "enabled": "Activado", "tor_only": "solo Tor", - "unmatched_currencies": "La moneda de su billetera actual no coincide con la del QR escaneado" + "unmatched_currencies": "La moneda de su billetera actual no coincide con la del QR escaneado", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 9acf7657c..53abe527a 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -677,5 +677,7 @@ "disabled": "अक्षम", "enabled": "सक्रिय", "tor_only": "Tor केवल", - "unmatched_currencies": "आपके वर्तमान वॉलेट की मुद्रा स्कैन किए गए क्यूआर से मेल नहीं खाती" + "unmatched_currencies": "आपके वर्तमान वॉलेट की मुद्रा स्कैन किए गए क्यूआर से मेल नहीं खाती" , + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index dacd3952b..0c4c84d2f 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -677,5 +677,7 @@ "disabled": "Onemogućeno", "enabled": "Omogućeno", "tor_only": "Samo Tor", - "unmatched_currencies": "Valuta vašeg trenutnog novčanika ne odgovara onoj na skeniranom QR-u" + "unmatched_currencies": "Valuta vašeg trenutnog novčanika ne odgovara onoj na skeniranom QR-u", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index ac0ad5833..dc4375380 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -677,5 +677,7 @@ "disabled": "Disabilitato", "enabled": "Abilitato", "tor_only": "Solo Tor", - "unmatched_currencies": "La valuta del tuo portafoglio attuale non corrisponde a quella del QR scansionato" + "unmatched_currencies": "La valuta del tuo portafoglio attuale non corrisponde a quella del QR scansionato", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index fc1abc280..88f9d5bc9 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -677,5 +677,7 @@ "disabled": "無効", "enabled": "有効", "tor_only": "Torのみ", - "unmatched_currencies": "現在のウォレットの通貨がスキャンされたQRの通貨と一致しません" + "unmatched_currencies": "現在のウォレットの通貨がスキャンされたQRの通貨と一致しません", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index b30529038..d55f0175b 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -677,5 +677,7 @@ "disabled": "장애가 있는", "enabled": "사용", "tor_only": "Tor 뿐", - "unmatched_currencies": "현재 지갑의 통화가 스캔한 QR의 통화와 일치하지 않습니다." + "unmatched_currencies": "현재 지갑의 통화가 스캔한 QR의 통화와 일치하지 않습니다.", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 734347991..41bd8de75 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -677,5 +677,7 @@ "disabled": "Gehandicapt", "enabled": "Ingeschakeld", "tor_only": "Alleen Tor", - "unmatched_currencies": "De valuta van uw huidige portemonnee komt niet overeen met die van de gescande QR" + "unmatched_currencies": "De valuta van uw huidige portemonnee komt niet overeen met die van de gescande QR", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index b7806d2a4..c8e208fbd 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -677,5 +677,7 @@ "disabled": "Wyłączone", "enabled": "Włączony", "tor_only": "Tylko Tor", - "unmatched_currencies": "Waluta Twojego obecnego portfela nie odpowiada walucie zeskanowanego kodu QR" + "unmatched_currencies": "Waluta Twojego obecnego portfela nie odpowiada walucie zeskanowanego kodu QR", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 80177d22c..0312ed07f 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -676,5 +676,7 @@ "disabled": "Desabilitado", "enabled": "Habilitado", "tor_only": "Tor apenas", - "unmatched_currencies": "A moeda da sua carteira atual não corresponde à do QR digitalizado" + "unmatched_currencies": "A moeda da sua carteira atual não corresponde à do QR digitalizado", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index eb63a974f..145f0418d 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -677,5 +677,7 @@ "disabled": "Отключено", "enabled": "Включено", "tor_only": "Только Tor", - "unmatched_currencies": "Валюта вашего текущего кошелька не соответствует валюте отсканированного QR-кода." + "unmatched_currencies": "Валюта вашего текущего кошелька не соответствует валюте отсканированного QR-кода.", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 20cbfaf6f..dd8a83d08 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -676,5 +676,7 @@ "disabled": "Вимкнено", "enabled": "Увімкнено", "tor_only": "Тільки Tor", - "unmatched_currencies": "Валюта вашого гаманця не збігається з валютою сканованого QR-коду" + "unmatched_currencies": "Валюта вашого гаманця не збігається з валютою сканованого QR-коду", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 248eabda1..a2021fa56 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -675,5 +675,7 @@ "disabled": "禁用", "enabled": "启用", "tor_only": "仅限 Tor", - "unmatched_currencies": "您当前钱包的货币与扫描的 QR 的货币不匹配" + "unmatched_currencies": "您当前钱包的货币与扫描的 QR 的货币不匹配", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets" } From 21dfe86da02f7fe921f4b81ee9511f90c13ea656 Mon Sep 17 00:00:00 2001 From: rosedaler <121954045+maddymodd@users.noreply.github.com> Date: Thu, 5 Jan 2023 21:21:10 -0500 Subject: [PATCH 200/203] Update strings_th.arb --- res/values/strings_th.arb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index f39025e3d..aaff40730 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -261,7 +261,7 @@ "view_key_public" : "คีย์มุมมอง (สาธารณะ)", "spend_key_private" : "คีย์จ่าย (ส่วนตัว)", "spend_key_public" : "คีย์จ่าย (สาธารณะ)", - "copied_key_to_clipboard" : "คัดลอก ${key} ไปยัง Clipboard แล้ว" + "copied_key_to_clipboard" : "คัดลอก ${key} ไปยัง Clipboard แล้ว", "new_subaddress_title" : "ที่อยู่ใหม่", @@ -279,7 +279,7 @@ "trade_details_provider" : "ผู้ให้บริการ", "trade_details_created_at" : "สร้างเมื่อ", "trade_details_pair" : "คู่", - "trade_details_copied" : "${title} คัดลอกไปยัง Clipboard" + "trade_details_copied" : "${title} คัดลอกไปยัง Clipboard", "trade_history_title" : "ประวัติการซื้อขาย", @@ -527,7 +527,7 @@ "second_intro_title" : "อิโมจิที่อยู่เดียวที่จะควบคุมพวกเขาทั้งหมด", "second_intro_content" : "Yat ของคุณเป็นอิโมจิที่อยู่เดียวที่จะแทนที่ทุกที่อยู่และเลขฐานสิบหกของคุณสำหรับเหรียญคริปโตทุกชนิด", "third_intro_title" : "Yat ปฏิบัติตนอย่างดีกับผู้อื่น", - "third_intro_content" : "Yat อาศัยอยู่นอก Cake Wallet ด้วย ที่อยู่กระเป๋าใดๆ ทั่วโลกสามารถแทนด้วย Yat ได้อีกด้วย!" + "third_intro_content" : "Yat อาศัยอยู่นอก Cake Wallet ด้วย ที่อยู่กระเป๋าใดๆ ทั่วโลกสามารถแทนด้วย Yat ได้อีกด้วย!", "learn_more" : "ศึกษาเพิ่มเติม", "search": "ค้นหา", "search_language": "ค้นหาภาษา", @@ -580,7 +580,7 @@ "order_physical_card": "สั่งซื้อบัตรดิบิต", "add_value": "เพิ่มมูลค่า", "activate": "เปิดใช้งาน", - "get_a": "รับ " + "get_a": "รับ ", "digital_and_physical_card": "บัตรเดบิตดิจิตอลและบัตรพื้นฐาน", "get_card_note": "ที่คุณสามารถเติมเงินด้วยสกุลเงินดิจิตอล ไม่จำเป็นต้องใส่ข้อมูลเพิ่มเติม!", "signup_for_card_accept_terms": "ลงทะเบียนสำหรับบัตรและยอมรับเงื่อนไข", From 23490b088f00711f64d4c24b03d7f743af9338c3 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 6 Jan 2023 14:40:35 +0200 Subject: [PATCH 201/203] Translate contact list for other languages --- res/values/strings_de.arb | 4 ++-- res/values/strings_es.arb | 4 ++-- res/values/strings_hi.arb | 4 ++-- res/values/strings_hr.arb | 4 ++-- res/values/strings_it.arb | 4 ++-- res/values/strings_ja.arb | 4 ++-- res/values/strings_ko.arb | 4 ++-- res/values/strings_nl.arb | 4 ++-- res/values/strings_pl.arb | 4 ++-- res/values/strings_pt.arb | 4 ++-- res/values/strings_ru.arb | 4 ++-- res/values/strings_uk.arb | 4 ++-- res/values/strings_zh.arb | 4 ++-- 13 files changed, 26 insertions(+), 26 deletions(-) diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index a5076f289..9ba0a7553 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -678,6 +678,6 @@ "enabled": "Ermöglicht", "tor_only": "Nur Tor", "unmatched_currencies": "Die Währung Ihres aktuellen Wallets stimmt nicht mit der des gescannten QR überein", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "Kontakte", + "contact_list_wallets": "Meine Geldbörsen" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 12cf47469..10c866676 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -678,6 +678,6 @@ "enabled": "Activado", "tor_only": "solo Tor", "unmatched_currencies": "La moneda de su billetera actual no coincide con la del QR escaneado", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "Contactos", + "contact_list_wallets": "Mis billeteras" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 53abe527a..a5c27ddb4 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -678,6 +678,6 @@ "enabled": "सक्रिय", "tor_only": "Tor केवल", "unmatched_currencies": "आपके वर्तमान वॉलेट की मुद्रा स्कैन किए गए क्यूआर से मेल नहीं खाती" , - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "संपर्क", + "contact_list_wallets": "मेरा बटुआ" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 0c4c84d2f..9aa9f0b4f 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -678,6 +678,6 @@ "enabled": "Omogućeno", "tor_only": "Samo Tor", "unmatched_currencies": "Valuta vašeg trenutnog novčanika ne odgovara onoj na skeniranom QR-u", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "Kontakti", + "contact_list_wallets": "Moji novčanici" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index dc4375380..e90fc20c2 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -678,6 +678,6 @@ "enabled": "Abilitato", "tor_only": "Solo Tor", "unmatched_currencies": "La valuta del tuo portafoglio attuale non corrisponde a quella del QR scansionato", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "Contatti", + "contact_list_wallets": "I miei portafogli" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 88f9d5bc9..3c5a5d951 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -678,6 +678,6 @@ "enabled": "有効", "tor_only": "Torのみ", "unmatched_currencies": "現在のウォレットの通貨がスキャンされたQRの通貨と一致しません", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "連絡先", + "contact_list_wallets": "マイウォレット" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index d55f0175b..216a3a143 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -678,6 +678,6 @@ "enabled": "사용", "tor_only": "Tor 뿐", "unmatched_currencies": "현재 지갑의 통화가 스캔한 QR의 통화와 일치하지 않습니다.", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "콘택트 렌즈", + "contact_list_wallets": "내 지갑" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 41bd8de75..9ac0cd1d1 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -678,6 +678,6 @@ "enabled": "Ingeschakeld", "tor_only": "Alleen Tor", "unmatched_currencies": "De valuta van uw huidige portemonnee komt niet overeen met die van de gescande QR", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "Contacten", + "contact_list_wallets": "Mijn portefeuilles" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index c8e208fbd..11bf637e5 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -678,6 +678,6 @@ "enabled": "Włączony", "tor_only": "Tylko Tor", "unmatched_currencies": "Waluta Twojego obecnego portfela nie odpowiada walucie zeskanowanego kodu QR", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "Łączność", + "contact_list_wallets": "Moje portfele" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 0312ed07f..8529aadb8 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -677,6 +677,6 @@ "enabled": "Habilitado", "tor_only": "Tor apenas", "unmatched_currencies": "A moeda da sua carteira atual não corresponde à do QR digitalizado", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "Contatos", + "contact_list_wallets": "minhas carteiras" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 145f0418d..1ba5fd85c 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -678,6 +678,6 @@ "enabled": "Включено", "tor_only": "Только Tor", "unmatched_currencies": "Валюта вашего текущего кошелька не соответствует валюте отсканированного QR-кода.", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "Контакты", + "contact_list_wallets": "Мои кошельки" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index dd8a83d08..4fad9a19d 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -677,6 +677,6 @@ "enabled": "Увімкнено", "tor_only": "Тільки Tor", "unmatched_currencies": "Валюта вашого гаманця не збігається з валютою сканованого QR-коду", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "Контакти", + "contact_list_wallets": "Мої гаманці" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index a2021fa56..7c0f4ab74 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -676,6 +676,6 @@ "enabled": "启用", "tor_only": "仅限 Tor", "unmatched_currencies": "您当前钱包的货币与扫描的 QR 的货币不匹配", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets" + "contact_list_contacts": "联系人", + "contact_list_wallets": "我的钱包" } From 0b5b74943c52be53dc0fcd0e33be4f3207dd7dd9 Mon Sep 17 00:00:00 2001 From: rosedaler <121954045+maddymodd@users.noreply.github.com> Date: Fri, 6 Jan 2023 07:57:04 -0500 Subject: [PATCH 202/203] Update strings_th.arb --- res/values/strings_th.arb | 1 + 1 file changed, 1 insertion(+) diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index aaff40730..6955a68dc 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -587,6 +587,7 @@ "add_fund_to_card": "เพิ่มเงินสำรองไว้บนบัตร (ถึง ${value})", "use_card_info_two": "เงินจะถูกแปลงค่าเป็นดอลลาร์สหรัฐเมื่อถือไว้ในบัญชีสำรองเงิน ไม่ใช่สกุลเงินดิจิตอล", "use_card_info_three": "ใช้บัตรดิจิตอลออนไลน์หรือผ่านวิธีการชำระเงินแบบไม่ต้องใช้บัตรกระดาษ", + "optionally_order_card": "เลือกเพิ่มสั่งการ์ดจริง", "hide_details" : "ซ่อนรายละเอียด", "show_details" : "แสดงรายละเอียด", "upto": "สูงสุด ${value}", From 5e96c387a23ee897abb22bd7b3dc5054a9faee63 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 6 Jan 2023 15:22:00 +0200 Subject: [PATCH 203/203] Add Thai translation for contact list [skip ci] --- res/values/strings_th.arb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 6955a68dc..242a8d110 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -675,5 +675,7 @@ "disabled" : "ปิดใช้งาน", "enabled" : "เปิดใช้งาน", "tor_only" : "Tor เท่านั้น", - "unmatched_currencies" : "สกุลเงินของกระเป๋าปัจจุบันของคุณไม่ตรงกับของ QR ที่สแกน" + "unmatched_currencies" : "สกุลเงินของกระเป๋าปัจจุบันของคุณไม่ตรงกับของ QR ที่สแกน", + "contact_list_contacts": "ติดต่อ", + "contact_list_wallets": "กระเป๋าเงินของฉัน" }