diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index 22278d5f1..cf67a8c26 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -39,6 +39,15 @@ android:scheme="cakewallet" android:host="y.at" /> + + + + + + + + + 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 79ef8dabf..a60cf3148 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -13,6 +13,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dar 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/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_custom_tip_view_model.dart'; @@ -384,8 +385,11 @@ Future setup( getIt.get(), _transactionDescriptionBox)); - getIt.registerFactory( - () => SendPage(sendViewModel: getIt.get())); + getIt.registerFactoryParam( + (PaymentRequest? initialPaymentRequest, _) => SendPage( + sendViewModel: getIt.get(), + initialPaymentRequest: initialPaymentRequest, + )); getIt.registerFactory(() => SendTemplatePage( sendTemplateViewModel: getIt.get())); diff --git a/lib/main.dart b/lib/main.dart index 11eee146b..ebdad1500 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -204,12 +204,6 @@ class AppState extends State with SingleTickerProviderStateMixin { //_handleInitialUri(); } - @override - void dispose() { - stream?.cancel(); - super.dispose(); - } - Future _handleInitialUri() async { try { final uri = await getInitialUri(); diff --git a/lib/router.dart b/lib/router.dart index b59294428..896ddd99b 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -25,6 +25,7 @@ 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'; +import 'package:cake_wallet/utils/payment_request.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/advanced_privacy_settings_view_model.dart'; @@ -216,8 +217,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/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; }); }); } diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 190127c0c..2cd849f34 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -4,6 +4,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:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -25,11 +26,15 @@ import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'package:cw_core/crypto_currency.dart'; class SendPage extends BasePage { - SendPage({required this.sendViewModel}) : _formKey = GlobalKey(); + SendPage({ + required this.sendViewModel, + this.initialPaymentRequest, + }) : _formKey = GlobalKey(); final SendViewModel sendViewModel; final GlobalKey _formKey; final controller = PageController(initialPage: 0); + final PaymentRequest? initialPaymentRequest; bool _effectsInstalled = false; @@ -116,6 +121,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 8f0d6675d..082067d95 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; +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'; @@ -20,21 +21,28 @@ class SendCard extends StatefulWidget { SendCard({ Key? key, required this.output, - required this.sendViewModel}) : super(key: key); + required this.sendViewModel, + this.initialPaymentRequest, + }) : super(key: key); final Output output; final SendViewModel sendViewModel; + final PaymentRequest? initialPaymentRequest; @override SendCardState createState() => SendCardState( output: output, - sendViewModel: sendViewModel + sendViewModel: sendViewModel, + initialPaymentRequest: initialPaymentRequest, ); } class SendCardState extends State with AutomaticKeepAliveClientMixin { - SendCardState({required this.output, required this.sendViewModel}) + SendCardState({ + required this.output, + required this.sendViewModel, + this.initialPaymentRequest}) : addressController = TextEditingController(), cryptoAmountController = TextEditingController(), fiatAmountController = TextEditingController(), @@ -49,6 +57,7 @@ class SendCardState extends State final Output output; final SendViewModel sendViewModel; + final PaymentRequest? initialPaymentRequest; final TextEditingController addressController; final TextEditingController cryptoAmountController; @@ -61,6 +70,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); @@ -512,8 +542,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; @@ -605,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; } diff --git a/lib/utils/payment_request.dart b/lib/utils/payment_request.dart index 26244059f..88730f037 100644 --- a/lib/utils/payment_request.dart +++ b/lib/utils/payment_request.dart @@ -1,22 +1,25 @@ class PaymentRequest { - PaymentRequest(this.address, this.amount, this.note); + 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 = ""; + var scheme = ""; if (uri != null) { address = uri.path; amount = uri.queryParameters['tx_amount'] ?? uri.queryParameters['amount'] ?? ""; note = uri.queryParameters['tx_description'] ?? uri.queryParameters['message'] ?? ""; + scheme = uri.scheme; } - return PaymentRequest(address, amount, note); + return PaymentRequest(address, amount, note, scheme); } final String address; final String amount; final String note; + 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 fd783cf6f..b6604789a 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -53,7 +53,7 @@ abstract class SendViewModelBase with Store { outputs.add(Output(_wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency)); } - + @observable ExecutionState state; @@ -180,6 +180,8 @@ abstract class SendViewModelBase with Store { WalletType get walletType => _wallet.type; + String? get walletCurrencyName => _wallet.currency.name?.toLowerCase(); + bool get hasCurrecyChanger => walletType == WalletType.haven; @computed @@ -306,7 +308,7 @@ abstract class SendViewModelBase with Store { @action void onClose() => _settingsStore.fiatCurrency = fiatFromSettings; - + @action void setFiatCurrency(FiatCurrency fiat) => _settingsStore.fiatCurrency = fiat; diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 2dd55c704..571bae86d 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -669,5 +669,6 @@ "fiat_api": "Fiat API", "disabled": "Deaktiviert", "enabled": "Ermöglicht", - "tor_only": "Nur Tor" + "tor_only": "Nur Tor", + "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 fd5eae1d6..8e39c1e8e 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -669,5 +669,6 @@ "fiat_api": "Fiat API", "disabled": "Disabled", "enabled": "Enabled", - "tor_only": "Tor only" + "tor_only": "Tor only", + "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 8e56c13aa..b9e115273 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -669,5 +669,6 @@ "fiat_api": "Fiat API", "disabled": "Desactivado", "enabled": "Activado", - "tor_only": "solo Tor" + "tor_only": "solo Tor", + "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 075e917be..f17e4e7b6 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -667,5 +667,6 @@ "fiat_api": "Fiat API", "disabled": "Handicapé", "enabled": "Activé", - "tor_only": "Tor uniquement" + "tor_only": "Tor uniquement", + "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 06e66fab2..91ceff77d 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -665,9 +665,9 @@ "advanced_privacy_settings": "उन्नत गोपनीयता सेटिंग्स", "settings_can_be_changed_later": "इन सेटिंग्स को बाद में ऐप सेटिंग में बदला जा सकता है", "add_custom_node": "नया कस्टम नोड जोड़ें", - "disable_exchange": "एक्सचेंज अक्षम करें", "fiat_api": "फिएट पैसे API", "disabled": "अक्षम", "enabled": "सक्रिय", - "tor_only": "Tor केवल" + "tor_only": "Tor केवल", + "unmatched_currencies": "आपके वर्तमान वॉलेट की मुद्रा स्कैन किए गए क्यूआर से मेल नहीं खाती" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index b6cecf570..a7ee21582 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -669,5 +669,6 @@ "fiat_api": "Fiat API", "disabled": "Onemogućeno", "enabled": "Omogućeno", - "tor_only": "Samo Tor" + "tor_only": "Samo Tor", + "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 375e003af..0dd72425b 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -669,5 +669,6 @@ "fiat_api": "Fiat API", "disabled": "Disabilitato", "enabled": "Abilitato", - "tor_only": "Solo Tor" + "tor_only": "Solo Tor", + "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 eed3a15ec..483b2a173 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -669,5 +669,6 @@ "fiat_api": "不換紙幣 API", "disabled": "無効", "enabled": "有効", - "tor_only": "Torのみ" + "tor_only": "Torのみ", + "unmatched_currencies": "現在のウォレットの通貨がスキャンされたQRの通貨と一致しません" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 9614cca6a..ff2985c1f 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -669,5 +669,6 @@ "fiat_api": "명목 화폐 API", "disabled": "장애가 있는", "enabled": "사용", - "tor_only": "Tor 뿐" + "tor_only": "Tor 뿐", + "unmatched_currencies": "현재 지갑의 통화가 스캔한 QR의 통화와 일치하지 않습니다." } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 7ea2f4906..dfe888c03 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -669,5 +669,6 @@ "fiat_api": "Fiat API", "disabled": "Gehandicapt", "enabled": "Ingeschakeld", - "tor_only": "Alleen Tor" + "tor_only": "Alleen Tor", + "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 fc5ae9015..94fc16b77 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -669,5 +669,6 @@ "fiat_api": "API Fiata", "disabled": "Wyłączone", "enabled": "Włączony", - "tor_only": "Tylko Tor" + "tor_only": "Tylko Tor", + "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 5cd2e4374..40383df38 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -668,5 +668,6 @@ "fiat_api": "API da Fiat", "disabled": "Desabilitado", "enabled": "Habilitado", - "tor_only": "Tor apenas" + "tor_only": "Tor apenas", + "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 a762aeba9..722b76ac4 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -369,7 +369,7 @@ "trade_for_not_created" : "Сделка для ${title} не создана.", "trade_not_created" : "Сделка не создана", "trade_id_not_found" : "Сделка ${tradeId} ${title} не найдена.", - "trade_not_found" : "Trade not found.", + "trade_not_found" : "Торговля не найдена.", "trade_state_pending" : "Ожидание", @@ -669,5 +669,6 @@ "fiat_api": "Фиат API", "disabled": "Отключено", "enabled": "Включено", - "tor_only": "Только Tor" + "tor_only": "Только Tor", + "unmatched_currencies": "Валюта вашего текущего кошелька не соответствует валюте отсканированного QR-кода." } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 3b8629035..90c2fb5be 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -668,6 +668,6 @@ "fiat_api": "Фіат API", "disabled": "Вимкнено", "enabled": "Увімкнено", - "tor_only": "Тільки Tor" - + "tor_only": "Тільки Tor", + "unmatched_currencies": "Валюта вашого гаманця не збігається з валютою сканованого QR-коду" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index ff65175eb..2c2321078 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -667,5 +667,6 @@ "fiat_api": "法币API", "disabled": "禁用", "enabled": "启用", - "tor_only": "仅限 Tor" + "tor_only": "仅限 Tor", + "unmatched_currencies": "您当前钱包的货币与扫描的 QR 的货币不匹配" }