Skip to content

Commit

Permalink
feat(cat-voices): registration confirm exit dialog (#949)
Browse files Browse the repository at this point in the history
* feat: confirm exit dialog

* chore: make builder method private
  • Loading branch information
damian-molinski authored Oct 4, 2024
1 parent 980e714 commit b611980
Show file tree
Hide file tree
Showing 9 changed files with 285 additions and 26 deletions.
33 changes: 30 additions & 3 deletions catalyst_voices/lib/pages/registration/registration_dialog.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import 'dart:async';

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/widgets/widgets.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
Expand All @@ -22,10 +25,34 @@ class RegistrationDialog extends StatelessWidget {
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => Dependencies.instance.get<RegistrationCubit>(),
child: const VoicesTwoPaneDialog(
left: RegistrationInfoPanel(),
right: RegistrationDetailsPanel(),
child: PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) {
unawaited(_confirmedExit(context, didPop: didPop));
},
child: const VoicesTwoPaneDialog(
left: RegistrationInfoPanel(),
right: RegistrationDetailsPanel(),
),
),
);
}

Future<void> _confirmedExit(
BuildContext context, {
required bool didPop,
}) async {
if (didPop) {
return;
}

final confirmed = await VoicesQuestionDialog.show(
context,
builder: (_) => const RegistrationExitConfirmDialog(),
);

if (context.mounted && confirmed) {
Navigator.of(context).pop();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
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,
);
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:catalyst_voices/widgets/buttons/voices_buttons.dart';
import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -144,7 +146,7 @@ class _DialogCloseButton extends StatelessWidget {
child: XButton(
onTap: () {
onCancel?.call();
Navigator.of(context).pop();
unawaited(Navigator.of(context).maybePop());
},
),
),
Expand Down
109 changes: 109 additions & 0 deletions catalyst_voices/lib/widgets/modals/voices_question_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import 'package:catalyst_voices/widgets/buttons/voices_filled_button.dart';
import 'package:catalyst_voices/widgets/buttons/voices_text_button.dart';
import 'package:catalyst_voices/widgets/modals/voices_alert_dialog.dart';
import 'package:catalyst_voices/widgets/modals/voices_dialog.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';

enum VoicesQuestionActionType { filled, text }

final class VoicesQuestionActionItem extends Equatable {
final String name;
final bool isPositive;
final VoicesQuestionActionType type;

const VoicesQuestionActionItem.positive(
this.name, {
this.type = VoicesQuestionActionType.filled,
}) : isPositive = true;

const VoicesQuestionActionItem.negative(
this.name, {
this.type = VoicesQuestionActionType.text,
}) : isPositive = false;

@override
List<Object?> get props => [
name,
isPositive,
type,
];
}

/// Simple dialog when working with yes/no type of dialogs.
///
/// example:
/// ```dart
/// final confirmed = await VoicesQuestionDialog.show(
/// context,
/// builder: (_) => const RegistrationExitConfirmDialog(),
/// );
///```
class VoicesQuestionDialog extends StatelessWidget {
/// [VoicesAlertDialog.title].
final Widget title;

/// [VoicesAlertDialog.icon].
final Widget? icon;

/// [VoicesAlertDialog.subtitle].
final Widget? subtitle;

/// [VoicesAlertDialog.content].
final Widget? content;

/// List of yes/no actions, usually only 2 make sense.
/// See [VoicesQuestionActionItem] for config details.
final List<VoicesQuestionActionItem> actions;

static Future<bool> show(
BuildContext context, {
required WidgetBuilder builder,
bool fallback = false,
}) async {
final result = await VoicesDialog.show<bool>(
context: context,
builder: builder,
);

return result ?? fallback;
}

const VoicesQuestionDialog({
super.key,
required this.title,
this.icon,
this.subtitle,
this.content,
required this.actions,
});

@override
Widget build(BuildContext context) {
return VoicesAlertDialog(
title: title,
icon: icon,
subtitle: subtitle,
content: content,
buttons: actions.map((e) => _buildItem(context, item: e)).toList(),
);
}

Widget _buildItem(
BuildContext context, {
required VoicesQuestionActionItem item,
}) {
switch (item.type) {
case VoicesQuestionActionType.filled:
return VoicesFilledButton(
onTap: () => Navigator.of(context).pop(item.isPositive),
child: Text(item.name),
);
case VoicesQuestionActionType.text:
return VoicesTextButton(
onTap: () => Navigator.of(context).pop(item.isPositive),
child: Text(item.name),
);
}
}
}
1 change: 1 addition & 0 deletions catalyst_voices/lib/widgets/widgets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export 'modals/voices_alert_dialog.dart';
export 'modals/voices_desktop_dialog.dart';
export 'modals/voices_dialog.dart';
export 'modals/voices_info_dialog.dart';
export 'modals/voices_question_dialog.dart';
export 'modals/voices_upload_file_dialog.dart';
export 'scrollbar/voices_scrollbar.dart';
export 'seed_phrase/seed_phrases_completer.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,36 @@ abstract class VoicesLocalizations {
/// In en, this message translates to:
/// **'Passwords do not match, please correct'**
String get passwordDoNotMatch;

/// No description provided for @warning.
///
/// In en, this message translates to:
/// **'Warning'**
String get warning;

/// No description provided for @registrationExitConfirmDialogSubtitle.
///
/// In en, this message translates to:
/// **'Account creation incomplete!'**
String get registrationExitConfirmDialogSubtitle;

/// No description provided for @registrationExitConfirmDialogContent.
///
/// In en, this message translates to:
/// **'If attempt to leave without creating your keychain - account creation will be incomplete. 

You are not able to login without 
completing your keychain.'**
String get registrationExitConfirmDialogContent;

/// No description provided for @registrationExitConfirmDialogContinue.
///
/// In en, this message translates to:
/// **'Continue keychain creation'**
String get registrationExitConfirmDialogContinue;

/// No description provided for @registrationExitConfirmDialogCancel.
///
/// In en, this message translates to:
/// **'Cancel anyway'**
String get registrationExitConfirmDialogCancel;
}

