diff --git a/lib/pages/special/firo_rescan_recovery_error_dialog.dart b/lib/pages/special/firo_rescan_recovery_error_dialog.dart new file mode 100644 index 000000000..6248313f4 --- /dev/null +++ b/lib/pages/special/firo_rescan_recovery_error_dialog.dart @@ -0,0 +1,225 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart'; +import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart'; +import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart'; +import 'package:stackwallet/providers/global/wallets_provider.dart'; +import 'package:stackwallet/route_generator.dart'; +import 'package:stackwallet/themes/stack_colors.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/background.dart'; +import 'package:stackwallet/widgets/conditional_parent.dart'; +import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/stack_dialog.dart'; +import 'package:tuple/tuple.dart'; + +enum FiroRescanRecoveryErrorViewOption { + retry, + showMnemonic, + deleteWallet; +} + +class FiroRescanRecoveryErrorView extends ConsumerStatefulWidget { + const FiroRescanRecoveryErrorView({ + super.key, + required this.walletId, + }); + + static const String routeName = "/firoRescanRecoveryErrorView"; + + final String walletId; + + @override + ConsumerState createState() => + _FiroRescanRecoveryErrorViewState(); +} + +class _FiroRescanRecoveryErrorViewState + extends ConsumerState { + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async => false, + child: ConditionalParent( + condition: Util.isDesktop, + builder: (child) { + return child; + }, + child: ConditionalParent( + condition: !Util.isDesktop, + builder: (child) { + return Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + automaticallyImplyLeading: false, + actions: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + semanticsLabel: "Delete wallet button. " + "Start process of deleting current wallet.", + key: const Key("walletViewRadioButton"), + size: 36, + shadows: const [], + color: Theme.of(context) + .extension()! + .background, + icon: SvgPicture.asset( + Assets.svg.trash, + width: 20, + height: 20, + color: Theme.of(context) + .extension()! + .topNavIconPrimary, + ), + onPressed: () async { + await showDialog( + barrierDismissible: true, + context: context, + builder: (_) => StackDialog( + title: + "Do you want to delete ${ref.read(walletsChangeNotifierProvider).getManager(widget.walletId).walletName}?", + leftButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + "Cancel", + style: STextStyles.button(context).copyWith( + color: Theme.of(context) + .extension()! + .accentColorDark), + ), + ), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () { + Navigator.pop(context); + Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: (_) => LockscreenView( + routeOnSuccessArguments: + widget.walletId, + showBackButton: true, + routeOnSuccess: + DeleteWalletWarningView.routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to delete wallet", + biometricsAuthenticationTitle: + "Delete wallet", + ), + settings: const RouteSettings( + name: "/deleteWalletLockscreen"), + ), + ); + }, + child: Text( + "Delete", + style: STextStyles.button(context), + ), + ), + ), + ); + }, + ), + ), + ), + ], + ), + body: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), + ), + ); + }, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (!Util.isDesktop) const Spacer(), + Text( + "Failed to rescan firo wallet", + style: STextStyles.pageTitleH2(context), + ), + if (!Util.isDesktop) const Spacer(), + Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Show mnemonic", + onPressed: () async { + final mnemonic = await ref + .read(walletsChangeNotifierProvider) + .getManager(widget.walletId) + .mnemonic; + + if (mounted) { + await Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: (_) => LockscreenView( + routeOnSuccessArguments: + Tuple2(widget.walletId, mnemonic), + showBackButton: true, + routeOnSuccess: WalletBackupView.routeName, + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to view recovery phrase", + biometricsAuthenticationTitle: + "View recovery phrase", + ), + settings: const RouteSettings( + name: "/viewRecoverPhraseLockscreen"), + ), + ); + } + }, + ), + ), + const SizedBox( + width: 16, + ), + Expanded( + child: PrimaryButton( + label: "Retry", + onPressed: () { + Navigator.of(context).pop( + true, + ); + }, + ), + ), + ], + ) + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/wallet_view/wallet_view.dart b/lib/pages/wallet_view/wallet_view.dart index a4d7a69b6..c9e391320 100644 --- a/lib/pages/wallet_view/wallet_view.dart +++ b/lib/pages/wallet_view/wallet_view.dart @@ -27,13 +27,10 @@ import 'package:stackwallet/pages/notification_views/notifications_view.dart'; import 'package:stackwallet/pages/ordinals/ordinals_view.dart'; import 'package:stackwallet/pages/paynym/paynym_claim_view.dart'; import 'package:stackwallet/pages/paynym/paynym_home_view.dart'; -import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart'; import 'package:stackwallet/pages/receive_view/receive_view.dart'; import 'package:stackwallet/pages/send_view/send_view.dart'; -import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_view.dart'; -import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart'; import 'package:stackwallet/pages/special/firo_rescan_recovery_error_dialog.dart'; import 'package:stackwallet/pages/token_view/my_tokens_view.dart'; import 'package:stackwallet/pages/wallet_view/sub_widgets/transactions_list.dart'; @@ -47,7 +44,6 @@ import 'package:stackwallet/providers/ui/unread_notifications_provider.dart'; import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart'; import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart'; import 'package:stackwallet/providers/wallet/wallet_balance_toggle_state_provider.dart'; -import 'package:stackwallet/route_generator.dart'; import 'package:stackwallet/services/coins/firo/firo_wallet.dart'; import 'package:stackwallet/services/coins/manager.dart'; import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart'; @@ -141,101 +137,13 @@ class _WalletViewState extends ConsumerState { } else { // show error message dialog w/ options if (mounted) { - final result = await showDialog( - context: context, - builder: (_) => FiroRescanRecoveryErrorDialog( - walletId: widget.walletId, - ), + final shouldRetry = await Navigator.of(context).pushNamed( + FiroRescanRecoveryErrorView.routeName, + arguments: walletId, ); - switch (result!) { - case FiroRescanRecoveryErrorDialogOption.showMnemonic: - final mnemonic = await ref - .read(walletsChangeNotifierProvider) - .getManager(widget.walletId) - .mnemonic; - - if (mounted) { - await Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => LockscreenView( - routeOnSuccessArguments: Tuple2(widget.walletId, mnemonic), - showBackButton: true, - routeOnSuccess: WalletBackupView.routeName, - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: - "Authenticate to view recovery phrase", - biometricsAuthenticationTitle: "View recovery phrase", - ), - settings: - const RouteSettings(name: "/viewRecoverPhraseLockscreen"), - ), - ); - } - return; - - case FiroRescanRecoveryErrorDialogOption.deleteWallet: - if (mounted) { - await showDialog( - barrierDismissible: true, - context: context, - builder: (_) => StackDialog( - title: - "Do you want to delete ${ref.read(walletsChangeNotifierProvider).getManager(walletId).walletName}?", - leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - }, - child: Text( - "Cancel", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark), - ), - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, - builder: (_) => LockscreenView( - routeOnSuccessArguments: walletId, - showBackButton: true, - routeOnSuccess: DeleteWalletWarningView.routeName, - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: - "Authenticate to delete wallet", - biometricsAuthenticationTitle: "Delete wallet", - ), - settings: const RouteSettings( - name: "/deleteWalletLockscreen"), - ), - ); - }, - child: Text( - "Delete", - style: STextStyles.button(context), - ), - ), - ), - ); - } - return; - - case FiroRescanRecoveryErrorDialogOption.retry: - return await _firoRescanRecovery(); + if (shouldRetry is bool && shouldRetry) { + await _firoRescanRecovery(); } } else { return await _firoRescanRecovery(); @@ -262,14 +170,7 @@ class _WalletViewState extends ConsumerState { .lelantusCoinIsarRescanRequired) { _rescanningOnOpen = true; _lelantusRescanRecovery = true; - _firoRescanRecovery().then( - (_) => WidgetsBinding.instance.addPostFrameCallback( - (_) => setState(() { - _rescanningOnOpen = false; - _lelantusRescanRecovery = false; - }), - ), - ); + _firoRescanRecovery(); } else if (ref.read(managerProvider).rescanOnOpenVersion == Constants.rescanV1) { _rescanningOnOpen = true; diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 8916bb008..2b7aa662d 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -118,6 +118,7 @@ import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_set import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart'; +import 'package:stackwallet/pages/special/firo_rescan_recovery_error_dialog.dart'; import 'package:stackwallet/pages/stack_privacy_calls.dart'; import 'package:stackwallet/pages/token_view/my_tokens_view.dart'; import 'package:stackwallet/pages/token_view/token_contract_details_view.dart'; @@ -264,6 +265,20 @@ class RouteGenerator { } return _routeError("${settings.name} invalid args: ${args.toString()}"); + case FiroRescanRecoveryErrorView.routeName: + if (args is String) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => FiroRescanRecoveryErrorView( + walletId: args, + ), + settings: RouteSettings( + name: settings.name, + ), + ); + } + return _routeError("${settings.name} invalid args: ${args.toString()}"); + case WalletsView.routeName: return getRoute( shouldUseMaterialRoute: useMaterialPageRoute,