From 8d56358ebc8b6d320609e72c49479b4c3a289157 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 18 Apr 2024 15:29:36 -0500 Subject: [PATCH] validate remainder seed word input(s) --- .../restore_wallet_view.dart | 874 +++++++++--------- 1 file changed, 426 insertions(+), 448 deletions(-) diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index e9f0442d5..14174b22b 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -56,7 +56,6 @@ import 'package:stackwallet/wallets/wallet/impl/monero_wallet.dart'; import 'package:stackwallet/wallets/wallet/impl/wownero_wallet.dart'; import 'package:stackwallet/wallets/wallet/supporting/epiccash_wallet_info_extension.dart'; import 'package:stackwallet/wallets/wallet/wallet.dart'; -import 'package:stackwallet/widgets/conditional_parent.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'; @@ -724,480 +723,459 @@ class _RestoreWalletViewState extends ConsumerState { ], ), body: Container( - color: Theme.of(context).extension()!.background, - child: Padding( - padding: const EdgeInsets.all(12.0), - child: SingleChildScrollView( - controller: controller, - child: Column( - children: [ - /*if (isDesktop) + color: Theme.of(context).extension()!.background, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: SingleChildScrollView( + controller: controller, + child: Column( + children: [ + /*if (isDesktop) const Spacer( flex: 10, ),*/ - if (!isDesktop) - Text( - widget.walletName, - style: STextStyles.itemSubtitle(context), - ), - SizedBox( - height: isDesktop ? 0 : 4, - ), + if (!isDesktop) Text( - "Recovery phrase", - style: isDesktop - ? STextStyles.desktopH2(context) - : STextStyles.pageTitleH1(context), + widget.walletName, + style: STextStyles.itemSubtitle(context), ), - SizedBox( - height: isDesktop ? 16 : 8, - ), - Text( - "Enter your $_seedWordCount-word recovery phrase.", - style: isDesktop - ? STextStyles.desktopSubtitleH2(context) - : STextStyles.subtitle(context), - ), - SizedBox( - height: isDesktop ? 16 : 10, - ), - if (isDesktop) - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - TextButton( - onPressed: pasteMnemonic, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 12, - ), - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.clipboard, - width: 22, - height: 22, - color: Theme.of(context) - .extension()! - .buttonTextSecondary, - ), - const SizedBox( - width: 8, - ), - Text( - "Paste", - style: STextStyles - .desktopButtonSmallSecondaryEnabled( - context), - ) - ], - ), + SizedBox( + height: isDesktop ? 0 : 4, + ), + Text( + "Recovery phrase", + style: isDesktop + ? STextStyles.desktopH2(context) + : STextStyles.pageTitleH1(context), + ), + SizedBox( + height: isDesktop ? 16 : 8, + ), + Text( + "Enter your $_seedWordCount-word recovery phrase.", + style: isDesktop + ? STextStyles.desktopSubtitleH2(context) + : STextStyles.subtitle(context), + ), + SizedBox( + height: isDesktop ? 16 : 10, + ), + if (isDesktop) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton( + onPressed: pasteMnemonic, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 12, ), - ), - ], - ), - if (isDesktop) - const SizedBox( - height: 20, - ), - if (isDesktop) - ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 1008, - ), - child: Builder( - builder: (BuildContext context) { - const cols = 4; - final int rows = _seedWordCount ~/ cols; - final int remainder = _seedWordCount % cols; - - return Column( + child: Row( children: [ - Form( - key: _formKey, - child: TableView( - shrinkWrap: true, - rowSpacing: 20, - rows: [ - for (int i = 0; i < rows; i++) - TableViewRow( - crossAxisAlignment: - CrossAxisAlignment.start, - spacing: 16, - cells: [ - for (int j = 1; j <= cols; j++) - TableViewCell( - flex: 1, - child: Column( - children: [ - TextFormField( - autocorrect: !isDesktop, - enableSuggestions: - !isDesktop, - textCapitalization: - TextCapitalization.none, - key: Key( - "restoreMnemonicFormField_$i"), - decoration: - _getInputDecorationFor( - _inputStatuses[ - i * 4 + j - 1], - "${i * 4 + j}"), - autovalidateMode: - AutovalidateMode - .onUserInteraction, - selectionControls: i * 4 + - j - - 1 == - 1 - ? textSelectionControls - : null, - // focusNode: - // _focusNodes[i * 4 + j - 1], - onChanged: (value) { - final FormInputStatus - formInputStatus; - - if (value.isEmpty) { - formInputStatus = - FormInputStatus - .empty; - } else if (_isValidMnemonicWord( - value - .trim() - .toLowerCase())) { - formInputStatus = - FormInputStatus - .valid; - } else { - formInputStatus = - FormInputStatus - .invalid; - } - - // if (formInputStatus == - // FormInputStatus.valid) { - // if (i * 4 + j < - // _focusNodes.length) { - // _focusNodes[i * 4 + j] - // .requestFocus(); - // } else if (i * 4 + j == - // _focusNodes.length) { - // _focusNodes[i * 4 + j - 1] - // .unfocus(); - // } - // } - setState(() { - _inputStatuses[ - i * 4 + j - 1] = - formInputStatus; - }); - }, - controller: _controllers[ - i * 4 + j - 1], - style: STextStyles.field( - context) - .copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textRestore, - fontSize: - isDesktop ? 16 : 14, - ), - ), - if (_inputStatuses[ - i * 4 + j - 1] == - FormInputStatus.invalid) - Align( - alignment: - Alignment.topLeft, - child: Padding( - padding: - const EdgeInsets - .only( - left: 12.0, - bottom: 4.0, - ), - child: Text( - "Please check spelling", - textAlign: - TextAlign.left, - style: - STextStyles.label( - context) - .copyWith( - color: Theme.of( - context) - .extension< - StackColors>()! - .textError, - ), - ), - ), - ) - ], - ), - ), - ], - expandingChild: null, - ), - if (remainder > 0) - TableViewRow( - spacing: 16, - cells: [ - for (int i = rows * cols; - i < _seedWordCount; - i++) ...[ - TableViewCell( - flex: 1, - child: Column( - children: [ - TextFormField( - autocorrect: !isDesktop, - enableSuggestions: - !isDesktop, - textCapitalization: - TextCapitalization.none, - key: Key( - "restoreMnemonicFormField_$i"), - decoration: - _getInputDecorationFor( - _inputStatuses[i], - "${i + 1}"), - autovalidateMode: - AutovalidateMode - .onUserInteraction, - selectionControls: i == 1 - ? textSelectionControls - : null, - // focusNode: _focusNodes[i], - onChanged: (value) { - final FormInputStatus - formInputStatus; - - if (value.isEmpty) { - formInputStatus = - FormInputStatus - .empty; - } else if (_isValidMnemonicWord( - value - .trim() - .toLowerCase())) { - formInputStatus = - FormInputStatus - .valid; - } else { - formInputStatus = - FormInputStatus - .invalid; - } - - // if (formInputStatus == - // FormInputStatus - // .valid && - // (i - 1) < - // _focusNodes.length) { - // Focus.of(context) - // .requestFocus( - // _focusNodes[i]); - // } - - // if (formInputStatus == - // FormInputStatus.valid) { - // if (i + 1 < - // _focusNodes.length) { - // _focusNodes[i + 1] - // .requestFocus(); - // } else if (i + 1 == - // _focusNodes.length) { - // _focusNodes[i].unfocus(); - // } - // } - }, - controller: _controllers[i], - style: STextStyles.field( - context) - .copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .overlay, - fontSize: - isDesktop ? 16 : 14, - ), - ), - if (_inputStatuses[i] == - FormInputStatus.invalid) - Align( - alignment: - Alignment.topLeft, - child: Padding( - padding: - const EdgeInsets - .only( - left: 12.0, - bottom: 4.0, - ), - child: Text( - "Please check spelling", - textAlign: - TextAlign.left, - style: - STextStyles.label( - context) - .copyWith( - color: Theme.of( - context) - .extension< - StackColors>()! - .textError, - ), - ), - ), - ) - ], - ), - ), - ], - for (int i = remainder; - i < cols; - i++) ...[ - TableViewCell( - flex: 1, - child: Container(), - ), - ], - ], - expandingChild: null, - ), - ], - ), + SvgPicture.asset( + Assets.svg.clipboard, + width: 22, + height: 22, + color: Theme.of(context) + .extension()! + .buttonTextSecondary, ), const SizedBox( - height: 32, - ), - PrimaryButton( - label: "Restore wallet", - width: 480, - onPressed: requestRestore, + width: 8, ), + Text( + "Paste", + style: STextStyles + .desktopButtonSmallSecondaryEnabled( + context), + ) ], - ); - }, + ), + ), ), + ], + ), + if (isDesktop) + const SizedBox( + height: 20, + ), + if (isDesktop) + ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 1008, ), - /*if (isDesktop) + child: Builder( + builder: (BuildContext context) { + const cols = 4; + final int rows = _seedWordCount ~/ cols; + final int remainder = _seedWordCount % cols; + + return Column( + children: [ + Form( + key: _formKey, + child: TableView( + shrinkWrap: true, + rowSpacing: 20, + rows: [ + for (int i = 0; i < rows; i++) + TableViewRow( + crossAxisAlignment: + CrossAxisAlignment.start, + spacing: 16, + cells: [ + for (int j = 1; j <= cols; j++) + TableViewCell( + flex: 1, + child: Column( + children: [ + TextFormField( + autocorrect: !isDesktop, + enableSuggestions: !isDesktop, + textCapitalization: + TextCapitalization.none, + key: Key( + "restoreMnemonicFormField_$i"), + decoration: + _getInputDecorationFor( + _inputStatuses[ + i * 4 + j - 1], + "${i * 4 + j}"), + autovalidateMode: + AutovalidateMode + .onUserInteraction, + selectionControls: i * 4 + + j - + 1 == + 1 + ? textSelectionControls + : null, + // focusNode: + // _focusNodes[i * 4 + j - 1], + onChanged: (value) { + final FormInputStatus + formInputStatus; + + if (value.isEmpty) { + formInputStatus = + FormInputStatus.empty; + } else if (_isValidMnemonicWord( + value + .trim() + .toLowerCase())) { + formInputStatus = + FormInputStatus.valid; + } else { + formInputStatus = + FormInputStatus + .invalid; + } + + // if (formInputStatus == + // FormInputStatus.valid) { + // if (i * 4 + j < + // _focusNodes.length) { + // _focusNodes[i * 4 + j] + // .requestFocus(); + // } else if (i * 4 + j == + // _focusNodes.length) { + // _focusNodes[i * 4 + j - 1] + // .unfocus(); + // } + // } + setState(() { + _inputStatuses[i * 4 + + j - + 1] = formInputStatus; + }); + }, + controller: _controllers[ + i * 4 + j - 1], + style: + STextStyles.field(context) + .copyWith( + color: Theme.of(context) + .extension< + StackColors>()! + .textRestore, + fontSize: + isDesktop ? 16 : 14, + ), + ), + if (_inputStatuses[ + i * 4 + j - 1] == + FormInputStatus.invalid) + Align( + alignment: + Alignment.topLeft, + child: Padding( + padding: + const EdgeInsets.only( + left: 12.0, + bottom: 4.0, + ), + child: Text( + "Please check spelling", + textAlign: + TextAlign.left, + style: + STextStyles.label( + context) + .copyWith( + color: Theme.of( + context) + .extension< + StackColors>()! + .textError, + ), + ), + ), + ) + ], + ), + ), + ], + expandingChild: null, + ), + if (remainder > 0) + TableViewRow( + spacing: 16, + cells: [ + for (int i = rows * cols; + i < _seedWordCount - remainder; + i++) ...[ + TableViewCell( + flex: 1, + child: Column( + // ... (existing code for input field) + ), + ), + ], + for (int i = _seedWordCount - remainder; + i < _seedWordCount; + i++) ...[ + TableViewCell( + flex: 1, + child: Column( + children: [ + TextFormField( + autocorrect: !isDesktop, + enableSuggestions: !isDesktop, + textCapitalization: + TextCapitalization.none, + key: Key( + "restoreMnemonicFormField_$i"), + decoration: + _getInputDecorationFor( + _inputStatuses[i], + "${i + 1}"), + autovalidateMode: + AutovalidateMode + .onUserInteraction, + selectionControls: i == 1 + ? textSelectionControls + : null, + onChanged: (value) { + final FormInputStatus + formInputStatus; + + if (value.isEmpty) { + formInputStatus = + FormInputStatus.empty; + } else if (_isValidMnemonicWord( + value + .trim() + .toLowerCase())) { + formInputStatus = + FormInputStatus.valid; + } else { + formInputStatus = + FormInputStatus + .invalid; + } + + setState(() { + _inputStatuses[i] = + formInputStatus; + }); + }, + controller: _controllers[i], + style: + STextStyles.field(context) + .copyWith( + color: Theme.of(context) + .extension< + StackColors>()! + .overlay, + fontSize: + isDesktop ? 16 : 14, + ), + ), + if (_inputStatuses[i] == + FormInputStatus.invalid) + Align( + alignment: + Alignment.topLeft, + child: Padding( + padding: + const EdgeInsets.only( + left: 12.0, + bottom: 4.0, + ), + child: Text( + "Please check spelling", + textAlign: + TextAlign.left, + style: + STextStyles.label( + context) + .copyWith( + color: Theme.of( + context) + .extension< + StackColors>()! + .textError, + ), + ), + ), + ) + ], + ), + ), + ], + for (int i = 0; + i < cols - remainder; + i++) ...[ + TableViewCell( + flex: 1, + child: Container(), + ), + ], + ], + expandingChild: null, + ), + ], + ), + ), + const SizedBox( + height: 32, + ), + PrimaryButton( + label: "Restore wallet", + width: 480, + onPressed: requestRestore, + ), + ], + ); + }, + ), + ), + /*if (isDesktop) const Spacer( flex: 15, ),*/ - if (!isDesktop) - Padding( - padding: const EdgeInsets.all(4.0), - child: Form( - key: _formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - for (int i = 1; i <= _seedWordCount; i++) - Column( - children: [ - Padding( - padding: - const EdgeInsets.symmetric(vertical: 4), - child: TextFormField( - autocorrect: !isDesktop, - enableSuggestions: !isDesktop, - textCapitalization: - TextCapitalization.none, - key: Key("restoreMnemonicFormField_$i"), - decoration: _getInputDecorationFor( - _inputStatuses[i - 1], "$i"), - autovalidateMode: - AutovalidateMode.onUserInteraction, - selectionControls: - i == 1 ? textSelectionControls : null, - // focusNode: _focusNodes[i - 1], - onChanged: (value) { - final FormInputStatus formInputStatus; + if (!isDesktop) + Padding( + padding: const EdgeInsets.all(4.0), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + for (int i = 1; i <= _seedWordCount; i++) + Column( + children: [ + Padding( + padding: + const EdgeInsets.symmetric(vertical: 4), + child: TextFormField( + autocorrect: !isDesktop, + enableSuggestions: !isDesktop, + textCapitalization: TextCapitalization.none, + key: Key("restoreMnemonicFormField_$i"), + decoration: _getInputDecorationFor( + _inputStatuses[i - 1], "$i"), + autovalidateMode: + AutovalidateMode.onUserInteraction, + selectionControls: + i == 1 ? textSelectionControls : null, + // focusNode: _focusNodes[i - 1], + onChanged: (value) { + final FormInputStatus formInputStatus; - if (value.isEmpty) { - formInputStatus = - FormInputStatus.empty; - } else if (_isValidMnemonicWord( - value.trim().toLowerCase())) { - formInputStatus = - FormInputStatus.valid; - } else { - formInputStatus = - FormInputStatus.invalid; - } + if (value.isEmpty) { + formInputStatus = FormInputStatus.empty; + } else if (_isValidMnemonicWord( + value.trim().toLowerCase())) { + formInputStatus = FormInputStatus.valid; + } else { + formInputStatus = + FormInputStatus.invalid; + } - // if (formInputStatus == - // FormInputStatus.valid) { - // if (i < _focusNodes.length) { - // _focusNodes[i].requestFocus(); - // } else if (i == _focusNodes.length) { - // _focusNodes[i - 1].unfocus(); - // } - // } - setState(() { - _inputStatuses[i - 1] = - formInputStatus; - }); - }, - controller: _controllers[i - 1], - style: - STextStyles.field(context).copyWith( - color: Theme.of(context) - .extension()! - .textRestore, - fontSize: isDesktop ? 16 : 14, - ), + // if (formInputStatus == + // FormInputStatus.valid) { + // if (i < _focusNodes.length) { + // _focusNodes[i].requestFocus(); + // } else if (i == _focusNodes.length) { + // _focusNodes[i - 1].unfocus(); + // } + // } + setState(() { + _inputStatuses[i - 1] = formInputStatus; + }); + }, + controller: _controllers[i - 1], + style: STextStyles.field(context).copyWith( + color: Theme.of(context) + .extension()! + .textRestore, + fontSize: isDesktop ? 16 : 14, ), ), - if (_inputStatuses[i - 1] == - FormInputStatus.invalid) - Align( - alignment: Alignment.topLeft, - child: Padding( - padding: const EdgeInsets.only( - left: 12.0, - bottom: 4.0, - ), - child: Text( - "Please check spelling", - textAlign: TextAlign.left, - style: STextStyles.label(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textError, - ), + ), + if (_inputStatuses[i - 1] == + FormInputStatus.invalid) + Align( + alignment: Alignment.topLeft, + child: Padding( + padding: const EdgeInsets.only( + left: 12.0, + bottom: 4.0, + ), + child: Text( + "Please check spelling", + textAlign: TextAlign.left, + style: + STextStyles.label(context).copyWith( + color: Theme.of(context) + .extension()! + .textError, ), ), - ) - ], - ), - Padding( - padding: const EdgeInsets.only( - top: 8.0, - ), - child: PrimaryButton( - onPressed: requestRestore, - label: "Restore", - ), + ), + ) + ], ), - ], - ), + Padding( + padding: const EdgeInsets.only( + top: 8.0, + ), + child: PrimaryButton( + onPressed: requestRestore, + label: "Restore", + ), + ), + ], ), ), - ], - ), + ), + ], ), ), ), - ); + ), + ); } }