Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cat-voices): My account, modals #894

Merged
merged 17 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
0ca512f
feat: My account, modals
digitalheartxs Sep 26, 2024
4710263
feat: My account, modals, background and border
digitalheartxs Sep 26, 2024
522e3ab
feat: My account, modals, add seedphrase to project.dic
digitalheartxs Sep 26, 2024
61390e1
feat: My account, modals, keychain_deleted_dialog.dart
digitalheartxs Sep 26, 2024
866751a
feat: My account, modals, correct logic
digitalheartxs Sep 26, 2024
386ff77
feat: My account, modals, remove unnecessary comment
digitalheartxs Sep 27, 2024
c0c7f9b
feat: My account, modals, extract translations for delete_keychain_di…
digitalheartxs Sep 27, 2024
0229234
feat: My account, modals, extract translations for keychain_deleted_d…
digitalheartxs Sep 27, 2024
11276e6
feat: My account, modals, extract _onRemoveKeychainTap
digitalheartxs Sep 27, 2024
24905c0
feat: My account, modals, pass onDeleteKeychain callback
digitalheartxs Sep 27, 2024
9e2814d
Merge remote-tracking branch 'refs/remotes/origin/main' into feat/my_…
digitalheartxs Sep 27, 2024
921a8bc
feat: My account, modals, merge changes
digitalheartxs Sep 27, 2024
50974e4
feat: My account, modals, refactor base dialogs
digitalheartxs Sep 27, 2024
dfe1786
feat: My account, modals, change callback name
digitalheartxs Sep 27, 2024
5899198
Merge branch 'main' into feat/my_account_822_modals
stevenj Sep 28, 2024
e3ccff2
feat: My account, modals, return value from dialog instead of passing…
digitalheartxs Sep 30, 2024
b3c1848
Merge remote-tracking branch 'refs/remotes/origin/main' into feat/my_…
digitalheartxs Sep 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .config/dictionaries/project.dic
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ Scripthash
ScyllaDB
seckey
Seedable
seedphrase
sendfile
servernum
serviceworker
Expand Down
23 changes: 22 additions & 1 deletion catalyst_voices/lib/pages/account/account_page.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import 'package:catalyst_voices/common/ext/account_role_ext.dart';
import 'package:catalyst_voices/pages/account/delete_keychain_dialog.dart';
import 'package:catalyst_voices/pages/account/keychain_deleted_dialog.dart';
import 'package:catalyst_voices/widgets/buttons/voices_icon_button.dart';
import 'package:catalyst_voices/widgets/buttons/voices_text_button.dart';
import 'package:catalyst_voices/widgets/modals/voices_dialog.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';
Expand Down Expand Up @@ -35,7 +38,25 @@ final class AccountPage extends StatelessWidget {
AccountRole.drep,
],
defaultRole: AccountRole.voter,
onRemoveKeychain: () => debugPrint('Keychain removed'),
onRemoveKeychain: () async {
await VoicesDialog.show<void>(
context: context,
builder: (context) {
return DeleteKeychainDialog(
onRemoveKeychainConfirmed: () async {
// TODO(Jakub): remove keychain
Navigator.of(context).pop();
await VoicesDialog.show<void>(
digitalheartxs marked this conversation as resolved.
Show resolved Hide resolved
context: context,
builder: (context) {
return const KeychainDeletedDialog();
},
);
},
);
},
);
},
),
],
),
Expand Down
148 changes: 148 additions & 0 deletions catalyst_voices/lib/pages/account/delete_keychain_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
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_desktop_dialog.dart';
import 'package:catalyst_voices/widgets/text_field/voices_text_field.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 DeleteKeychainDialog extends StatefulWidget {
final VoidCallback? onRemoveKeychainConfirmed;

const DeleteKeychainDialog({
super.key,
this.onRemoveKeychainConfirmed,
});

@override
State<DeleteKeychainDialog> createState() => _DeleteKeychainDialogState();
}

class _DeleteKeychainDialogState extends State<DeleteKeychainDialog> {
final _textEditingController = TextEditingController();
String? _errorText;

@override
void initState() {
super.initState();
_textEditingController.addListener(() {
setState(() {
_errorText = null;
});
});
}

@override
void dispose() {
_textEditingController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return VoicesSinglePaneDialog(
backgroundColor: Theme.of(context).colors.iconsBackground,
showBorder: true,
constraints: const BoxConstraints(maxHeight: 500, maxWidth: 900),
child: SizedBox(
width: double.infinity,
child: SingleChildScrollView(
child: Column(
children: [
const SizedBox(height: 24),
Text(
context.l10n.deleteKeychainDialogTitle,
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 48),
Text(
context.l10n.deleteKeychainDialogSubtitle,
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.center,
),
const SizedBox(height: 32),
Wrap(
children: [
VoicesAssets.icons.exclamation.buildIcon(
color: Theme.of(context).colors.iconsError,
),
Padding(
padding: const EdgeInsets.only(top: 2, left: 8),
child: Text(
context.l10n.deleteKeychainDialogWarning,
style: Theme.of(context).textTheme.titleSmall,
),
),
],
),
const SizedBox(height: 8),
Text(
context.l10n.deleteKeychainDialogWarningInfo,
style: Theme.of(context).textTheme.bodyMedium,
textAlign: TextAlign.center,
),
const SizedBox(height: 48),
Text(
context.l10n.deleteKeychainDialogTypingInfo,
style: Theme.of(context).textTheme.titleSmall,
),
const SizedBox(height: 24),
Wrap(
direction: Axis.vertical,
children: [
Text(
context.l10n.deleteKeychainDialogInputLabel,
style: Theme.of(context).textTheme.titleSmall,
),
const SizedBox(height: 2),
SizedBox(
width: 300,
child: VoicesTextField(
controller: _textEditingController,
decoration: VoicesTextFieldDecoration(
errorText: _errorText,
errorMaxLines: 2,
filled: true,
fillColor: Theme.of(context)
.colors
.elevationsOnSurfaceNeutralLv1White,
),
),
),
],
),
const SizedBox(height: 24),
Wrap(
children: [
VoicesFilledButton(
backgroundColor: Theme.of(context).colors.iconsError,
onTap: () async => _onRemoveKeychainTap(),
child: Text(context.l10n.delete),
),
const SizedBox(width: 8),
VoicesTextButton.custom(
color: Theme.of(context).colors.iconsError,
onTap: () => Navigator.of(context).pop(),
child: Text(context.l10n.cancelButtonText),
),
],
),
],
),
),
),
);
}

Future<void> _onRemoveKeychainTap() async {
if (_textEditingController.text ==
context.l10n.deleteKeychainDialogRemovingPhrase) {
widget.onRemoveKeychainConfirmed?.call();
} else {
setState(() {
_errorText = context.l10n.deleteKeychainDialogErrorText;
});
}
}
}
49 changes: 49 additions & 0 deletions catalyst_voices/lib/pages/account/keychain_deleted_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import 'package:catalyst_voices/widgets/buttons/voices_filled_button.dart';
import 'package:catalyst_voices/widgets/modals/voices_desktop_dialog.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 KeychainDeletedDialog extends StatelessWidget {
const KeychainDeletedDialog({super.key});

