From 1cddb14bf1d08ae66bcd7be87f4469c87fa1b95b Mon Sep 17 00:00:00 2001 From: dethe <76167420+detherminal@users.noreply.github.com> Date: Mon, 17 Mar 2025 18:34:08 +0300 Subject: [PATCH 1/3] feat: detect bitcoin/monero uri's fix: use uri instead of manual parsing reformat: remove braces and use efficient variables refactor: add forgotten vars --- lib/pages/send_view/send_view.dart | 51 +++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 7d063ba6f..6fb8af4bf 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -1350,11 +1350,31 @@ class _SendViewState extends ConsumerState { selectAll: false, ), onChanged: (newValue) { - _address = newValue.trim(); + final trimmed = newValue.trim(); + + if ((trimmed.length - (_address?.length ?? 0)).abs() > 1) { + if (coin is Monero && Uri.parse(trimmed).scheme == "monero") { + final parsedUri = Uri.parse(trimmed); + final addr = parsedUri.path; + sendToController.text = addr; + _address = addr; + cryptoAmountController.text = parsedUri.queryParameters["tx_amount"] ?? ""; + } else if (coin is Bitcoin && Uri.parse(trimmed).scheme == "bitcoin") { + final parsedUri = Uri.parse(trimmed); + final addr = parsedUri.path; + sendToController.text = addr; + _address = addr; + cryptoAmountController.text = parsedUri.queryParameters["amount"] ?? ""; + } + } else { + sendToController.text = trimmed; + _address = trimmed; + } + _setValidAddressProviders(_address); setState(() { - _addressToggleFlag = newValue.isNotEmpty; + _addressToggleFlag = trimmed.isNotEmpty; }); }, focusNode: _addressFocusNode, @@ -1433,13 +1453,28 @@ class _SendViewState extends ConsumerState { content, ); } - sendToController.text = - content.trim(); - _address = content.trim(); - _setValidAddressProviders( - _address, - ); + final trimmed = content.trim(); + + if (coin is Monero && Uri.parse(trimmed).scheme == "monero") { + final parsedUri = Uri.parse(trimmed); + final addr = parsedUri.path; + sendToController.text = addr; + _address = addr; + cryptoAmountController.text = parsedUri.queryParameters["tx_amount"] ?? ""; + } else if (coin is Bitcoin && Uri.parse(trimmed).scheme == "bitcoin") { + final parsedUri = Uri.parse(trimmed); + final addr = parsedUri.path; + sendToController.text = addr; + _address = addr; + cryptoAmountController.text = parsedUri.queryParameters["amount"] ?? ""; + } else { + sendToController.text = trimmed; + _address = trimmed; + } + + _setValidAddressProviders(_address,); + setState(() { _addressToggleFlag = sendToController From d835b142301dd1b332f22c78593d0131c1208101 Mon Sep 17 00:00:00 2001 From: dethe <76167420+detherminal@users.noreply.github.com> Date: Tue, 18 Mar 2025 13:31:28 +0300 Subject: [PATCH 2/3] fix: controller positioning --- lib/pages/send_view/send_view.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 6fb8af4bf..1e6f33970 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -1367,7 +1367,6 @@ class _SendViewState extends ConsumerState { cryptoAmountController.text = parsedUri.queryParameters["amount"] ?? ""; } } else { - sendToController.text = trimmed; _address = trimmed; } From 3fbc6daba0c0cb22a677d585c9e42b3f9aa8d155 Mon Sep 17 00:00:00 2001 From: dethe <76167420+detherminal@users.noreply.github.com> Date: Sat, 22 Mar 2025 01:30:36 +0300 Subject: [PATCH 3/3] feat: use _applyUri for paste --- lib/pages/send_view/send_view.dart | 135 +++++++++--------- .../wallet_view/sub_widgets/desktop_send.dart | 105 +++++++------- 2 files changed, 118 insertions(+), 122 deletions(-) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 1e6f33970..4bdcef6e2 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -135,6 +135,44 @@ class _SendViewState extends ConsumerState { Set selectedUTXOs = {}; + void _applyUri(PaymentUriData paymentData) { + try { + // auto fill address + _address = paymentData.address.trim(); + sendToController.text = _address!; + + // autofill notes field + if (paymentData.message != null) { + noteController.text = paymentData.message!; + } else if (paymentData.label != null) { + noteController.text = paymentData.label!; + } + + // autofill amount field + if (paymentData.amount != null) { + final Amount amount = Decimal.parse(paymentData.amount!).toAmount( + fractionDigits: coin.fractionDigits, + ); + cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( + amount, + withUnitName: false, + ); + ref.read(pSendAmount.notifier).state = amount; + } + + _setValidAddressProviders(_address); + setState(() { + _addressToggleFlag = sendToController.text.isNotEmpty; + }); + } catch (e, s) { + Logging.instance.e( + "Failed to apply uri in SendView: ", + error: e, + stackTrace: s, + ); + } + } + Future _scanQr() async { try { // ref @@ -167,35 +205,7 @@ class _SendViewState extends ConsumerState { if (paymentData != null && paymentData.coin?.uriScheme == coin.uriScheme) { - // auto fill address - _address = paymentData.address.trim(); - sendToController.text = _address!; - - // autofill notes field - if (paymentData.message != null) { - noteController.text = paymentData.message!; - } else if (paymentData.label != null) { - noteController.text = paymentData.label!; - } - - // autofill amount field - if (paymentData.amount != null) { - final Amount amount = Decimal.parse(paymentData.amount!).toAmount( - fractionDigits: coin.fractionDigits, - ); - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); - ref.read(pSendAmount.notifier).state = amount; - } - - _setValidAddressProviders(_address); - setState(() { - _addressToggleFlag = sendToController.text.isNotEmpty; - }); - - // now check for non standard encoded basic address + _applyUri(paymentData); } else { _address = qrResult.rawContent.split("\n").first.trim(); sendToController.text = _address ?? ""; @@ -1353,27 +1363,24 @@ class _SendViewState extends ConsumerState { final trimmed = newValue.trim(); if ((trimmed.length - (_address?.length ?? 0)).abs() > 1) { - if (coin is Monero && Uri.parse(trimmed).scheme == "monero") { - final parsedUri = Uri.parse(trimmed); - final addr = parsedUri.path; - sendToController.text = addr; - _address = addr; - cryptoAmountController.text = parsedUri.queryParameters["tx_amount"] ?? ""; - } else if (coin is Bitcoin && Uri.parse(trimmed).scheme == "bitcoin") { - final parsedUri = Uri.parse(trimmed); - final addr = parsedUri.path; - sendToController.text = addr; - _address = addr; - cryptoAmountController.text = parsedUri.queryParameters["amount"] ?? ""; + final parsed = AddressUtils.parsePaymentUri( + trimmed, + logging: Logging.instance, + ); + if (parsed != null) { + _applyUri(parsed); + } else { + _address = newValue; + sendToController.text = newValue; } } else { - _address = trimmed; + _address = newValue; } _setValidAddressProviders(_address); setState(() { - _addressToggleFlag = trimmed.isNotEmpty; + _addressToggleFlag = newValue.isNotEmpty; }); }, focusNode: _addressFocusNode, @@ -1454,32 +1461,26 @@ class _SendViewState extends ConsumerState { } final trimmed = content.trim(); - - if (coin is Monero && Uri.parse(trimmed).scheme == "monero") { - final parsedUri = Uri.parse(trimmed); - final addr = parsedUri.path; - sendToController.text = addr; - _address = addr; - cryptoAmountController.text = parsedUri.queryParameters["tx_amount"] ?? ""; - } else if (coin is Bitcoin && Uri.parse(trimmed).scheme == "bitcoin") { - final parsedUri = Uri.parse(trimmed); - final addr = parsedUri.path; - sendToController.text = addr; - _address = addr; - cryptoAmountController.text = parsedUri.queryParameters["amount"] ?? ""; + final parsed = AddressUtils.parsePaymentUri( + trimmed, + logging: Logging.instance, + ); + if (parsed != null) { + _applyUri(parsed); } else { - sendToController.text = trimmed; - _address = trimmed; + sendToController.text = + content; + _address = content; + + _setValidAddressProviders(_address,); + + setState(() { + _addressToggleFlag = + sendToController + .text + .isNotEmpty; + }); } - - _setValidAddressProviders(_address,); - - setState(() { - _addressToggleFlag = - sendToController - .text - .isNotEmpty; - }); } }, child: sendToController diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 0c8b9034c..009893e7e 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -660,33 +660,7 @@ class _DesktopSendState extends ConsumerState { if (paymentData != null && paymentData.coin?.uriScheme == coin.uriScheme) { - // Auto fill address. - _address = paymentData.address.trim(); - sendToController.text = _address!; - - // Amount. - if (paymentData.amount != null) { - final Amount amount = Decimal.parse(paymentData.amount!).toAmount( - fractionDigits: coin.fractionDigits, - ); - cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format( - amount, - withUnitName: false, - ); - ref.read(pSendAmount.notifier).state = amount; - } - - // Note/message. - if (paymentData.message != null) { - _note = paymentData.message; - } else if (paymentData.label != null) { - _note = paymentData.label; - } - - _setValidAddressProviders(_address); - setState(() { - _addressToggleFlag = sendToController.text.isNotEmpty; - }); + _applyUri(paymentData); } else { _address = qrCodeData.split("\n").first.trim(); sendToController.text = _address ?? ""; @@ -736,6 +710,40 @@ class _DesktopSendState extends ConsumerState { } } + void _applyUri(PaymentUriData paymentData) { + try { + // auto fill address + _address = paymentData.address; + sendToController.text = _address!; + + // autofill notes field. + if (paymentData.message != null) { + _note = paymentData.message; + } else if (paymentData.label != null) { + _note = paymentData.label; + } + + // autofill amount field + if (paymentData.amount != null) { + final amount = Decimal.parse(paymentData.amount!).toAmount( + fractionDigits: coin.fractionDigits, + ); + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format(amount, withUnitName: false); + ref.read(pSendAmount.notifier).state = amount; + } + + // Trigger validation after pasting. + _setValidAddressProviders(_address); + setState(() { + _addressToggleFlag = sendToController.text.isNotEmpty; + }); + } catch (e, s) { + Logging.instance.e("Error applying URI", error: e, stackTrace: s); + } + } + Future pasteAddress() async { final ClipboardData? data = await clipboard.getData(Clipboard.kTextPlain); if (data?.text != null && data!.text!.isNotEmpty) { @@ -751,33 +759,7 @@ class _DesktopSendState extends ConsumerState { ); if (paymentData != null && paymentData.coin?.uriScheme == coin.uriScheme) { - // auto fill address - _address = paymentData.address; - sendToController.text = _address!; - - // autofill notes field. - if (paymentData.message != null) { - _note = paymentData.message; - } else if (paymentData.label != null) { - _note = paymentData.label; - } - - // autofill amoutn field - if (paymentData.amount != null) { - final amount = Decimal.parse(paymentData.amount!).toAmount( - fractionDigits: coin.fractionDigits, - ); - cryptoAmountController.text = ref - .read(pAmountFormatter(coin)) - .format(amount, withUnitName: false); - ref.read(pSendAmount.notifier).state = amount; - } - - // Trigger validation after pasting. - _setValidAddressProviders(_address); - setState(() { - _addressToggleFlag = sendToController.text.isNotEmpty; - }); + _applyUri(paymentData); } else { content = content.split("\n").first.trim(); if (coin is Epiccash) { @@ -1439,7 +1421,20 @@ class _DesktopSendState extends ConsumerState { selectAll: false, ), onChanged: (newValue) { - _address = newValue; + final trimmed = newValue; + + if ((trimmed.length - (_address?.length ?? 0)).abs() > 1) { + final parsed = AddressUtils.parsePaymentUri(trimmed, logging: Logging.instance); + if (parsed != null) { + _applyUri(parsed); + } else { + _address = newValue; + sendToController.text = newValue; + } + } else { + _address = newValue; + } + _setValidAddressProviders(_address); setState(() {