From 2ada2d5bded40bc6ae6a82feb3a8428bacc8d352 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 26 Aug 2022 10:38:17 -0600 Subject: [PATCH] override paste in first text field on mnemonic restore form --- .../restore_wallet_view.dart | 73 +++++++++++++------ .../custom_text_selection_controls.dart | 22 ++++++ 2 files changed, 71 insertions(+), 24 deletions(-) create mode 100644 lib/utilities/custom_text_selection_controls.dart diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index f377f212d..4e4871bda 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'dart:collection'; -import 'dart:math'; import 'dart:io'; +import 'dart:math'; import 'package:bip39/bip39.dart' as bip39; import 'package:bip39/src/wordlists/english.dart' as bip39wordlist; @@ -26,6 +26,7 @@ import 'package:stackwallet/utilities/barcode_scanner_interface.dart'; import 'package:stackwallet/utilities/cfcolors.dart'; import 'package:stackwallet/utilities/clipboard_interface.dart'; import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/custom_text_selection_controls.dart'; import 'package:stackwallet/utilities/default_nodes.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/flush_bar_type.dart'; @@ -70,25 +71,61 @@ class _RestoreWalletViewState extends ConsumerState { final ScrollController controller = ScrollController(); final List _controllers = []; - // late final TextEditingController _heightController; final List _inputStatuses = []; - // late final FocusNode _heightFocusNode; - late final BarcodeScannerInterface scanner; + late final TextSelectionControls textSelectionControls; + + Future onControlsPaste(TextSelectionDelegate delegate) async { + final data = await widget.clipboard.getData(Clipboard.kTextPlain); + if (data?.text == null) { + return; + } + + final text = data!.text!.trim(); + if (text.isEmpty || _controllers.isEmpty) { + delegate.pasteText(SelectionChangedCause.toolbar); + return; + } + + final words = text.split(" "); + if (words.isEmpty) { + delegate.pasteText(SelectionChangedCause.toolbar); + return; + } + + if (words.length == 1) { + _controllers.first.text = words.first; + if (_isValidMnemonicWord(words.first.toLowerCase())) { + setState(() { + _inputStatuses.first = FormInputStatus.valid; + }); + } else { + setState(() { + _inputStatuses.first = FormInputStatus.invalid; + }); + } + return; + } + + _clearAndPopulateMnemonic(words); + } + @override void initState() { _seedWordCount = widget.seedWordsLength; - // _heightFocusNode = FocusNode(); + textSelectionControls = Platform.isIOS + ? CustomCupertinoTextSelectionControls(onPaste: onControlsPaste) + : CustomMaterialTextSelectionControls(onPaste: onControlsPaste); scanner = widget.barcodeScanner; for (int i = 0; i < _seedWordCount; i++) { _controllers.add(TextEditingController()); _inputStatuses.add(FormInputStatus.empty); } - // _heightController = TextEditingController(); + super.initState(); } @@ -97,8 +134,7 @@ class _RestoreWalletViewState extends ConsumerState { for (var element in _controllers) { element.dispose(); } - // _heightController.dispose(); - // _heightFocusNode.dispose(); + super.dispose(); } @@ -404,6 +440,9 @@ class _RestoreWalletViewState extends ConsumerState { _inputStatuses[i] = FormInputStatus.empty; }); } + + controller.animateTo(controller.position.maxScrollExtent, + duration: const Duration(milliseconds: 300), curve: Curves.decelerate); } @override @@ -442,18 +481,8 @@ class _RestoreWalletViewState extends ConsumerState { ), onPressed: () async { try { - // ref - // .read(shouldShowLockscreenOnResumeStateProvider.state) - // .state = false; final qrResult = await scanner.scan(); - // Future.delayed( - // const Duration(seconds: 2), - // () => ref - // .read(shouldShowLockscreenOnResumeStateProvider.state) - // .state = true, - // ); - final results = AddressUtils.decodeQRSeedData(qrResult.rawContent); @@ -474,9 +503,6 @@ class _RestoreWalletViewState extends ConsumerState { } } } on PlatformException catch (e) { - // ref - // .read(shouldShowLockscreenOnResumeStateProvider.state) - // .state = true; // likely failed to get camera permissions Logging.instance.log("Restore wallet qr scan failed: $e", level: LogLevel.Warning); @@ -512,9 +538,6 @@ class _RestoreWalletViewState extends ConsumerState { final content = data.text!.trim(); final list = content.split(" "); _clearAndPopulateMnemonic(list); - controller.animateTo(controller.position.maxScrollExtent, - duration: const Duration(milliseconds: 300), - curve: Curves.decelerate); } }, ), @@ -572,6 +595,8 @@ class _RestoreWalletViewState extends ConsumerState { _inputStatuses[i - 1], "$i"), autovalidateMode: AutovalidateMode.onUserInteraction, + selectionControls: + i == 1 ? textSelectionControls : null, onChanged: (value) { if (value.isEmpty) { setState(() { diff --git a/lib/utilities/custom_text_selection_controls.dart b/lib/utilities/custom_text_selection_controls.dart new file mode 100644 index 000000000..e51f317fe --- /dev/null +++ b/lib/utilities/custom_text_selection_controls.dart @@ -0,0 +1,22 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class CustomMaterialTextSelectionControls + extends MaterialTextSelectionControls { + CustomMaterialTextSelectionControls({required this.onPaste}); + ValueChanged onPaste; + @override + Future handlePaste(final TextSelectionDelegate delegate) async { + return onPaste(delegate); + } +} + +class CustomCupertinoTextSelectionControls + extends CupertinoTextSelectionControls { + CustomCupertinoTextSelectionControls({required this.onPaste}); + ValueChanged onPaste; + @override + Future handlePaste(final TextSelectionDelegate delegate) async { + return onPaste(delegate); + } +}