recovery phrase view and mnemonic table view desktop ui layout

This commit is contained in:
julian 2022-09-18 12:26:21 -06:00
parent f63acf4fa7
commit 98252ac4fb
7 changed files with 297 additions and 188 deletions

View file

@ -1,3 +1,5 @@
import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'package:flutter/material.dart';
@ -8,6 +10,8 @@ import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart';
import 'package:stackwallet/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/desktop_home_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/exit_to_my_stack_button.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/utilities/assets.dart';
@ -17,6 +21,8 @@ import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
import 'package:tuple/tuple.dart';
class NewWalletRecoveryPhraseView extends ConsumerStatefulWidget {
@ -46,12 +52,14 @@ class _NewWalletRecoveryPhraseViewState
late Manager _manager;
late List<String> _mnemonic;
late ClipboardInterface _clipboardInterface;
late final bool isDesktop;
@override
void initState() {
_manager = widget.manager;
_mnemonic = widget.mnemonic;
_clipboardInterface = widget.clipboardInterface;
isDesktop = Platform.isMacOS || Platform.isWindows || Platform.isLinux;
super.initState();
}
@ -67,144 +75,228 @@ class _NewWalletRecoveryPhraseViewState
await _manager.exitCurrentWallet();
}
Future<void> _copy() async {
final words = await _manager.mnemonic;
await _clipboardInterface.setData(ClipboardData(text: words.join(" ")));
unawaited(showFloatingFlushBar(
type: FlushBarType.info,
message: "Copied to clipboard",
iconAsset: Assets.svg.copy,
context: context,
));
}
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
return WillPopScope(
onWillPop: onWillPop,
child: Scaffold(
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
await delete();
onWillPop: onWillPop,
child: MasterScaffold(
isDesktop: isDesktop,
appBar: isDesktop
? DesktopAppBar(
isCompactHeight: false,
leading: AppBarBackButton(
onPressed: () async {
await delete();
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(
NewWalletRecoveryPhraseWarningView.routeName,
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(
NewWalletRecoveryPhraseWarningView.routeName,
),
);
}
// Navigator.of(context).pop();
},
),
);
}
// Navigator.of(context).pop();
},
),
actions: [
Padding(
padding: const EdgeInsets.all(10),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
color: CFColors.almostWhite,
shadows: const [],
icon: SvgPicture.asset(
Assets.svg.copy,
width: 24,
height: 24,
trailing: ExitToMyStackButton(
onPressed: () async {
await delete();
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(DesktopHomeView.routeName),
);
}
},
),
onPressed: () async {
final words = await _manager.mnemonic;
await _clipboardInterface
.setData(ClipboardData(text: words.join(" ")));
showFloatingFlushBar(
type: FlushBarType.info,
message: "Copied to clipboard",
iconAsset: Assets.svg.copy,
context: context,
);
},
),
),
),
],
),
body: Container(
color: CFColors.almostWhite,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(
height: 4,
),
Text(
_manager.walletName,
textAlign: TextAlign.center,
style: STextStyles.label.copyWith(
fontSize: 12,
),
),
const SizedBox(
height: 4,
),
Text(
"Recovery Phrase",
textAlign: TextAlign.center,
style: STextStyles.pageTitleH1,
),
const SizedBox(
height: 16,
),
Container(
decoration: BoxDecoration(
color: CFColors.white,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius),
),
child: Padding(
padding: const EdgeInsets.all(12),
child: Text(
"Please write down your recovery phrase in the correct order and save it to keep your funds secure. You will also be asked to verify the words on the next screen.",
style: STextStyles.label.copyWith(
color: CFColors.stackAccent,
),
),
),
),
const SizedBox(
height: 8,
),
Expanded(
child: SingleChildScrollView(
child: MnemonicTable(
words: _mnemonic,
),
),
),
const SizedBox(
height: 16,
),
TextButton(
onPressed: () async {
final int next = Random().nextInt(_mnemonic.length);
ref
.read(verifyMnemonicWordIndexStateProvider.state)
.update((state) => next);
)
: AppBar(
leading: AppBarBackButton(
onPressed: () async {
await delete();
ref
.read(verifyMnemonicCorrectWordStateProvider.state)
.update((state) => _mnemonic[next]);
Navigator.of(context).pushNamed(
VerifyRecoveryPhraseView.routeName,
arguments: Tuple2(_manager, _mnemonic),
);
},
style: Theme.of(context).textButtonTheme.style?.copyWith(
backgroundColor: MaterialStateProperty.all<Color>(
CFColors.stackAccent,
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(
NewWalletRecoveryPhraseWarningView.routeName,
),
);
}
},
),
actions: [
Padding(
padding: const EdgeInsets.all(10),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
color: CFColors.almostWhite,
shadows: const [],
icon: SvgPicture.asset(
Assets.svg.copy,
width: 24,
height: 24,
),
onPressed: () async {
await _copy();
},
),
),
child: Text(
"I saved my recovery phrase",
style: STextStyles.button,
),
),
],
),
],
body: Container(
color: CFColors.background,
width: isDesktop ? 600 : null,
child: Padding(
padding: isDesktop
? const EdgeInsets.all(0)
: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (!isDesktop)
const SizedBox(
height: 4,
),
if (!isDesktop)
Text(
_manager.walletName,
textAlign: TextAlign.center,
style: STextStyles.label.copyWith(
fontSize: 12,
),
),
SizedBox(
height: isDesktop ? 24 : 4,
),
Text(
"Recovery Phrase",
textAlign: TextAlign.center,
style: isDesktop
? STextStyles.desktopH2
: STextStyles.pageTitleH1,
),
const SizedBox(
height: 16,
),
Container(
decoration: BoxDecoration(
color: isDesktop
? CFColors.background
: CFColors.popupBackground,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius),
),
child: Padding(
padding: isDesktop
? const EdgeInsets.all(0)
: const EdgeInsets.all(12),
child: Text(
"Please write down your recovery phrase in the correct order and save it to keep your funds secure. You will also be asked to verify the words on the next screen.",
textAlign: TextAlign.center,
style: isDesktop
? STextStyles.desktopSubtitleH2
: STextStyles.label.copyWith(
color: CFColors.stackAccent,
),
),
),
),
SizedBox(
height: isDesktop ? 21 : 8,
),
if (!isDesktop)
Expanded(
child: SingleChildScrollView(
child: MnemonicTable(
words: _mnemonic,
isDesktop: isDesktop,
),
),
),
if (isDesktop)
MnemonicTable(
words: _mnemonic,
isDesktop: isDesktop,
),
SizedBox(
height: isDesktop ? 24 : 16,
),
if (isDesktop)
SizedBox(
height: 70,
child: TextButton(
onPressed: () async {
await _copy();
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
Assets.svg.copy,
width: 20,
height: 20,
),
const SizedBox(
width: 10,
),
Text(
"Copy to clipboard",
style: STextStyles.desktopButtonSecondaryEnabled,
)
],
),
),
),
if (isDesktop)
const SizedBox(
height: 16,
),
ConstrainedBox(
constraints: BoxConstraints(
minHeight: isDesktop ? 70 : 0,
),
child: TextButton(
onPressed: () async {
final int next = Random().nextInt(_mnemonic.length);
ref
.read(verifyMnemonicWordIndexStateProvider.state)
.update((state) => next);
ref
.read(verifyMnemonicCorrectWordStateProvider.state)
.update((state) => _mnemonic[next]);
unawaited(Navigator.of(context).pushNamed(
VerifyRecoveryPhraseView.routeName,
arguments: Tuple2(_manager, _mnemonic),
));
},
style: CFColors.getPrimaryEnabledButtonColor(context),
child: Text(
"I saved my recovery phrase",
style: isDesktop
? STextStyles.desktopButtonEnabled
: STextStyles.button,
),
),
),
],
),
),
),
),
),
);
));
}
}

View file

@ -1,19 +1,20 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table_item.dart';
class MnemonicTable extends StatelessWidget {
const MnemonicTable({
Key? key,
required this.words,
required this.isDesktop,
}) : super(key: key);
final List<String> words;
static const wordsPerRow = 3;
final bool isDesktop;
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
final wordsPerRow = isDesktop ? 4 : 3;
final int rows = words.length ~/ wordsPerRow;
@ -26,51 +27,54 @@ class MnemonicTable extends StatelessWidget {
children: [
for (int i = 1; i <= rows; i++)
Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
padding: EdgeInsets.symmetric(vertical: isDesktop ? 8 : 5),
child: Row(
children: [
for (int j = 1; j <= wordsPerRow; j++) ...[
if (j > 1)
const SizedBox(
width: 6,
SizedBox(
width: isDesktop ? 10 : 6,
),
Expanded(
child: MnemonicTableItem(
number: ++index,
word: words[index - 1],
isDesktop: isDesktop,
),
),
],
],
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: Row(
children: [
for (int i = index; i < words.length; i++) ...[
if (i > index)
if (index != words.length)
Padding(
padding: EdgeInsets.symmetric(vertical: isDesktop ? 8 : 5),
child: Row(
children: [
for (int i = index; i < words.length; i++) ...[
if (i > index)
SizedBox(
width: isDesktop ? 10 : 6,
),
Expanded(
child: MnemonicTableItem(
number: i + 1,
word: words[i],
isDesktop: isDesktop,
),
),
],
for (int i = remainder; i < wordsPerRow; i++) ...[
const SizedBox(
width: 6,
),
Expanded(
child: MnemonicTableItem(
number: i + 1,
word: words[i],
Expanded(
child: Container(),
),
),
],
],
for (int i = remainder; i < wordsPerRow; i++) ...[
const SizedBox(
width: 6,
),
Expanded(
child: Container(),
),
],
],
),
),
),
],
);
}

View file

@ -1,49 +1,53 @@
import 'package:flutter/material.dart';
import 'package:stackwallet/utilities/cfcolors.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class MnemonicTableItem extends StatelessWidget {
const MnemonicTableItem({
Key? key,
required this.number,
required this.word,
required this.isDesktop,
}) : super(key: key);
final int number;
final String word;
final bool isDesktop;
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
return Container(
decoration: BoxDecoration(
color: CFColors.white,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
child: Padding(
padding: const EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
number.toString(),
style: STextStyles.baseXS.copyWith(
color: CFColors.gray3,
fontSize: 10,
),
),
const SizedBox(
width: 8,
),
Text(
word,
style: STextStyles.baseXS,
),
],
),
return RoundedWhiteContainer(
padding: isDesktop
? const EdgeInsets.symmetric(horizontal: 12, vertical: 9)
: const EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
number.toString(),
style: isDesktop
? STextStyles.desktopTextExtraSmall.copyWith(
color: CFColors.gray3,
)
: STextStyles.baseXS.copyWith(
color: CFColors.gray3,
fontSize: 10,
),
),
const SizedBox(
width: 8,
),
Text(
word,
style: isDesktop
? STextStyles.desktopTextExtraSmall.copyWith(
color: CFColors.textDark,
)
: STextStyles.baseXS,
),
],
),
);
}

