From 4b69277858a75ea3beafb268eb9f4c60cef9f070 Mon Sep 17 00:00:00 2001 From: cyan Date: Tue, 13 Aug 2024 15:47:37 +0200 Subject: [PATCH] add mutex around _confirmForm to prevent the wallets from breaking (#1602) * add mutex around _confirmForm to prevent the wallets from breaking * add async * drop mutex for a boolean * don't make the variable global --- .../screens/new_wallet/new_wallet_page.dart | 49 +++--- .../screens/restore/wallet_restore_page.dart | 139 ++++++++++-------- 2 files changed, 106 insertions(+), 82 deletions(-) diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index b66aab4cf..cd5a7ce8d 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -25,6 +25,7 @@ import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/entities/seed_type.dart'; + class NewWalletPage extends BasePage { NewWalletPage(this._walletNewVM, this._seedTypeViewModel); @@ -74,6 +75,7 @@ class _WalletNameFormState extends State { _walletNewVM.hasWalletPassword ? TextEditingController() : null; static const aspectRatioImage = 1.22; + static bool formProcessing = false; final GlobalKey _formKey; final GlobalKey _languageSelectorKey; @@ -347,26 +349,35 @@ class _WalletNameFormState extends State { ); } - void _confirmForm() { - if (_formKey.currentState != null && !_formKey.currentState!.validate()) { - return; - } - if (_walletNewVM.nameExists(_walletNewVM.name)) { - showPopUp( - context: context, - builder: (_) { - return AlertWithOneAction( - alertTitle: '', - alertContent: S.of(context).wallet_name_exists, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); - } else { - _walletNewVM.create( - options: _walletNewVM.hasLanguageSelector - ? [_languageSelectorKey.currentState!.selected, isPolyseed] - : null); + void _confirmForm() async { + if (formProcessing) return; + formProcessing = true; + try { + if (_formKey.currentState != null && !_formKey.currentState!.validate()) { + formProcessing = false; + return; + } + if (_walletNewVM.nameExists(_walletNewVM.name)) { + await showPopUp( + context: context, + builder: (_) { + return AlertWithOneAction( + alertTitle: '', + alertContent: S.of(context).wallet_name_exists, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); + } else { + await _walletNewVM.create( + options: _walletNewVM.hasLanguageSelector + ? [_languageSelectorKey.currentState!.selected, isPolyseed] + : null); + } + } catch (e) { + formProcessing = false; + rethrow; } + formProcessing = false; } bool get isPolyseed => widget._seedTypeViewModel.moneroSeedType == SeedType.polyseed; diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index cd6383c0d..29bc29986 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/core/execution_state.dart'; 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/new_wallet/new_wallet_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_from_keys_form.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_form.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; @@ -80,6 +81,8 @@ class WalletRestorePage extends BasePage { }); } + static bool formProcessing = false; + @override Widget middle(BuildContext context) => Observer( builder: (_) => Text( @@ -350,75 +353,85 @@ class WalletRestorePage extends BasePage { } Future _confirmForm(BuildContext context) async { - // Dismissing all visible keyboard to provide context for navigation - FocusManager.instance.primaryFocus?.unfocus(); + if (formProcessing) return; + formProcessing = true; + try { + // Dismissing all visible keyboard to provide context for navigation + FocusManager.instance.primaryFocus?.unfocus(); - late BuildContext? formContext; - late GlobalKey? formKey; - late String name; - if (walletRestoreViewModel.mode == WalletRestoreMode.seed) { - formContext = walletRestoreFromSeedFormKey.currentContext; - formKey = walletRestoreFromSeedFormKey.currentState!.formKey; - name = walletRestoreFromSeedFormKey.currentState!.nameTextEditingController.value.text; - } else if (walletRestoreViewModel.mode == WalletRestoreMode.keys) { - formContext = walletRestoreFromKeysFormKey.currentContext; - formKey = walletRestoreFromKeysFormKey.currentState!.formKey; - name = walletRestoreFromKeysFormKey.currentState!.nameTextEditingController.value.text; - } - - if (!formKey!.currentState!.validate()) { - return; - } - - if (walletRestoreViewModel.nameExists(name)) { - showNameExistsAlert(formContext!); - return; - } - - walletRestoreViewModel.state = IsExecutingState(); - - DerivationInfo? dInfo; - - // get info about the different derivations: - List derivations = - await walletRestoreViewModel.getDerivationInfo(_credentials()); - - int derivationsWithHistory = 0; - int derivationWithHistoryIndex = 0; - for (int i = 0; i < derivations.length; i++) { - if (derivations[i].transactionsCount > 0) { - derivationsWithHistory++; - derivationWithHistoryIndex = i; + late BuildContext? formContext; + late GlobalKey? formKey; + late String name; + if (walletRestoreViewModel.mode == WalletRestoreMode.seed) { + formContext = walletRestoreFromSeedFormKey.currentContext; + formKey = walletRestoreFromSeedFormKey.currentState!.formKey; + name = walletRestoreFromSeedFormKey.currentState!.nameTextEditingController.value.text; + } else if (walletRestoreViewModel.mode == WalletRestoreMode.keys) { + formContext = walletRestoreFromKeysFormKey.currentContext; + formKey = walletRestoreFromKeysFormKey.currentState!.formKey; + name = walletRestoreFromKeysFormKey.currentState!.nameTextEditingController.value.text; } - } - if (derivationsWithHistory > 1) { - dInfo = await Navigator.of(context).pushNamed( - Routes.restoreWalletChooseDerivation, - arguments: derivations, - ) as DerivationInfo?; - } else if (derivationsWithHistory == 1) { - dInfo = derivations[derivationWithHistoryIndex]; - } - - // get the default derivation for this wallet type: - if (dInfo == null) { - // we only return 1 derivation if we're pretty sure we know which one to use: - if (derivations.length == 1) { - dInfo = derivations.first; - } else { - // if we have multiple possible derivations, and none have histories - // we just default to the most common one: - dInfo = walletRestoreViewModel.getCommonRestoreDerivation(); + if (!formKey!.currentState!.validate()) { + formProcessing = false; + return; } - } - this.derivationInfo = dInfo; - if (this.derivationInfo == null) { - this.derivationInfo = walletRestoreViewModel.getDefaultDerivation(); - } + if (walletRestoreViewModel.nameExists(name)) { + showNameExistsAlert(formContext!); + formProcessing = false; + return; + } - walletRestoreViewModel.create(options: _credentials()); + walletRestoreViewModel.state = IsExecutingState(); + + DerivationInfo? dInfo; + + // get info about the different derivations: + List derivations = + await walletRestoreViewModel.getDerivationInfo(_credentials()); + + int derivationsWithHistory = 0; + int derivationWithHistoryIndex = 0; + for (int i = 0; i < derivations.length; i++) { + if (derivations[i].transactionsCount > 0) { + derivationsWithHistory++; + derivationWithHistoryIndex = i; + } + } + + if (derivationsWithHistory > 1) { + dInfo = await Navigator.of(context).pushNamed( + Routes.restoreWalletChooseDerivation, + arguments: derivations, + ) as DerivationInfo?; + } else if (derivationsWithHistory == 1) { + dInfo = derivations[derivationWithHistoryIndex]; + } + + // get the default derivation for this wallet type: + if (dInfo == null) { + // we only return 1 derivation if we're pretty sure we know which one to use: + if (derivations.length == 1) { + dInfo = derivations.first; + } else { + // if we have multiple possible derivations, and none have histories + // we just default to the most common one: + dInfo = walletRestoreViewModel.getCommonRestoreDerivation(); + } + } + + this.derivationInfo = dInfo; + if (this.derivationInfo == null) { + this.derivationInfo = walletRestoreViewModel.getDefaultDerivation(); + } + + await walletRestoreViewModel.create(options: _credentials()); + } catch (e) { + formProcessing = false; + rethrow; + } + formProcessing = false; } Future showNameExistsAlert(BuildContext context) {