Skip to content

Commit

Permalink
feat: re add puzzle quiz screen flow (#1430)
Browse files Browse the repository at this point in the history
Co-authored-by: ookami-kb <ookami.kb@gmail.com>
  • Loading branch information
justinenerio and ookami-kb authored May 8, 2024
1 parent abf4eee commit 126f7e8
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:flutter/material.dart';

import '../../../utils/routing.dart';
import 'puzzle_input_screen.dart';
import 'puzzle_success_screen.dart';
import 'puzzle_view_phrase_screen.dart';

extension PuzzleFlow on BuildContext {
void launchPuzzleFlow() {
final navigator = Navigator.of(this, rootNavigator: true);

MaterialPageRoute<void> successRoute() => MaterialPageRoute(
builder: (context) => PuzzleSuccessScreen(
onDone: () => context.openFirstScreen(),
),
);

MaterialPageRoute<void> inputPhraseRoute(String phrase) =>
MaterialPageRoute(
builder: (context) => PuzzleInputScreen(
correctPhrase: phrase,
onConfirmed: () => navigator.pushAndRemoveUntil(
successRoute(),
(route) => route.isFirst,
),
),
);

navigator.push<void>(
MaterialPageRoute(
builder: (context) => PuzzleViewPhraseScreen(
onConfirmed: (phrase) => navigator.push(inputPhraseRoute(phrase)),
),
),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import 'package:flutter/material.dart';

import '../../../../l10n/l10n.dart';
import '../../../../ui/app_bar.dart';
import '../../../../ui/onboarding_screen.dart';
import '../../../../ui/recovery_phrase_text_view.dart';
import '../../../../ui/theme.dart';
import '../widgets/grid_phrase.dart';

class PuzzleInputScreen extends StatefulWidget {
const PuzzleInputScreen({
super.key,
required this.correctPhrase,
required this.onConfirmed,
});

final String correctPhrase;
final VoidCallback onConfirmed;

@override
State<PuzzleInputScreen> createState() => _PuzzleInputScreenState();
}

class _PuzzleInputScreenState extends State<PuzzleInputScreen> {
String _currentPhrase = '';

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

return CpTheme.black(
child: Scaffold(
body: OnboardingScreen(
footer: OnboardingFooterButton(
text: context.l10n.next,
onPressed:
_currentPhrase == correctPhrase ? widget.onConfirmed : null,
),
children: [
const CpAppBar(),
const OnboardingLogo(),
OnboardingDescription(text: context.l10n.completeThePuzzle),
OnboardingPadding(
child: RecoveryPhraseTextView(
phrase: _currentPhrase,
hasCopyButton: false,
),
),
const SizedBox(height: 32),
SizedBox(
height: 200,
child: OnboardingPadding(
child: GridPhrase(
correctPhrase: widget.correctPhrase,
callback: (phrase) => setState(() => _currentPhrase = phrase),
),
),
),
],
),
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,20 @@ import '../../../utils/routing.dart';
import '../services/puzzle_reminder_bloc.dart';
import '../widgets/puzzle_screen.dart';

class PuzzleReminderSetupScreen extends StatefulWidget {
const PuzzleReminderSetupScreen({super.key});
class PuzzlePostponeScreen extends StatefulWidget {
const PuzzlePostponeScreen({super.key});

static void push(BuildContext context) => Navigator.of(context).push<void>(
MaterialPageRoute(
builder: (context) => const PuzzleReminderSetupScreen(),
builder: (context) => const PuzzlePostponeScreen(),
),
);

@override
State<PuzzleReminderSetupScreen> createState() =>
_PuzzleReminderSetupScreenState();
State<PuzzlePostponeScreen> createState() => _PuzzlePostponeScreenState();
}

class _PuzzleReminderSetupScreenState extends State<PuzzleReminderSetupScreen> {
class _PuzzlePostponeScreenState extends State<PuzzlePostponeScreen> {
bool _checked = false;
Duration _duration = const Duration(days: 1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ import '../../../l10n/l10n.dart';
import '../../../ui/button.dart';
import '../../../ui/message_info_widget.dart';
import '../widgets/puzzle_screen.dart';
import 'puzzle_reminder_setup_screen.dart';
import 'puzzle_flow.dart';
import 'puzzle_postpone_screen.dart';

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

static void push(BuildContext context) => Navigator.of(context).push<void>(
MaterialPageRoute(
builder: (context) => const PuzzleReminderMessageScreen(),
builder: (context) => const PuzzleReminderScreen(),
),
);

void _handleRemindPressed(BuildContext context) =>
PuzzleReminderSetupScreen.push(context);
PuzzlePostponeScreen.push(context);

@override
Widget build(BuildContext context) => PuzzleScreen(
Expand All @@ -42,9 +43,7 @@ class PuzzleReminderMessageScreen extends StatelessWidget {
text: context.l10n.protectWallet,
size: CpButtonSize.big,
minWidth: 300,
onPressed: () {
// TODO(KB): redirect to proper screen
},
onPressed: () => context.launchPuzzleFlow(),
),
const SizedBox(height: 8),
TextButton(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import 'package:flutter/material.dart';

import '../../../../../../gen/assets.gen.dart';
import '../../../../../../l10n/l10n.dart';
import '../../../../../../ui/button.dart';
import '../../../../../../ui/content_padding.dart';
import '../../../../../../ui/theme.dart';
import '../../../../ui/rounded_rectangle.dart';
import '../../../di.dart';
import '../services/puzzle_reminder_bloc.dart';

class PuzzleSuccessScreen extends StatelessWidget {
const PuzzleSuccessScreen({super.key, required this.onDone});

final VoidCallback onDone;

@override
Widget build(BuildContext context) => CpTheme.black(
child: Scaffold(
body: CpContentPadding(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 110),
Assets.icons.successCheck.svg(width: 72, height: 72),
const SizedBox(height: 42),
const CpRoundedRectangle(
padding: EdgeInsets.all(32),
backgroundColor: Colors.black,
child: _SuccessMessage(),
),
const SizedBox(height: 80),
CpButton(
size: CpButtonSize.big,
width: double.infinity,
text: context.l10n.ok,
onPressed: () {
sl<PuzzleReminderBloc>()
.add(const PuzzleReminderEvent.solved());
onDone();
},
),
],
),
),
),
);
}

class _SuccessMessage extends StatelessWidget {
const _SuccessMessage();

@override
Widget build(BuildContext context) => Text(
context.l10n.backupPhrase_lblSuccessMessage,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 19, fontWeight: FontWeight.w400),
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import 'package:flutter/material.dart';

import '../../../../di.dart';
import '../../../../l10n/l10n.dart';
import '../../../../ui/app_bar.dart';
import '../../../../ui/onboarding_screen.dart';
import '../../../../ui/recovery_phrase_text_view.dart';
import '../../../../ui/theme.dart';
import '../../accounts/data/account_repository.dart';

class PuzzleViewPhraseScreen extends StatefulWidget {
const PuzzleViewPhraseScreen({
super.key,
required this.onConfirmed,
});

final ValueSetter<String> onConfirmed;

@override
State<PuzzleViewPhraseScreen> createState() => _PuzzleViewPhraseScreenState();
}

class _PuzzleViewPhraseScreenState extends State<PuzzleViewPhraseScreen> {
String _phrase = '';

@override
void initState() {
super.initState();
sl<AccountRepository>().loadMnemonic().then((String? phrase) {
if (phrase != null) {
setState(() => _phrase = phrase);
}
});
}

@override
Widget build(BuildContext context) => CpTheme.black(
child: Scaffold(
body: OnboardingScreen(
footer: OnboardingFooterButton(
text: context.l10n.next,
onPressed: () => widget.onConfirmed(_phrase),
),
children: [
const CpAppBar(),
const OnboardingLogo(),
OnboardingTitle(text: context.l10n.yourRecoveryPhrase),
OnboardingDescription(text: context.l10n.yourRecoveryPhraseSub),
OnboardingPadding(
child: RecoveryPhraseTextView(phrase: _phrase),
),
],
),
),
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';

import '../../../di.dart';
import '../../accounts/models/account.dart';
import '../screens/puzzle_reminder_message_screen.dart';
import '../screens/puzzle_reminder_screen.dart';
import '../services/puzzle_reminder_bloc.dart';

class BackupPhraseModule extends StatefulWidget {
Expand All @@ -27,7 +27,7 @@ class _BackupPhraseModuleState extends State<BackupPhraseModule> {
sl<PuzzleReminderBloc>().add(event);
}

void _showPuzzleReminderDialog() => PuzzleReminderMessageScreen.push(context);
void _showPuzzleReminderDialog() => PuzzleReminderScreen.push(context);

@override
Widget build(BuildContext context) =>
Expand Down
4 changes: 4 additions & 0 deletions packages/espressocash_app/lib/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
"@appLock_lblAutoLock": {},
"appLock_lblAutoLockDescription": "Require passcode to access the app",
"@appLock_lblAutoLockDescription": {},
"backupPhrase_lblSuccessMessage": "You’ve successfully confirmed your secret recovery phrase.\n\nMake sure to keep it private and store it in a safe and secure place.",
"@backupPhrase_lblSuccessMessage": {},
"balances_lblConnectionError": "Cannot connect to the network!",
"@balances_lblConnectionError": {},
"carousel1Subtitle": "Instant & Low Fee Money Transfers to 200+ Countries & Territories.",
Expand All @@ -42,6 +44,8 @@
"@close": {},
"comingSoon": "Coming soon!",
"@comingSoon": {},
"completeThePuzzle": "Did you write it down your recovery phrase correctly? Test it here:",
"@completeThePuzzle": {},
"contactUs": "Contact Us",
"@contactUs": {},
"copiedFid": "Copied FID: {fid}",
Expand Down

0 comments on commit 126f7e8

Please sign in to comment.