@override
Widget build(BuildContext context) {
return VoicesSinglePaneDialog(
backgroundColor: Theme.of(context).colors.iconsBackground,
showBorder: true,
constraints: const BoxConstraints(maxHeight: 260, maxWidth: 900),
child: SizedBox(
width: double.infinity,
child: SingleChildScrollView(
child: Column(
children: [
const SizedBox(height: 24),
Text(
context.l10n.keychainDeletedDialogTitle,
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 48),
Text(
context.l10n.keychainDeletedDialogSubtitle,
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.center,
),
const SizedBox(height: 32),
Text(
context.l10n.keychainDeletedDialogInfo,
style: Theme.of(context).textTheme.bodyMedium,
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
VoicesFilledButton(
onTap: () => Navigator.of(context).pop(),
child: Text(context.l10n.close),
),
],
),
),
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class _RegistrationDialog extends StatelessWidget {

@override
Widget build(BuildContext context) {
return VoicesDesktopPanelsDialog(
return VoicesTwoPaneDialog(
left: RegistrationInfoPanel(
state: state,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class VoicesFilledButton extends StatelessWidget {
/// The widget to be displayed after the button's main content.
final Widget? trailing;

/// The optional button's background color.
final Color? backgroundColor;

/// The main content of the button.
final Widget child;

Expand All @@ -24,12 +27,16 @@ class VoicesFilledButton extends StatelessWidget {
this.onTap,
this.leading,
this.trailing,
this.backgroundColor,
required this.child,
});

@override
Widget build(BuildContext context) {
return FilledButton(
style: FilledButton.styleFrom(
backgroundColor: backgroundColor,
),
onPressed: onTap,
child: VoicesButtonAffixDecoration(
leading: leading,
Expand Down
68 changes: 57 additions & 11 deletions catalyst_voices/lib/widgets/modals/voices_desktop_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,35 @@ import 'package:catalyst_voices/widgets/buttons/voices_buttons.dart';
import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
import 'package:flutter/material.dart';

class VoicesDesktopDialog extends StatelessWidget {
/// Commonly used structure for desktop dialogs.
///
/// Keep in mind that this dialog has fixed size of 900x600 and
/// is always adding close button in top right corner.
class VoicesSinglePaneDialog extends StatelessWidget {
final BoxConstraints constraints;
final Color? backgroundColor;
final bool showBorder;
final Widget child;

const VoicesDesktopDialog({
const VoicesSinglePaneDialog({
super.key,
this.constraints = const BoxConstraints(minWidth: 900, minHeight: 600),
this.backgroundColor,
this.showBorder = false,
required this.child,
});

@override
Widget build(BuildContext context) {
return Dialog(
alignment: Alignment.topCenter,
insetPadding: const EdgeInsets.symmetric(horizontal: 40, vertical: 90),
child: ConstrainedBox(
constraints: constraints,
child: child,
return _VoicesDesktopDialog(
backgroundColor: Theme.of(context).colors.iconsBackground,
showBorder: true,
constraints: constraints,
child: Stack(
children: [
child,
const _DialogCloseButton(),
],
),
);
}
Expand All @@ -29,11 +40,11 @@ class VoicesDesktopDialog extends StatelessWidget {
///
/// Keep in mind that this dialog has fixed size of 900x600 and
/// is always adding close button in top right corner.
class VoicesDesktopPanelsDialog extends StatelessWidget {
class VoicesTwoPaneDialog extends StatelessWidget {
final Widget left;
final Widget right;

const VoicesDesktopPanelsDialog({
const VoicesTwoPaneDialog({
super.key,
required this.left,
required this.right,
Expand All @@ -43,7 +54,7 @@ class VoicesDesktopPanelsDialog extends StatelessWidget {
Widget build(BuildContext context) {
final theme = Theme.of(context);

return VoicesDesktopDialog(
return _VoicesDesktopDialog(
constraints: const BoxConstraints.tightFor(width: 900, height: 600),
child: Stack(
children: [
Expand Down Expand Up @@ -74,6 +85,41 @@ class VoicesDesktopPanelsDialog extends StatelessWidget {
}
}

class _VoicesDesktopDialog extends StatelessWidget {
final BoxConstraints constraints;
final Color? backgroundColor;
final bool showBorder;
final Widget child;

const _VoicesDesktopDialog({
this.constraints = const BoxConstraints(minWidth: 900, minHeight: 600),
this.backgroundColor,
this.showBorder = false,
required this.child,
});

@override
Widget build(BuildContext context) {
return Dialog(
shape: showBorder
? RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
side: BorderSide(
color: Theme.of(context).colors.outlineBorderVariant!,
),
)
: Theme.of(context).dialogTheme.shape,
backgroundColor: backgroundColor,
alignment: Alignment.topCenter,
insetPadding: const EdgeInsets.symmetric(horizontal: 40, vertical: 90),
child: ConstrainedBox(
constraints: constraints,
child: child,
),
);
}
}

class _DialogCloseButton extends StatelessWidget {
const _DialogCloseButton();

Expand Down
Loading
Loading