class _VoicesLocalizationsDelegate extends LocalizationsDelegate<VoicesLocalizations> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -727,4 +727,19 @@ class VoicesLocalizationsEn extends VoicesLocalizations {

@override
String get passwordDoNotMatch => 'Passwords do not match, please correct';

@override
String get warning => 'Warning';

@override
String get registrationExitConfirmDialogSubtitle => 'Account creation incomplete!';

@override
String get registrationExitConfirmDialogContent => 'If attempt to leave without creating your keychain - account creation will be incomplete. 

You are not able to login without 
completing your keychain.';

@override
String get registrationExitConfirmDialogContinue => 'Continue keychain creation';

@override
String get registrationExitConfirmDialogCancel => 'Cancel anyway';
}
Original file line number Diff line number Diff line change
Expand Up @@ -727,4 +727,19 @@ class VoicesLocalizationsEs extends VoicesLocalizations {

@override
String get passwordDoNotMatch => 'Passwords do not match, please correct';

@override
String get warning => 'Warning';

@override
String get registrationExitConfirmDialogSubtitle => 'Account creation incomplete!';

@override
String get registrationExitConfirmDialogContent => 'If attempt to leave without creating your keychain - account creation will be incomplete. 

You are not able to login without 
completing your keychain.';

@override
String get registrationExitConfirmDialogContinue => 'Continue keychain creation';

@override
String get registrationExitConfirmDialogCancel => 'Cancel anyway';
}
Original file line number Diff line number Diff line change
Expand Up @@ -708,28 +708,28 @@
"yes": "Yes",
"no": "No",
"total": "Total",
"file": "file",
"key": "key",
"upload": "Upload",
"browse": "browse",
"uploadDropInfo": "Drop your {itemNameToUpload} here or ",
"@uploadDropInfo": {
"description": "An info on upload dialog",
"placeholders": {
"itemNameToUpload": {
"type": "String"
}
"file": "file",
"key": "key",
"upload": "Upload",
"browse": "browse",
"uploadDropInfo": "Drop your {itemNameToUpload} here or ",
"@uploadDropInfo": {
"description": "An info on upload dialog",
"placeholders": {
"itemNameToUpload": {
"type": "String"
}
},
"uploadProgressInfo": "Upload in progress",
"uploadKeychainTitle": "Upload Catalyst Keychain",
"@uploadKeychainTitle": {
"description": "A title on keychain upload dialog"
},
"uploadKeychainInfo": "Make sure it's a correct Catalyst keychain file.",
"@uploadKeychainInfo": {
"description": "An info on keychain upload dialog"
},
}
},
"uploadProgressInfo": "Upload in progress",
"uploadKeychainTitle": "Upload Catalyst Keychain",
"@uploadKeychainTitle": {
"description": "A title on keychain upload dialog"
},
"uploadKeychainInfo": "Make sure it's a correct Catalyst keychain file.",
"@uploadKeychainInfo": {
"description": "An info on keychain upload dialog"
},
"themeLight": "Light",
"@themeLight": {
"description": "Refers to a light theme mode."
Expand Down Expand Up @@ -790,5 +790,10 @@
"passwordDoNotMatch": "Passwords do not match, please correct",
"@passwordDoNotMatch": {
"description": "When user confirms password but it does not match original one."
}
},
"warning": "Warning",
"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"
}

0 comments on commit b611980

Please sign in to comment.