mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 11:59:30 +00:00
recovery phrase view and mnemonic table view desktop ui layout
This commit is contained in:
parent
f63acf4fa7
commit
98252ac4fb
7 changed files with 297 additions and 188 deletions
|
@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ class RecoverPhraseView extends StatelessWidget {
|
|||
child: SingleChildScrollView(
|
||||
child: MnemonicTable(
|
||||
words: mnemonic,
|
||||
isDesktop: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -123,6 +123,7 @@ class WalletBackupView extends ConsumerWidget {
|
|||
child: SingleChildScrollView(
|
||||
child: MnemonicTable(
|
||||
words: mnemonic,
|
||||
isDesktop: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -140,6 +140,7 @@ class _DeleteWalletRecoveryPhraseViewState
|
|||
child: SingleChildScrollView(
|
||||
child: MnemonicTable(
|
||||
words: _mnemonic,
|
||||
isDesktop: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue