mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-29 21:55:58 +00:00
recovery warning desktop ui
This commit is contained in:
parent
3047a90b41
commit
f63acf4fa7
5 changed files with 228 additions and 153 deletions
|
@ -1,6 +1,10 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/new_wallet_recovery_phrase_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/coin_service.dart';
|
||||
import 'package:stackwallet/services/coins/manager.dart';
|
||||
|
@ -12,7 +16,10 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
|||
import 'package:stackwallet/utilities/logger.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:stackwallet/widgets/loading_indicator.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class NewWalletRecoveryPhraseWarningView extends StatefulWidget {
|
||||
|
@ -36,11 +43,13 @@ class _NewWalletRecoveryPhraseWarningViewState
|
|||
extends State<NewWalletRecoveryPhraseWarningView> {
|
||||
late final Coin coin;
|
||||
late final String walletName;
|
||||
late final bool isDesktop;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
coin = widget.coin;
|
||||
walletName = widget.walletName;
|
||||
isDesktop = Platform.isMacOS || Platform.isWindows || Platform.isLinux;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
@ -52,24 +61,28 @@ class _NewWalletRecoveryPhraseWarningViewState
|
|||
? Constants.seedPhraseWordCountMonero
|
||||
: Constants.seedPhraseWordCountBip39;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: AppBarBackButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
),
|
||||
body: Container(
|
||||
color: CFColors.almostWhite,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
return MasterScaffold(
|
||||
isDesktop: isDesktop,
|
||||
appBar: isDesktop
|
||||
? const DesktopAppBar(
|
||||
isCompactHeight: false,
|
||||
leading: AppBarBackButton(),
|
||||
trailing: ExitToMyStackButton(),
|
||||
)
|
||||
: AppBar(
|
||||
leading: const AppBarBackButton(),
|
||||
),
|
||||
body: Padding(
|
||||
padding: EdgeInsets.all(isDesktop ? 0 : 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: isDesktop
|
||||
? CrossAxisAlignment.center
|
||||
: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
if (!isDesktop)
|
||||
Text(
|
||||
walletName,
|
||||
textAlign: TextAlign.center,
|
||||
|
@ -77,35 +90,42 @@ class _NewWalletRecoveryPhraseWarningViewState
|
|||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
"Recovery Phrase",
|
||||
textAlign: TextAlign.center,
|
||||
style:
|
||||
isDesktop ? STextStyles.desktopH2 : STextStyles.pageTitleH1,
|
||||
),
|
||||
SizedBox(
|
||||
height: isDesktop ? 32 : 16,
|
||||
),
|
||||
RoundedWhiteContainer(
|
||||
padding: isDesktop
|
||||
? const EdgeInsets.all(32)
|
||||
: const EdgeInsets.all(12),
|
||||
width: isDesktop ? 480 : null,
|
||||
child: Text(
|
||||
"On the next screen you will see $_numberOfPhraseWords words that make up your recovery phrase.\n\nPlease write it down. Keep it safe and never share it with anyone. Your recovery phrase is the only way you can access your funds if you forget your PIN, lose your phone, etc.\n\nStack Wallet does not keep nor is able to restore your recover phrase. Only you have access to your wallet.",
|
||||
style: isDesktop
|
||||
? STextStyles.desktopTextMediumRegular
|
||||
: STextStyles.subtitle.copyWith(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!isDesktop) const Spacer(),
|
||||
if (isDesktop)
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
height: 32,
|
||||
),
|
||||
Text(
|
||||
"Recovery Phrase",
|
||||
textAlign: TextAlign.center,
|
||||
style: STextStyles.pageTitleH1,
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: isDesktop ? 480 : 0,
|
||||
),
|
||||
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(
|
||||
"On the next screen you will see $_numberOfPhraseWords words that make up your recovery phrase.\n\nPlease write it down. Keep it safe and never share it with anyone. Your recovery phrase is the only way you can access your funds if you forget your PIN, lose your phone, etc.\n\nStack Wallet does not keep nor is able to restore your recover phrase. Only you have access to your wallet.",
|
||||
style: STextStyles.subtitle.copyWith(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Consumer(
|
||||
child: Consumer(
|
||||
builder: (_, ref, __) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
|
@ -119,6 +139,9 @@ class _NewWalletRecoveryPhraseWarningViewState
|
|||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Row(
|
||||
crossAxisAlignment: isDesktop
|
||||
? CrossAxisAlignment.start
|
||||
: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Checkbox(
|
||||
materialTapTargetSize:
|
||||
|
@ -131,138 +154,139 @@ class _NewWalletRecoveryPhraseWarningViewState
|
|||
newValue!;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 4,
|
||||
SizedBox(
|
||||
width: isDesktop ? 14 : 4,
|
||||
),
|
||||
Flexible(
|
||||
child: Text(
|
||||
"I understand that if I lose my recovery phrase, I will not be able to access my funds.",
|
||||
style: STextStyles.baseXS,
|
||||
style: isDesktop
|
||||
? STextStyles.desktopTextMedium
|
||||
: STextStyles.baseXS,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
SizedBox(
|
||||
height: isDesktop ? 32 : 16,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: ref.read(checkBoxStateProvider.state).state
|
||||
? () async {
|
||||
try {
|
||||
showDialog<dynamic>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
useSafeArea: true,
|
||||
builder: (ctx) {
|
||||
return const Center(
|
||||
child: LoadingIndicator(
|
||||
width: 50,
|
||||
height: 50,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
final walletsService = ref.read(
|
||||
walletsServiceChangeNotifierProvider);
|
||||
|
||||
final walletId =
|
||||
await walletsService.addNewWallet(
|
||||
name: walletName,
|
||||
coin: coin,
|
||||
shouldNotifyListeners: false,
|
||||
);
|
||||
|
||||
var node = ref
|
||||
.read(nodeServiceChangeNotifierProvider)
|
||||
.getPrimaryNodeFor(coin: coin);
|
||||
|
||||
if (node == null) {
|
||||
node = DefaultNodes.getNodeFor(coin);
|
||||
ref
|
||||
.read(nodeServiceChangeNotifierProvider)
|
||||
.setPrimaryNodeFor(
|
||||
coin: coin,
|
||||
node: node,
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: isDesktop ? 70 : 0,
|
||||
),
|
||||
child: TextButton(
|
||||
onPressed: ref.read(checkBoxStateProvider.state).state
|
||||
? () async {
|
||||
try {
|
||||
unawaited(showDialog<dynamic>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
useSafeArea: true,
|
||||
builder: (ctx) {
|
||||
return const Center(
|
||||
child: LoadingIndicator(
|
||||
width: 50,
|
||||
height: 50,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
));
|
||||
|
||||
final txTracker =
|
||||
TransactionNotificationTracker(
|
||||
walletId: walletId!);
|
||||
final walletsService = ref.read(
|
||||
walletsServiceChangeNotifierProvider);
|
||||
|
||||
final failovers = ref
|
||||
.read(nodeServiceChangeNotifierProvider)
|
||||
.failoverNodesFor(coin: widget.coin);
|
||||
|
||||
final wallet = CoinServiceAPI.from(
|
||||
coin,
|
||||
walletId,
|
||||
walletName,
|
||||
node,
|
||||
txTracker,
|
||||
ref.read(prefsChangeNotifierProvider),
|
||||
failovers,
|
||||
);
|
||||
|
||||
final manager = Manager(wallet);
|
||||
|
||||
await manager.initializeNew();
|
||||
|
||||
// pop progress dialog
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
// set checkbox back to unchecked to annoy users to agree again :P
|
||||
ref.read(checkBoxStateProvider.state).state =
|
||||
false;
|
||||
|
||||
if (mounted) {
|
||||
Navigator.of(context).pushNamed(
|
||||
NewWalletRecoveryPhraseView.routeName,
|
||||
arguments: Tuple2(
|
||||
manager,
|
||||
await manager.mnemonic,
|
||||
),
|
||||
final walletId =
|
||||
await walletsService.addNewWallet(
|
||||
name: walletName,
|
||||
coin: coin,
|
||||
shouldNotifyListeners: false,
|
||||
);
|
||||
|
||||
var node = ref
|
||||
.read(nodeServiceChangeNotifierProvider)
|
||||
.getPrimaryNodeFor(coin: coin);
|
||||
|
||||
if (node == null) {
|
||||
node = DefaultNodes.getNodeFor(coin);
|
||||
await ref
|
||||
.read(
|
||||
nodeServiceChangeNotifierProvider)
|
||||
.setPrimaryNodeFor(
|
||||
coin: coin,
|
||||
node: node,
|
||||
);
|
||||
}
|
||||
|
||||
final txTracker =
|
||||
TransactionNotificationTracker(
|
||||
walletId: walletId!);
|
||||
|
||||
final failovers = ref
|
||||
.read(nodeServiceChangeNotifierProvider)
|
||||
.failoverNodesFor(coin: widget.coin);
|
||||
|
||||
final wallet = CoinServiceAPI.from(
|
||||
coin,
|
||||
walletId,
|
||||
walletName,
|
||||
node,
|
||||
txTracker,
|
||||
ref.read(prefsChangeNotifierProvider),
|
||||
failovers,
|
||||
);
|
||||
|
||||
final manager = Manager(wallet);
|
||||
|
||||
await manager.initializeNew();
|
||||
|
||||
// pop progress dialog
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
// set checkbox back to unchecked to annoy users to agree again :P
|
||||
ref
|
||||
.read(checkBoxStateProvider.state)
|
||||
.state = false;
|
||||
|
||||
if (mounted) {
|
||||
unawaited(Navigator.of(context).pushNamed(
|
||||
NewWalletRecoveryPhraseView.routeName,
|
||||
arguments: Tuple2(
|
||||
manager,
|
||||
await manager.mnemonic,
|
||||
),
|
||||
));
|
||||
}
|
||||
} catch (e, s) {
|
||||
Logging.instance
|
||||
.log("$e\n$s", level: LogLevel.Fatal);
|
||||
// TODO: handle gracefully
|
||||
// any network/socket exception here will break new wallet creation
|
||||
rethrow;
|
||||
}
|
||||
} catch (e, s) {
|
||||
Logging.instance
|
||||
.log("$e\n$s", level: LogLevel.Fatal);
|
||||
// TODO: handle gracefully
|
||||
// any network/socket exception here will break new wallet creation
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
: null,
|
||||
style: ref.read(checkBoxStateProvider.state).state
|
||||
? Theme.of(context).textButtonTheme.style?.copyWith(
|
||||
backgroundColor:
|
||||
MaterialStateProperty.all<Color>(
|
||||
CFColors.stackAccent,
|
||||
),
|
||||
)
|
||||
: Theme.of(context).textButtonTheme.style?.copyWith(
|
||||
backgroundColor:
|
||||
MaterialStateProperty.all<Color>(
|
||||
CFColors.stackAccent.withOpacity(
|
||||
0.25,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
"View recovery phrase",
|
||||
style: STextStyles.button,
|
||||
: null,
|
||||
style: ref.read(checkBoxStateProvider.state).state
|
||||
? CFColors.getPrimaryEnabledButtonColor(context)
|
||||
: CFColors.getPrimaryDisabledButtonColor(context),
|
||||
child: Text(
|
||||
"View recovery phrase",
|
||||
style: isDesktop
|
||||
? ref.read(checkBoxStateProvider.state).state
|
||||
? STextStyles.desktopButtonEnabled
|
||||
: STextStyles.desktopButtonDisabled
|
||||
: STextStyles.button,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -166,6 +166,13 @@ class STextStyles {
|
|||
height: 30 / 20,
|
||||
);
|
||||
|
||||
static final TextStyle desktopTextMediumRegular = GoogleFonts.inter(
|
||||
color: CFColors.textDark,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 20,
|
||||
height: 30 / 20,
|
||||
);
|
||||
|
||||
static final TextStyle desktopSubtitleH2 = GoogleFonts.inter(
|
||||
color: CFColors.textDark,
|
||||
fontWeight: FontWeight.w400,
|
||||
|
|
|
@ -30,3 +30,35 @@ class DesktopScaffold extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MasterScaffold extends StatelessWidget {
|
||||
const MasterScaffold({
|
||||
Key? key,
|
||||
required this.isDesktop,
|
||||
required this.appBar,
|
||||
required this.body,
|
||||
this.background = CFColors.background,
|
||||
}) : super(key: key);
|
||||
|
||||
final bool isDesktop;
|
||||
final Widget appBar;
|
||||
final Widget body;
|
||||
final Color background;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (isDesktop) {
|
||||
return DesktopScaffold(
|
||||
background: background,
|
||||
appBar: appBar,
|
||||
body: body,
|
||||
);
|
||||
} else {
|
||||
return Scaffold(
|
||||
backgroundColor: background,
|
||||
appBar: appBar as PreferredSizeWidget?,
|
||||
body: body,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,16 +8,22 @@ class RoundedContainer extends StatelessWidget {
|
|||
required this.color,
|
||||
this.padding = const EdgeInsets.all(12),
|
||||
this.radiusMultiplier = 1.0,
|
||||
this.width,
|
||||
this.height,
|
||||
}) : super(key: key);
|
||||
|
||||
final Widget? child;
|
||||
final Color color;
|
||||
final EdgeInsets padding;
|
||||
final double radiusMultiplier;
|
||||
final double? width;
|
||||
final double? height;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: width,
|
||||
height: height,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
borderRadius: BorderRadius.circular(
|
||||
|
|
|
@ -8,11 +8,15 @@ class RoundedWhiteContainer extends StatelessWidget {
|
|||
this.child,
|
||||
this.padding = const EdgeInsets.all(12),
|
||||
this.radiusMultiplier = 1.0,
|
||||
this.width,
|
||||
this.height,
|
||||
}) : super(key: key);
|
||||
|
||||
final Widget? child;
|
||||
final EdgeInsets padding;
|
||||
final double radiusMultiplier;
|
||||
final double? width;
|
||||
final double? height;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -20,6 +24,8 @@ class RoundedWhiteContainer extends StatelessWidget {
|
|||
color: CFColors.white,
|
||||
padding: padding,
|
||||
radiusMultiplier: radiusMultiplier,
|
||||
width: width,
|
||||
height: height,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue