Merge pull request #834 from cypherstack/ui

Validate remainder seed word input(s)
This commit is contained in:
Diego Salazar 2024-04-18 15:54:00 -06:00 committed by GitHub
commit d4b760c3e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -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/impl/wownero_wallet.dart';
import 'package:stackwallet/wallets/wallet/supporting/epiccash_wallet_info_extension.dart'; import 'package:stackwallet/wallets/wallet/supporting/epiccash_wallet_info_extension.dart';
import 'package:stackwallet/wallets/wallet/wallet.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/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart'; import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart'; import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
@ -724,480 +723,459 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
], ],
), ),
body: Container( body: Container(
color: Theme.of(context).extension<StackColors>()!.background, color: Theme.of(context).extension<StackColors>()!.background,
child: Padding( child: Padding(
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12.0),
child: SingleChildScrollView( child: SingleChildScrollView(
controller: controller, controller: controller,
child: Column( child: Column(
children: [ children: [
/*if (isDesktop) /*if (isDesktop)
const Spacer( const Spacer(
flex: 10, flex: 10,
),*/ ),*/
if (!isDesktop) if (!isDesktop)
Text(
widget.walletName,
style: STextStyles.itemSubtitle(context),
),
SizedBox(
height: isDesktop ? 0 : 4,
),
Text( Text(
"Recovery phrase", widget.walletName,
style: isDesktop style: STextStyles.itemSubtitle(context),
? STextStyles.desktopH2(context)
: STextStyles.pageTitleH1(context),
), ),
SizedBox( SizedBox(
height: isDesktop ? 16 : 8, height: isDesktop ? 0 : 4,
), ),
Text( Text(
"Enter your $_seedWordCount-word recovery phrase.", "Recovery phrase",
style: isDesktop style: isDesktop
? STextStyles.desktopSubtitleH2(context) ? STextStyles.desktopH2(context)
: STextStyles.subtitle(context), : STextStyles.pageTitleH1(context),
), ),
SizedBox( SizedBox(
height: isDesktop ? 16 : 10, height: isDesktop ? 16 : 8,
), ),
if (isDesktop) Text(
Row( "Enter your $_seedWordCount-word recovery phrase.",
mainAxisAlignment: MainAxisAlignment.center, style: isDesktop
children: [ ? STextStyles.desktopSubtitleH2(context)
TextButton( : STextStyles.subtitle(context),
onPressed: pasteMnemonic, ),
child: Padding( SizedBox(
padding: const EdgeInsets.symmetric( height: isDesktop ? 16 : 10,
horizontal: 16.0, ),
vertical: 12, if (isDesktop)
), Row(
child: Row( mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SvgPicture.asset( TextButton(
Assets.svg.clipboard, onPressed: pasteMnemonic,
width: 22, child: Padding(
height: 22, padding: const EdgeInsets.symmetric(
color: Theme.of(context) horizontal: 16.0,
.extension<StackColors>()! vertical: 12,
.buttonTextSecondary,
),
const SizedBox(
width: 8,
),
Text(
"Paste",
style: STextStyles
.desktopButtonSmallSecondaryEnabled(
context),
)
],
),
), ),
), child: Row(
],
),
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(
children: [ children: [
Form( SvgPicture.asset(
key: _formKey, Assets.svg.clipboard,
child: TableView( width: 22,
shrinkWrap: true, height: 22,
rowSpacing: 20, color: Theme.of(context)
rows: [ .extension<StackColors>()!
for (int i = 0; i < rows; i++) .buttonTextSecondary,
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,
),
],
),
), ),
const SizedBox( const SizedBox(
height: 32, width: 8,
),
PrimaryButton(
label: "Restore wallet",
width: 480,
onPressed: requestRestore,
), ),
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( const Spacer(
flex: 15, flex: 15,
),*/ ),*/
if (!isDesktop) if (!isDesktop)
Padding( Padding(
padding: const EdgeInsets.all(4.0), padding: const EdgeInsets.all(4.0),
child: Form( child: Form(
key: _formKey, key: _formKey,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
for (int i = 1; i <= _seedWordCount; i++) for (int i = 1; i <= _seedWordCount; i++)
Column( Column(
children: [ children: [
Padding( Padding(
padding: padding:
const EdgeInsets.symmetric(vertical: 4), const EdgeInsets.symmetric(vertical: 4),
child: TextFormField( child: TextFormField(
autocorrect: !isDesktop, autocorrect: !isDesktop,
enableSuggestions: !isDesktop, enableSuggestions: !isDesktop,
textCapitalization: textCapitalization: TextCapitalization.none,
TextCapitalization.none, key: Key("restoreMnemonicFormField_$i"),
key: Key("restoreMnemonicFormField_$i"), decoration: _getInputDecorationFor(
decoration: _getInputDecorationFor( _inputStatuses[i - 1], "$i"),
_inputStatuses[i - 1], "$i"), autovalidateMode:
autovalidateMode: AutovalidateMode.onUserInteraction,
AutovalidateMode.onUserInteraction, selectionControls:
selectionControls: i == 1 ? textSelectionControls : null,
i == 1 ? textSelectionControls : null, // focusNode: _focusNodes[i - 1],
// focusNode: _focusNodes[i - 1], onChanged: (value) {
onChanged: (value) { final FormInputStatus formInputStatus;
final FormInputStatus formInputStatus;
if (value.isEmpty) { if (value.isEmpty) {
formInputStatus = formInputStatus = FormInputStatus.empty;
FormInputStatus.empty; } else if (_isValidMnemonicWord(
} else if (_isValidMnemonicWord( value.trim().toLowerCase())) {
value.trim().toLowerCase())) { formInputStatus = FormInputStatus.valid;
formInputStatus = } else {
FormInputStatus.valid; formInputStatus =
} else { FormInputStatus.invalid;
formInputStatus = }
FormInputStatus.invalid;
}
// if (formInputStatus == // if (formInputStatus ==
// FormInputStatus.valid) { // FormInputStatus.valid) {
// if (i < _focusNodes.length) { // if (i < _focusNodes.length) {
// _focusNodes[i].requestFocus(); // _focusNodes[i].requestFocus();
// } else if (i == _focusNodes.length) { // } else if (i == _focusNodes.length) {
// _focusNodes[i - 1].unfocus(); // _focusNodes[i - 1].unfocus();
// } // }
// } // }
setState(() { setState(() {
_inputStatuses[i - 1] = _inputStatuses[i - 1] = formInputStatus;
formInputStatus; });
}); },
}, controller: _controllers[i - 1],
controller: _controllers[i - 1], style: STextStyles.field(context).copyWith(
style: color: Theme.of(context)
STextStyles.field(context).copyWith( .extension<StackColors>()!
color: Theme.of(context) .textRestore,
.extension<StackColors>()! fontSize: isDesktop ? 16 : 14,
.textRestore,
fontSize: isDesktop ? 16 : 14,
),
), ),
), ),
if (_inputStatuses[i - 1] == ),
FormInputStatus.invalid) if (_inputStatuses[i - 1] ==
Align( FormInputStatus.invalid)
alignment: Alignment.topLeft, Align(
child: Padding( alignment: Alignment.topLeft,
padding: const EdgeInsets.only( child: Padding(
left: 12.0, padding: const EdgeInsets.only(
bottom: 4.0, left: 12.0,
), bottom: 4.0,
child: Text( ),
"Please check spelling", child: Text(
textAlign: TextAlign.left, "Please check spelling",
style: STextStyles.label(context) textAlign: TextAlign.left,
.copyWith( style:
color: Theme.of(context) STextStyles.label(context).copyWith(
.extension<StackColors>()! color: Theme.of(context)
.textError, .extension<StackColors>()!
), .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",
),
),
],
), ),
), ),
], ),
), ],
), ),
), ),
), ),
); ),
);
} }
} }