mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-02-02 03:06:29 +00:00
verify mnemonic passphrase dialog
This commit is contained in:
parent
e20ce631e6
commit
244a1914b3
3 changed files with 245 additions and 1 deletions
|
@ -0,0 +1,218 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||||
|
import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart';
|
||||||
|
import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
|
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||||
|
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||||
|
|
||||||
|
class VerifyMnemonicPassphraseDialog extends ConsumerStatefulWidget {
|
||||||
|
const VerifyMnemonicPassphraseDialog({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<VerifyMnemonicPassphraseDialog> createState() =>
|
||||||
|
_VerifyMnemonicPassphraseDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _VerifyMnemonicPassphraseDialogState
|
||||||
|
extends ConsumerState<VerifyMnemonicPassphraseDialog> {
|
||||||
|
late final FocusNode passwordFocusNode;
|
||||||
|
late final TextEditingController passwordController;
|
||||||
|
|
||||||
|
bool hidePassword = true;
|
||||||
|
|
||||||
|
bool _verifyLock = false;
|
||||||
|
|
||||||
|
void _verify() {
|
||||||
|
if (_verifyLock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_verifyLock = true;
|
||||||
|
|
||||||
|
if (passwordController.text ==
|
||||||
|
ref.read(pNewWalletOptions.state).state!.mnemonicPassphrase) {
|
||||||
|
Navigator.of(context, rootNavigator: Util.isDesktop).pop("verified");
|
||||||
|
} else {
|
||||||
|
showFloatingFlushBar(
|
||||||
|
type: FlushBarType.warning,
|
||||||
|
message: "Passphrase does not match",
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_verifyLock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
passwordController = TextEditingController();
|
||||||
|
passwordFocusNode = FocusNode();
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
passwordController.dispose();
|
||||||
|
passwordFocusNode.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ConditionalParent(
|
||||||
|
condition: Util.isDesktop,
|
||||||
|
builder: (child) => DesktopDialog(
|
||||||
|
maxHeight: double.infinity,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 32,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
"Verify mnemonic passphrase",
|
||||||
|
style: STextStyles.desktopH3(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const DesktopDialogCloseButton(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 32,
|
||||||
|
right: 32,
|
||||||
|
bottom: 32,
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: ConditionalParent(
|
||||||
|
condition: !Util.isDesktop,
|
||||||
|
builder: (child) => StackDialogBase(
|
||||||
|
keyboardPaddingAmount: MediaQuery.of(context).viewInsets.bottom,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (!Util.isDesktop)
|
||||||
|
Text(
|
||||||
|
"Verify mnemonic passphrase",
|
||||||
|
style: STextStyles.pageTitleH2(context),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
key: const Key("mnemonicPassphraseFieldKey1"),
|
||||||
|
focusNode: passwordFocusNode,
|
||||||
|
controller: passwordController,
|
||||||
|
style: Util.isDesktop
|
||||||
|
? STextStyles.desktopTextMedium(context).copyWith(
|
||||||
|
height: 2,
|
||||||
|
)
|
||||||
|
: STextStyles.field(context),
|
||||||
|
obscureText: hidePassword,
|
||||||
|
enableSuggestions: false,
|
||||||
|
autocorrect: false,
|
||||||
|
decoration: standardInputDecoration(
|
||||||
|
"Recovery phrase password",
|
||||||
|
passwordFocusNode,
|
||||||
|
context,
|
||||||
|
).copyWith(
|
||||||
|
suffixIcon: UnconstrainedBox(
|
||||||
|
child: ConditionalParent(
|
||||||
|
condition: Util.isDesktop,
|
||||||
|
builder: (child) => SizedBox(
|
||||||
|
height: 70,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: Util.isDesktop ? 24 : 16,
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
key: const Key(
|
||||||
|
"mnemonicPassphraseFieldShowPasswordButtonKey"),
|
||||||
|
onTap: () async {
|
||||||
|
setState(() {
|
||||||
|
hidePassword = !hidePassword;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
hidePassword
|
||||||
|
? Assets.svg.eye
|
||||||
|
: Assets.svg.eyeSlash,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textDark3,
|
||||||
|
width: Util.isDesktop ? 24 : 16,
|
||||||
|
height: Util.isDesktop ? 24 : 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Util.isDesktop ? 48 : 24,
|
||||||
|
),
|
||||||
|
ConditionalParent(
|
||||||
|
condition: !Util.isDesktop,
|
||||||
|
builder: (child) => Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SecondaryButton(
|
||||||
|
label: "Cancel",
|
||||||
|
onPressed: Navigator.of(
|
||||||
|
context,
|
||||||
|
rootNavigator: Util.isDesktop,
|
||||||
|
).pop,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 16,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: PrimaryButton(
|
||||||
|
label: "Verify",
|
||||||
|
onPressed: _verify,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,9 +16,11 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart';
|
import 'package:stackwallet/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart';
|
||||||
|
import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/new_wallet_recovery_phrase_view.dart';
|
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/new_wallet_recovery_phrase_view.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/select_wallet_for_token_view.dart';
|
import 'package:stackwallet/pages/add_wallet_views/select_wallet_for_token_view.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/verify_recovery_phrase_view/sub_widgets/word_table.dart';
|
import 'package:stackwallet/pages/add_wallet_views/verify_recovery_phrase_view/sub_widgets/word_table.dart';
|
||||||
|
import 'package:stackwallet/pages/add_wallet_views/verify_recovery_phrase_view/verify_mnemonic_passphrase_dialog.dart';
|
||||||
import 'package:stackwallet/pages/home_view/home_view.dart';
|
import 'package:stackwallet/pages/home_view/home_view.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
|
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
|
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
|
||||||
|
@ -98,8 +100,25 @@ class _VerifyRecoveryPhraseViewState
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
Future<bool> _verifyMnemonicPassphrase() async {
|
||||||
|
final result = await showDialog<String?>(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => const VerifyMnemonicPassphraseDialog(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return result == "verified";
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _continue(bool isMatch) async {
|
Future<void> _continue(bool isMatch) async {
|
||||||
if (isMatch) {
|
if (isMatch) {
|
||||||
|
if (ref.read(pNewWalletOptions.state).state != null) {
|
||||||
|
final passphraseVerified = await _verifyMnemonicPassphrase();
|
||||||
|
|
||||||
|
if (!passphraseVerified) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await ref.read(walletsServiceChangeNotifierProvider).setMnemonicVerified(
|
await ref.read(walletsServiceChangeNotifierProvider).setMnemonicVerified(
|
||||||
walletId: _manager.walletId,
|
walletId: _manager.walletId,
|
||||||
);
|
);
|
||||||
|
|
|
@ -18,15 +18,22 @@ class StackDialogBase extends StatelessWidget {
|
||||||
Key? key,
|
Key? key,
|
||||||
this.child,
|
this.child,
|
||||||
this.padding = const EdgeInsets.all(24),
|
this.padding = const EdgeInsets.all(24),
|
||||||
|
this.keyboardPaddingAmount = 0,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final EdgeInsets padding;
|
final EdgeInsets padding;
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
|
final double keyboardPaddingAmount;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: EdgeInsets.only(
|
||||||
|
top: 16,
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
bottom: 16 + keyboardPaddingAmount,
|
||||||
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment:
|
||||||
!Util.isDesktop ? MainAxisAlignment.end : MainAxisAlignment.center,
|
!Util.isDesktop ? MainAxisAlignment.end : MainAxisAlignment.center,
|
||||||
|
|
Loading…
Reference in a new issue