From 2652655249dab186fb3394b8e386734e6382b5bd Mon Sep 17 00:00:00 2001 From: Damian Molinski Date: Mon, 14 Oct 2024 13:31:01 +0200 Subject: [PATCH] feat: exit dialog --- .../registration/registration_dialog.dart | 45 +++++++-- .../registration_exit_confirm_dialog.dart | 55 ----------- .../widgets/exit_confirm_dialog.dart | 96 +++++++++++++++++++ .../catalyst_voices_localizations.dart | 22 ++++- .../catalyst_voices_localizations_en.dart | 11 ++- .../catalyst_voices_localizations_es.dart | 11 ++- .../lib/l10n/intl_en.arb | 7 +- .../src/registration/registration_step.dart | 16 ++++ 8 files changed, 195 insertions(+), 68 deletions(-) delete mode 100644 catalyst_voices/lib/pages/registration/registration_exit_confirm_dialog.dart create mode 100644 catalyst_voices/lib/pages/registration/widgets/exit_confirm_dialog.dart diff --git a/catalyst_voices/lib/pages/registration/registration_dialog.dart b/catalyst_voices/lib/pages/registration/registration_dialog.dart index c9449974ec..6944033a1e 100644 --- a/catalyst_voices/lib/pages/registration/registration_dialog.dart +++ b/catalyst_voices/lib/pages/registration/registration_dialog.dart @@ -3,10 +3,11 @@ import 'dart:async'; import 'package:catalyst_voices/common/error_handler.dart'; import 'package:catalyst_voices/dependency/dependencies.dart'; import 'package:catalyst_voices/pages/registration/registration_details_panel.dart'; -import 'package:catalyst_voices/pages/registration/registration_exit_confirm_dialog.dart'; import 'package:catalyst_voices/pages/registration/registration_info_panel.dart'; +import 'package:catalyst_voices/pages/registration/widgets/exit_confirm_dialog.dart'; import 'package:catalyst_voices/widgets/widgets.dart'; import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart'; +import 'package:catalyst_voices_models/catalyst_voices_models.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -54,7 +55,12 @@ class _RegistrationDialogState extends State child: PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) { - unawaited(_confirmedExit(context, didPop: didPop)); + unawaited( + _handlePop( + context, + didPop: didPop, + ), + ); }, child: const VoicesTwoPaneDialog( left: RegistrationInfoPanel(), @@ -64,7 +70,7 @@ class _RegistrationDialogState extends State ); } - Future _confirmedExit( + Future _handlePop( BuildContext context, { required bool didPop, }) async { @@ -72,13 +78,38 @@ class _RegistrationDialogState extends State return; } - final confirmed = await VoicesQuestionDialog.show( - context, - builder: (_) => const RegistrationExitConfirmDialog(), - ); + final state = _cubit.state; + final hasProgress = (state.progress ?? 0.0) > 0.0; + if (!hasProgress) { + Navigator.of(context).pop(); + return; + } + + final confirmed = await _confirmExit(context, step: state.step); if (context.mounted && confirmed) { Navigator.of(context).pop(); } } + + Future _confirmExit( + BuildContext context, { + required RegistrationStep step, + }) { + if (step.isRegistrationFlow) { + return VoicesQuestionDialog.show( + context, + builder: (_) => const RegistrationExitConfirmDialog(), + ); + } + + if (step.isRecoverFlow) { + return VoicesQuestionDialog.show( + context, + builder: (_) => const RecoveryExitConfirmDialog(), + ); + } + + return Future.value(true); + } } diff --git a/catalyst_voices/lib/pages/registration/registration_exit_confirm_dialog.dart b/catalyst_voices/lib/pages/registration/registration_exit_confirm_dialog.dart deleted file mode 100644 index e8a8a1f0fa..0000000000 --- a/catalyst_voices/lib/pages/registration/registration_exit_confirm_dialog.dart +++ /dev/null @@ -1,55 +0,0 @@ -import 'package:catalyst_voices/widgets/widgets.dart'; -import 'package:catalyst_voices_assets/catalyst_voices_assets.dart'; -import 'package:catalyst_voices_brands/catalyst_voices_brands.dart'; -import 'package:catalyst_voices_localization/catalyst_voices_localization.dart'; -import 'package:flutter/material.dart'; - -class RegistrationExitConfirmDialog extends StatelessWidget { - const RegistrationExitConfirmDialog({super.key}); - - @override - Widget build(BuildContext context) { - final l10n = context.l10n; - - return VoicesQuestionDialog( - title: Text(l10n.warning.toUpperCase()), - icon: const _WarningIcon(), - subtitle: Text(l10n.registrationExitConfirmDialogSubtitle.toUpperCase()), - content: Padding( - padding: const EdgeInsets.only(bottom: 30), - child: Text(l10n.registrationExitConfirmDialogContent), - ), - actions: [ - VoicesQuestionActionItem.negative( - l10n.registrationExitConfirmDialogContinue, - type: VoicesQuestionActionType.filled, - ), - VoicesQuestionActionItem.positive( - l10n.registrationExitConfirmDialogCancel, - type: VoicesQuestionActionType.text, - ), - ], - ); - } -} - -class _WarningIcon extends StatelessWidget { - const _WarningIcon(); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - final color = theme.colors.iconsError!; - - return VoicesAvatar( - border: Border.all( - color: color, - width: 3, - ), - icon: VoicesAssets.icons.exclamation.buildIcon(size: 36), - backgroundColor: Colors.transparent, - foregroundColor: color, - radius: 40, - ); - } -} diff --git a/catalyst_voices/lib/pages/registration/widgets/exit_confirm_dialog.dart b/catalyst_voices/lib/pages/registration/widgets/exit_confirm_dialog.dart new file mode 100644 index 0000000000..95d0948a67 --- /dev/null +++ b/catalyst_voices/lib/pages/registration/widgets/exit_confirm_dialog.dart @@ -0,0 +1,96 @@ +import 'package:catalyst_voices/widgets/widgets.dart'; +import 'package:catalyst_voices_assets/catalyst_voices_assets.dart'; +import 'package:catalyst_voices_brands/catalyst_voices_brands.dart'; +import 'package:catalyst_voices_localization/catalyst_voices_localization.dart'; +import 'package:flutter/material.dart'; + +class RecoveryExitConfirmDialog extends StatelessWidget { + const RecoveryExitConfirmDialog({super.key}); + + @override + Widget build(BuildContext context) { + return ExitConfirmDialog( + title: context.l10n.warning, + subtitle: context.l10n.recoveryExitConfirmDialogSubtitle, + content: context.l10n.recoveryExitConfirmDialogContent, + positive: context.l10n.recoveryExitConfirmDialogContinue, + negative: context.l10n.cancelAnyways, + ); + } +} + +class RegistrationExitConfirmDialog extends StatelessWidget { + const RegistrationExitConfirmDialog({super.key}); + + @override + Widget build(BuildContext context) { + return ExitConfirmDialog( + title: context.l10n.warning, + subtitle: context.l10n.registrationExitConfirmDialogSubtitle, + content: context.l10n.registrationExitConfirmDialogContent, + positive: context.l10n.registrationExitConfirmDialogContinue, + negative: context.l10n.cancelAnyways, + ); + } +} + +class ExitConfirmDialog extends StatelessWidget { + final String title; + final String subtitle; + final String content; + final String positive; + final String negative; + + const ExitConfirmDialog({ + super.key, + required this.title, + required this.subtitle, + required this.content, + required this.positive, + required this.negative, + }); + + @override + Widget build(BuildContext context) { + return VoicesQuestionDialog( + title: Text(title.toUpperCase()), + icon: const _WarningIcon(), + subtitle: Text(subtitle.toUpperCase()), + content: Padding( + padding: const EdgeInsets.only(bottom: 30), + child: Text(content), + ), + actions: [ + VoicesQuestionActionItem.negative( + positive, + type: VoicesQuestionActionType.filled, + ), + VoicesQuestionActionItem.positive( + negative, + type: VoicesQuestionActionType.text, + ), + ], + ); + } +} + +class _WarningIcon extends StatelessWidget { + const _WarningIcon(); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final color = theme.colors.iconsError!; + + return VoicesAvatar( + border: Border.all( + color: color, + width: 3, + ), + icon: VoicesAssets.icons.exclamation.buildIcon(size: 36), + backgroundColor: Colors.transparent, + foregroundColor: color, + radius: 40, + ); + } +} diff --git a/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations.dart b/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations.dart index ad4067afca..b6869d9e60 100644 --- a/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations.dart +++ b/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations.dart @@ -1552,11 +1552,11 @@ abstract class VoicesLocalizations { /// **'Continue keychain creation'** String get registrationExitConfirmDialogContinue; - /// No description provided for @registrationExitConfirmDialogCancel. + /// No description provided for @cancelAnyways. /// /// In en, this message translates to: /// **'Cancel anyway'** - String get registrationExitConfirmDialogCancel; + String get cancelAnyways; /// No description provided for @recoverCatalystKeychain. /// @@ -1683,6 +1683,24 @@ abstract class VoicesLocalizations { /// In en, this message translates to: /// **'Check my account'** String get recoverySuccessGoAccount; + + /// No description provided for @recoveryExitConfirmDialogSubtitle. + /// + /// In en, this message translates to: + /// **'12 word keychain restoration incomplete'** + String get recoveryExitConfirmDialogSubtitle; + + /// No description provided for @recoveryExitConfirmDialogContent. + /// + /// In en, this message translates to: + /// **'Please continue your Catalyst Keychain restoration, if you cancel all input will be lost.'** + String get recoveryExitConfirmDialogContent; + + /// No description provided for @recoveryExitConfirmDialogContinue. + /// + /// In en, this message translates to: + /// **'Continue recovery process'** + String get recoveryExitConfirmDialogContinue; } class _VoicesLocalizationsDelegate extends LocalizationsDelegate { diff --git a/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_en.dart b/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_en.dart index c9e7c7560e..d4ad0ad93a 100644 --- a/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_en.dart +++ b/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_en.dart @@ -818,7 +818,7 @@ class VoicesLocalizationsEn extends VoicesLocalizations { String get registrationExitConfirmDialogContinue => 'Continue keychain creation'; @override - String get registrationExitConfirmDialogCancel => 'Cancel anyway'; + String get cancelAnyways => 'Cancel anyway'; @override String get recoverCatalystKeychain => 'Restore Catalyst keychain'; @@ -882,4 +882,13 @@ class VoicesLocalizationsEn extends VoicesLocalizations { @override String get recoverySuccessGoAccount => 'Check my account'; + + @override + String get recoveryExitConfirmDialogSubtitle => '12 word keychain restoration incomplete'; + + @override + String get recoveryExitConfirmDialogContent => 'Please continue your Catalyst Keychain restoration, if you cancel all input will be lost.'; + + @override + String get recoveryExitConfirmDialogContinue => 'Continue recovery process'; } diff --git a/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_es.dart b/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_es.dart index 74d015c871..16aed19d4f 100644 --- a/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_es.dart +++ b/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_es.dart @@ -818,7 +818,7 @@ class VoicesLocalizationsEs extends VoicesLocalizations { String get registrationExitConfirmDialogContinue => 'Continue keychain creation'; @override - String get registrationExitConfirmDialogCancel => 'Cancel anyway'; + String get cancelAnyways => 'Cancel anyway'; @override String get recoverCatalystKeychain => 'Restore Catalyst keychain'; @@ -882,4 +882,13 @@ class VoicesLocalizationsEs extends VoicesLocalizations { @override String get recoverySuccessGoAccount => 'Check my account'; + + @override + String get recoveryExitConfirmDialogSubtitle => '12 word keychain restoration incomplete'; + + @override + String get recoveryExitConfirmDialogContent => 'Please continue your Catalyst Keychain restoration, if you cancel all input will be lost.'; + + @override + String get recoveryExitConfirmDialogContinue => 'Continue recovery process'; } diff --git a/catalyst_voices/packages/catalyst_voices_localization/lib/l10n/intl_en.arb b/catalyst_voices/packages/catalyst_voices_localization/lib/l10n/intl_en.arb index afe2ab0b2b..d3a0988089 100644 --- a/catalyst_voices/packages/catalyst_voices_localization/lib/l10n/intl_en.arb +++ b/catalyst_voices/packages/catalyst_voices_localization/lib/l10n/intl_en.arb @@ -864,7 +864,7 @@ "registrationExitConfirmDialogSubtitle": "Account creation incomplete!", "registrationExitConfirmDialogContent": "If attempt to leave without creating your keychain - account creation will be incomplete. \u2028\u2028You are not able to login without \u2028completing your keychain.", "registrationExitConfirmDialogContinue": "Continue keychain creation", - "registrationExitConfirmDialogCancel": "Cancel anyway", + "cancelAnyways": "Cancel anyway", "recoverCatalystKeychain": "Restore Catalyst keychain", "recoverKeychainMethodsTitle": "Restore your Catalyst Keychain", "recoverKeychainMethodsNoKeychainFound": "No Catalyst Keychain found on this device.", @@ -885,5 +885,8 @@ "recoverySuccessTitle": "Congratulations your Catalyst \u2028Keychain is restored!", "recoverySuccessSubtitle": "You have successfully restored your Catalyst Keychain, and unlocked Catalyst Voices on this device.", "recoverySuccessGoToDashboard": "Jump into the Discovery space / Dashboard", - "recoverySuccessGoAccount": "Check my account" + "recoverySuccessGoAccount": "Check my account", + "recoveryExitConfirmDialogSubtitle": "12 word keychain restoration incomplete", + "recoveryExitConfirmDialogContent": "Please continue your Catalyst Keychain restoration, if you cancel all input will be lost.", + "recoveryExitConfirmDialogContinue": "Continue recovery process" } \ No newline at end of file diff --git a/catalyst_voices/packages/catalyst_voices_models/lib/src/registration/registration_step.dart b/catalyst_voices/packages/catalyst_voices_models/lib/src/registration/registration_step.dart index c9157a9e68..bcdec7bfa8 100644 --- a/catalyst_voices/packages/catalyst_voices_models/lib/src/registration/registration_step.dart +++ b/catalyst_voices/packages/catalyst_voices_models/lib/src/registration/registration_step.dart @@ -7,6 +7,10 @@ import 'package:equatable/equatable.dart'; sealed class RegistrationStep extends Equatable { const RegistrationStep(); + bool get isRegistrationFlow => false; + + bool get isRecoverFlow => false; + @override List get props => []; } @@ -26,6 +30,9 @@ final class SeedPhraseRecoverStep extends RegistrationStep { this.stage = RecoverSeedPhraseStage.seedPhraseInstructions, }); + @override + bool get isRecoverFlow => true; + @override List get props => [stage]; } @@ -37,12 +44,18 @@ final class CreateKeychainStep extends RegistrationStep { this.stage = CreateKeychainStage.splash, }); + @override + bool get isRegistrationFlow => true; + @override List get props => [stage]; } final class FinishAccountCreationStep extends RegistrationStep { const FinishAccountCreationStep(); + + @override + bool get isRegistrationFlow => true; } final class WalletLinkStep extends RegistrationStep { @@ -52,6 +65,9 @@ final class WalletLinkStep extends RegistrationStep { this.stage = WalletLinkStage.intro, }); + @override + bool get isRegistrationFlow => true; + @override List get props => [stage]; }