Skip to content

Commit

Permalink
feat(cat-voices): seed phrase error result and unlock password instru…
Browse files Browse the repository at this point in the history
…ctions (#920)

* refactor: rename panel to be consistent with others

* feat: allow wrong seed phrase order to go to results screen

* feat: better error seed phrase messages

* feat: unlock password instructions panel

* feat: unlock password stages picture

* refactor: scrollable panels content
  • Loading branch information
damian-molinski authored Oct 2, 2024
1 parent ffba899 commit 980067a
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import 'package:catalyst_voices/pages/registration/create_keychain/stage/check_seed_phrase_instructions_panel.dart';
import 'package:catalyst_voices/pages/registration/create_keychain/stage/instructions_panel.dart';
import 'package:catalyst_voices/pages/registration/create_keychain/stage/seed_phrase_check_instructions_panel.dart';
import 'package:catalyst_voices/pages/registration/create_keychain/stage/seed_phrase_check_panel.dart';
import 'package:catalyst_voices/pages/registration/create_keychain/stage/seed_phrase_check_result_panel.dart';
import 'package:catalyst_voices/pages/registration/create_keychain/stage/seed_phrase_panel.dart';
import 'package:catalyst_voices/pages/registration/create_keychain/stage/splash_panel.dart';
import 'package:catalyst_voices/pages/registration/create_keychain/stage/unlock_password_instructions_panel.dart';
import 'package:catalyst_voices/pages/registration/placeholder_panel.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
Expand All @@ -30,16 +31,16 @@ class CreateKeychainPanel extends StatelessWidget {
isNextEnabled: seedPhraseState.isStoredConfirmed,
),
CreateKeychainStage.checkSeedPhraseInstructions =>
const CheckSeedPhraseInstructionsPanel(),
const SeedPhraseCheckInstructionsPanel(),
CreateKeychainStage.checkSeedPhrase => SeedPhraseCheckPanel(
seedPhrase: seedPhraseState.seedPhrase,
),
CreateKeychainStage.checkSeedPhraseResult => SeedPhraseCheckResultPanel(
isCheckConfirmed: seedPhraseState.isCheckConfirmed,
),
CreateKeychainStage.unlockPasswordInstructions ||
CreateKeychainStage.unlockPasswordCreate =>
const PlaceholderPanel(),
CreateKeychainStage.unlockPasswordInstructions =>
const UnlockPasswordInstructionsPanel(),
CreateKeychainStage.unlockPasswordCreate => const PlaceholderPanel(),
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@ class InstructionsPanel extends StatelessWidget {

@override
Widget build(BuildContext context) {
final l10n = context.l10n;

return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 24),
RegistrationStageMessage(
title: context.l10n.accountInstructionsTitle,
subtitle: context.l10n.accountInstructionsMessage,
Expanded(
child: SingleChildScrollView(
child: RegistrationStageMessage(
title: l10n.accountInstructionsTitle,
subtitle: l10n.accountInstructionsMessage,
),
),
),
const Spacer(),
const SizedBox(height: 10),
const RegistrationBackNextNavigation(),
],
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:catalyst_voices/pages/registration/registration_stage_message.dart';
import 'package:catalyst_voices/pages/registration/registration_stage_navigation.dart';
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
import 'package:flutter/material.dart';

class SeedPhraseCheckInstructionsPanel extends StatelessWidget {
const SeedPhraseCheckInstructionsPanel({
super.key,
});

@override
Widget build(BuildContext context) {
final l10n = context.l10n;

return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 24),
Expanded(
child: SingleChildScrollView(
child: RegistrationStageMessage(
title: l10n.createKeychainSeedPhraseCheckInstructionsTitle,
subtitle: l10n.createKeychainSeedPhraseCheckInstructionsSubtitle,
),
),
),
const SizedBox(height: 10),
const RegistrationBackNextNavigation(),
],
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@ class _SeedPhraseCheckPanelState extends State<SeedPhraseCheckPanel> {
final _shuffledSeedPhraseWords = <String>[];
final _userWords = <String>[];

bool get _isStageValid {
if (_seedPhraseWords.isEmpty) {
return false;
}
bool get _hasSeedPhraseWords => _seedPhraseWords.isNotEmpty;

bool get _completedWordsSequence {
return _hasSeedPhraseWords && _userWords.length == _seedPhraseWords.length;
}

return listEquals(_seedPhraseWords, _userWords);
bool get _completedCorrectlyWordsSequence {
return _hasSeedPhraseWords && listEquals(_userWords, _seedPhraseWords);
}

@override
void initState() {
super.initState();

_updateSeedPhraseWords();
_updateUserWords(_seedPhraseWords);
_updateUserWords();
}

@override
Expand Down Expand Up @@ -69,7 +71,7 @@ class _SeedPhraseCheckPanelState extends State<SeedPhraseCheckPanel> {
),
),
const SizedBox(height: 10),
RegistrationBackNextNavigation(isNextEnabled: _isStageValid),
RegistrationBackNextNavigation(isNextEnabled: _completedWordsSequence),
],
);
}
Expand Down Expand Up @@ -109,9 +111,10 @@ class _SeedPhraseCheckPanelState extends State<SeedPhraseCheckPanel> {
..clear()
..addAll(words);

RegistrationCubit.of(context).setSeedPhraseCheckConfirmed(
isConfirmed: _isStageValid,
);
final isConfirmed = _completedCorrectlyWordsSequence;

RegistrationCubit.of(context)
.setSeedPhraseCheckConfirmed(isConfirmed: isConfirmed);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,27 @@ class SeedPhraseCheckResultPanel extends StatelessWidget {

@override
Widget build(BuildContext context) {
final l10n = context.l10n;

return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 24),
RegistrationStageMessage(
title: context.l10n.createKeychainSeedPhraseCheckSuccessTitle,
subtitle: context.l10n.createKeychainSeedPhraseCheckSuccessSubtitle,
),
const Spacer(),
NextStep(
context.l10n.createKeychainSeedPhraseCheckSuccessNextStep,
// TODO(damian-molinski): use correct strings when available.
Expanded(
child: SingleChildScrollView(
child: RegistrationStageMessage(
title: isCheckConfirmed
? l10n.createKeychainSeedPhraseCheckSuccessTitle
: 'Seed phrase words does not match!',
subtitle: isCheckConfirmed
? l10n.createKeychainSeedPhraseCheckSuccessSubtitle
: 'Go back ana make sure order is correct',
),
),
),
if (isCheckConfirmed)
NextStep(l10n.createKeychainSeedPhraseCheckSuccessNextStep),
const SizedBox(height: 10),
RegistrationBackNextNavigation(isNextEnabled: isCheckConfirmed),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,28 @@ import 'package:catalyst_voices/pages/registration/registration_stage_navigation
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
import 'package:flutter/material.dart';

class CheckSeedPhraseInstructionsPanel extends StatelessWidget {
const CheckSeedPhraseInstructionsPanel({
class UnlockPasswordInstructionsPanel extends StatelessWidget {
const UnlockPasswordInstructionsPanel({
super.key,
});

@override
Widget build(BuildContext context) {
final l10n = context.l10n;

return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 24),
RegistrationStageMessage(
title: context.l10n.createKeychainSeedPhraseCheckInstructionsTitle,
subtitle:
context.l10n.createKeychainSeedPhraseCheckInstructionsSubtitle,
Expanded(
child: SingleChildScrollView(
child: RegistrationStageMessage(
title: l10n.createKeychainUnlockPasswordInstructionsTitle,
subtitle: l10n.createKeychainUnlockPasswordInstructionsSubtitle,
),
),
),
const Spacer(),
const SizedBox(height: 10),
const RegistrationBackNextNavigation(),
],
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:catalyst_voices/pages/registration/pictures/task_picture.dart';
import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
import 'package:flutter/material.dart';

class PasswordPicture extends StatelessWidget {
const PasswordPicture({super.key});

@override
Widget build(BuildContext context) {
return TaskPicture(
child: TaskPictureIconBox(
type: TaskPictureType.error,
child: VoicesAssets.icons.lockClosed.buildIcon(size: 48),
),
);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:catalyst_voices/pages/registration/information_panel.dart';
import 'package:catalyst_voices/pages/registration/pictures/keychain_picture.dart';
import 'package:catalyst_voices/pages/registration/pictures/password_picture.dart';
import 'package:catalyst_voices/pages/registration/pictures/seed_phrase_picture.dart';
import 'package:catalyst_voices/pages/registration/pictures/task_picture.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
Expand Down Expand Up @@ -66,9 +67,9 @@ class RegistrationInfoPanel extends StatelessWidget {
subtitle: context.l10n.createKeychainSeedPhraseCheckSubtitle,
body: context.l10n.createKeychainSeedPhraseCheckBody,
),
CreateKeychainStage.checkSeedPhraseResult =>
CreateKeychainStage.checkSeedPhraseResult ||
CreateKeychainStage.unlockPasswordInstructions =>
_HeaderStrings(title: context.l10n.catalystKeychain),
CreateKeychainStage.unlockPasswordInstructions ||
CreateKeychainStage.unlockPasswordCreate =>
_HeaderStrings(title: 'TODO'),
};
Expand Down Expand Up @@ -138,7 +139,7 @@ class _RegistrationPicture extends StatelessWidget {
),
CreateKeychainStage.unlockPasswordInstructions ||
CreateKeychainStage.unlockPasswordCreate =>
const KeychainPicture(),
const PasswordPicture(),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,18 @@ abstract class VoicesLocalizations {
/// In en, this message translates to:
/// **'Now let’s set your Unlock password for this device!'**
String get createKeychainSeedPhraseCheckSuccessNextStep;

/// No description provided for @createKeychainUnlockPasswordInstructionsTitle.
///
/// In en, this message translates to:
/// **'Set your Catalyst unlock password 
for this device'**
String get createKeychainUnlockPasswordInstructionsTitle;

/// No description provided for @createKeychainUnlockPasswordInstructionsSubtitle.
///
/// In en, this message translates to:
/// **'With over 300 trillion possible combinations, your 12 word seed phrase is great for keeping your account safe. 

But it can be a bit tedious to enter every single time you want to use the app. 

In this next step, you\'ll set your Unlock Password for your current device. It\'s like a shortcut for proving ownership of your Keychain. 

Whenever you recover your account for the first time on a new device, you\'ll need to use your Catalyst Keychain to get started. Every time after that, you can use your Unlock Password to quickly regain access.'**
String get createKeychainUnlockPasswordInstructionsSubtitle;
}

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

@override
String get createKeychainSeedPhraseCheckSuccessNextStep => 'Now let’s set your Unlock password for this device!';

@override
String get createKeychainUnlockPasswordInstructionsTitle => 'Set your Catalyst unlock password 
for this device';

@override
String get createKeychainUnlockPasswordInstructionsSubtitle => 'With over 300 trillion possible combinations, your 12 word seed phrase is great for keeping your account safe. 

But it can be a bit tedious to enter every single time you want to use the app. 

In this next step, you\'ll set your Unlock Password for your current device. It\'s like a shortcut for proving ownership of your Keychain. 

Whenever you recover your account for the first time on a new device, you\'ll need to use your Catalyst Keychain to get started. Every time after that, you can use your Unlock Password to quickly regain access.';
}
Original file line number Diff line number Diff line change
Expand Up @@ -572,4 +572,10 @@ class VoicesLocalizationsEs extends VoicesLocalizations {

@override
String get createKeychainSeedPhraseCheckSuccessNextStep => 'Now let’s set your Unlock password for this device!';

@override
String get createKeychainUnlockPasswordInstructionsTitle => 'Set your Catalyst unlock password 
for this device';

@override
String get createKeychainUnlockPasswordInstructionsSubtitle => 'With over 300 trillion possible combinations, your 12 word seed phrase is great for keeping your account safe. 

But it can be a bit tedious to enter every single time you want to use the app. 

In this next step, you\'ll set your Unlock Password for your current device. It\'s like a shortcut for proving ownership of your Keychain. 

Whenever you recover your account for the first time on a new device, you\'ll need to use your Catalyst Keychain to get started. Every time after that, you can use your Unlock Password to quickly regain access.';
}
Original file line number Diff line number Diff line change
Expand Up @@ -649,5 +649,7 @@
"createKeychainSeedPhraseCheckSuccessTitle": "Nice job! You've successfully verified the seed phrase for your keychain.",
"createKeychainSeedPhraseCheckSuccessSubtitle": "Enter your seed phrase to recover your Catalyst Keychain on any device.\u2028\u2028It's kinda like your email and password all rolled into one, so keep it somewhere safe!\u2028\u2028In the next step we’ll add a password to your Catalyst Keychain, so you can lock/unlock access to Voices.",
"yourNextStep": "Your next step",
"createKeychainSeedPhraseCheckSuccessNextStep": "Now let’s set your Unlock password for this device!"
"createKeychainSeedPhraseCheckSuccessNextStep": "Now let’s set your Unlock password for this device!",
"createKeychainUnlockPasswordInstructionsTitle": "Set your Catalyst unlock password \u2028for this device",
"createKeychainUnlockPasswordInstructionsSubtitle": "With over 300 trillion possible combinations, your 12 word seed phrase is great for keeping your account safe. \u2028\u2028But it can be a bit tedious to enter every single time you want to use the app. \u2028\u2028In this next step, you'll set your Unlock Password for your current device. It's like a shortcut for proving ownership of your Keychain. \u2028\u2028Whenever you recover your account for the first time on a new device, you'll need to use your Catalyst Keychain to get started. Every time after that, you can use your Unlock Password to quickly regain access."
}

0 comments on commit 980067a

Please sign in to comment.