View file

@ -93,6 +93,7 @@ class RecoverPhraseView extends StatelessWidget {
child: SingleChildScrollView(
child: MnemonicTable(
words: mnemonic,
isDesktop: false,
),
),
),

View file

@ -123,6 +123,7 @@ class WalletBackupView extends ConsumerWidget {
child: SingleChildScrollView(
child: MnemonicTable(
words: mnemonic,
isDesktop: false,
),
),
),

View file

@ -140,6 +140,7 @@ class _DeleteWalletRecoveryPhraseViewState
child: SingleChildScrollView(
child: MnemonicTable(
words: _mnemonic,
isDesktop: false,
),
),
),

View file

@ -4,7 +4,12 @@ import 'package:stackwallet/utilities/cfcolors.dart';
import 'package:stackwallet/utilities/text_styles.dart';
class ExitToMyStackButton extends StatelessWidget {
const ExitToMyStackButton({Key? key}) : super(key: key);
const ExitToMyStackButton({
Key? key,
this.onPressed,
}) : super(key: key);
final VoidCallback? onPressed;
@override
Widget build(BuildContext context) {
@ -16,11 +21,12 @@ class ExitToMyStackButton extends StatelessWidget {
height: 56,
child: TextButton(
style: CFColors.getSmallSecondaryEnabledButtonColor(context),
onPressed: () {
Navigator.of(context).popUntil(
ModalRoute.withName(DesktopHomeView.routeName),
);
},
onPressed: onPressed ??
() {
Navigator.of(context).popUntil(
ModalRoute.withName(DesktopHomeView.routeName),
);
},
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30,