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
cyan committed
Aug 13, 2024 at 15:47 UTC
4b69277858a75ea3beafb268eb9f4c60cef9f070
2 files changed
+99
-75
lib/src/screens/new_wallet/new_wallet_page.dart
+30
-19
@@ -25,6 +25,7 @@ import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart';
25
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
26
import 'package:cake_wallet/entities/seed_type.dart';
27
28
+
29
class NewWalletPage extends BasePage {
30
NewWalletPage(this._walletNewVM, this._seedTypeViewModel);
31
@@ -74,6 +75,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
75
_walletNewVM.hasWalletPassword ? TextEditingController() : null;
76
77
static const aspectRatioImage = 1.22;
78
+ static bool formProcessing = false;
79
80
final GlobalKey<FormState> _formKey;
81
final GlobalKey<SeedLanguageSelectorState> _languageSelectorKey;
@@ -347,26 +349,35 @@ class _WalletNameFormState extends State<WalletNameForm> {
349
);
350
}
351
350
- void _confirmForm() {
351
- if (_formKey.currentState != null && !_formKey.currentState!.validate()) {
352
- return;
353
- }
354
- if (_walletNewVM.nameExists(_walletNewVM.name)) {
355
- showPopUp<void>(
356
- context: context,
357
- builder: (_) {
358
- return AlertWithOneAction(
359
- alertTitle: '',
360
- alertContent: S.of(context).wallet_name_exists,
361
- buttonText: S.of(context).ok,
362
- buttonAction: () => Navigator.of(context).pop());
363
- });
364
- } else {
365
- _walletNewVM.create(
366
- options: _walletNewVM.hasLanguageSelector
367
- ? [_languageSelectorKey.currentState!.selected, isPolyseed]
368
- : null);
352
+ void _confirmForm() async {
353
+ if (formProcessing) return;
354
+ formProcessing = true;
355
+ try {
356
+ if (_formKey.currentState != null && !_formKey.currentState!.validate()) {
357
+ formProcessing = false;
358
+ return;
359
+ }
360
+ if (_walletNewVM.nameExists(_walletNewVM.name)) {
361
+ await showPopUp<void>(
362
+ context: context,
363
+ builder: (_) {
364
+ return AlertWithOneAction(
365
+ alertTitle: '',
366
+ alertContent: S.of(context).wallet_name_exists,
367
+ buttonText: S.of(context).ok,
368
+ buttonAction: () => Navigator.of(context).pop());
369
+ });
370
+ } else {
371
+ await _walletNewVM.create(
372
+ options: _walletNewVM.hasLanguageSelector
373
+ ? [_languageSelectorKey.currentState!.selected, isPolyseed]
374
+ : null);
375
+ }
376
+ } catch (e) {
377
+ formProcessing = false;
378
+ rethrow;
379
}
380
+ formProcessing = false;
381
}
382
383
bool get isPolyseed => widget._seedTypeViewModel.moneroSeedType == SeedType.polyseed;
lib/src/screens/restore/wallet_restore_page.dart
+69
-56
@@ -2,6 +2,7 @@ import 'package:cake_wallet/core/execution_state.dart';
2
import 'package:cake_wallet/generated/i18n.dart';
3
import 'package:cake_wallet/routes.dart';
4
import 'package:cake_wallet/src/screens/base_page.dart';
5
+import 'package:cake_wallet/src/screens/new_wallet/new_wallet_page.dart';
6
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_keys_form.dart';
7
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_form.dart';
8
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
@@ -80,6 +81,8 @@ class WalletRestorePage extends BasePage {
81
});
82
}
83
84
+ static bool formProcessing = false;
85
+
86
@override
87
Widget middle(BuildContext context) => Observer(
88
builder: (_) => Text(
@@ -350,75 +353,85 @@ class WalletRestorePage extends BasePage {
353
}
354
355
Future<void> _confirmForm(BuildContext context) async {
353
- // Dismissing all visible keyboard to provide context for navigation
354
- FocusManager.instance.primaryFocus?.unfocus();
356
+ if (formProcessing) return;
357
+ formProcessing = true;
358
+ try {
359
+ // Dismissing all visible keyboard to provide context for navigation
360
+ FocusManager.instance.primaryFocus?.unfocus();
361
+
362
+ late BuildContext? formContext;
363
+ late GlobalKey<FormState>? formKey;
364
+ late String name;
365
+ if (walletRestoreViewModel.mode == WalletRestoreMode.seed) {
366
+ formContext = walletRestoreFromSeedFormKey.currentContext;
367
+ formKey = walletRestoreFromSeedFormKey.currentState!.formKey;
368
+ name = walletRestoreFromSeedFormKey.currentState!.nameTextEditingController.value.text;
369
+ } else if (walletRestoreViewModel.mode == WalletRestoreMode.keys) {
370
+ formContext = walletRestoreFromKeysFormKey.currentContext;
371
+ formKey = walletRestoreFromKeysFormKey.currentState!.formKey;
372
+ name = walletRestoreFromKeysFormKey.currentState!.nameTextEditingController.value.text;
373
+ }
374
356
- late BuildContext? formContext;
357
- late GlobalKey<FormState>? formKey;
358
- late String name;
359
- if (walletRestoreViewModel.mode == WalletRestoreMode.seed) {
360
- formContext = walletRestoreFromSeedFormKey.currentContext;
361
- formKey = walletRestoreFromSeedFormKey.currentState!.formKey;
362
- name = walletRestoreFromSeedFormKey.currentState!.nameTextEditingController.value.text;
363
- } else if (walletRestoreViewModel.mode == WalletRestoreMode.keys) {
364
- formContext = walletRestoreFromKeysFormKey.currentContext;
365
- formKey = walletRestoreFromKeysFormKey.currentState!.formKey;
366
- name = walletRestoreFromKeysFormKey.currentState!.nameTextEditingController.value.text;
367
- }
375
+ if (!formKey!.currentState!.validate()) {
376
+ formProcessing = false;
377
+ return;
378
+ }
379
369
- if (!formKey!.currentState!.validate()) {
370
- return;
371
- }
380
+ if (walletRestoreViewModel.nameExists(name)) {
381
+ showNameExistsAlert(formContext!);
382
+ formProcessing = false;
383
+ return;
384
+ }
385
373
- if (walletRestoreViewModel.nameExists(name)) {
374
- showNameExistsAlert(formContext!);
375
- return;
376
- }
386
+ walletRestoreViewModel.state = IsExecutingState();
387
378
- walletRestoreViewModel.state = IsExecutingState();
388
+ DerivationInfo? dInfo;
389
380
- DerivationInfo? dInfo;
390
+ // get info about the different derivations:
391
+ List<DerivationInfo> derivations =
392
+ await walletRestoreViewModel.getDerivationInfo(_credentials());
393
382
- // get info about the different derivations:
383
- List<DerivationInfo> derivations =
384
- await walletRestoreViewModel.getDerivationInfo(_credentials());
394
+ int derivationsWithHistory = 0;
395
+ int derivationWithHistoryIndex = 0;
396
+ for (int i = 0; i < derivations.length; i++) {
397
+ if (derivations[i].transactionsCount > 0) {
398
+ derivationsWithHistory++;
399
+ derivationWithHistoryIndex = i;
400
+ }
401
+ }
402
386
- int derivationsWithHistory = 0;
387
- int derivationWithHistoryIndex = 0;
388
- for (int i = 0; i < derivations.length; i++) {
389
- if (derivations[i].transactionsCount > 0) {
390
- derivationsWithHistory++;
391
- derivationWithHistoryIndex = i;
403
+ if (derivationsWithHistory > 1) {
404
+ dInfo = await Navigator.of(context).pushNamed(
405
+ Routes.restoreWalletChooseDerivation,
406
+ arguments: derivations,
407
+ ) as DerivationInfo?;
408
+ } else if (derivationsWithHistory == 1) {
409
+ dInfo = derivations[derivationWithHistoryIndex];
410
}
393
- }
411
395
- if (derivationsWithHistory > 1) {
396
- dInfo = await Navigator.of(context).pushNamed(
397
- Routes.restoreWalletChooseDerivation,
398
- arguments: derivations,
399
- ) as DerivationInfo?;
400
- } else if (derivationsWithHistory == 1) {
401
- dInfo = derivations[derivationWithHistoryIndex];
402
- }
412
+ // get the default derivation for this wallet type:
413
+ if (dInfo == null) {
414
+ // we only return 1 derivation if we're pretty sure we know which one to use:
415
+ if (derivations.length == 1) {
416
+ dInfo = derivations.first;
417
+ } else {
418
+ // if we have multiple possible derivations, and none have histories
419
+ // we just default to the most common one:
420
+ dInfo = walletRestoreViewModel.getCommonRestoreDerivation();
421
+ }
422
+ }
423
404
- // get the default derivation for this wallet type:
405
- if (dInfo == null) {
406
- // we only return 1 derivation if we're pretty sure we know which one to use:
407
- if (derivations.length == 1) {
408
- dInfo = derivations.first;
409
- } else {
410
- // if we have multiple possible derivations, and none have histories
411
- // we just default to the most common one:
412
- dInfo = walletRestoreViewModel.getCommonRestoreDerivation();
424
+ this.derivationInfo = dInfo;
425
+ if (this.derivationInfo == null) {
426
+ this.derivationInfo = walletRestoreViewModel.getDefaultDerivation();
427
}
414
- }
428
416
- this.derivationInfo = dInfo;
417
- if (this.derivationInfo == null) {
418
- this.derivationInfo = walletRestoreViewModel.getDefaultDerivation();
429
+ await walletRestoreViewModel.create(options: _credentials());
430
+ } catch (e) {
431
+ formProcessing = false;
432
+ rethrow;
433
}
420
-
421
- walletRestoreViewModel.create(options: _credentials());
434
+ formProcessing = false;
435
}
436
437
Future<void> showNameExistsAlert(BuildContext context) {