Cw 462 monero polyseed restore support (#1109)

* CW-462 Mark Places to integrate Polyseed

* CW-462 Add Restore from Polyseed

* CW-462 Add Restore from Polyseed

* CW-462 Add new Monero date-height pairs

* CW-462 Little Cleanup

* CW-462 Ups I missed that Debug line :/

* CW-462 Fix Polyseed not showing in Wallet-Seed/Keys Page

* CW-462 Prepare for Wallet creation

* CW-462 Fix merge conflict

* CW-462 Fix generating monero.dart

* CW-462 Add Polyseed generation

* CW-462 Add Polyseed Languages to SeedLanguagePicker

* CW-462 Apply requested changes

* CW-462 Minor bug fixes in restore screen

* Update wallet_restore_from_seed_form.dart

* CW-462 Minor Bugfix

* CW-462 Fix Restore from QR for Polyseeds

* CW-462 Fix null-check-operator exception for Polyseeds and minor inconveniences

* CW-462 Fix minor inconveniences

* Fix conflicts and review comments and wrap unspent issue with try and catch with reporting failure

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
This commit is contained in:
Konstantin Ullrich
2023-11-25 02:37:12 +02:00
committed by GitHub
co-authored by OmarHatem
parent eeb9976d09
commit 00c97c74b8
57 changed files with 906 additions and 444 deletions
@@ -1,6 +1,7 @@
import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/fiat_api_mode.dart';
import 'package:cake_wallet/entities/seed_phrase_length.dart';
import 'package:cake_wallet/entities/seed_type.dart';
import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
@@ -97,16 +98,27 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
);
}),
if (widget.privacySettingsViewModel.hasSeedPhraseLengthOption)
Observer(builder: (_) {
return SettingsPickerCell<SeedPhraseLength>(
title: S.current.seed_phrase_length,
items: SeedPhraseLength.values,
selectedItem: widget.privacySettingsViewModel.seedPhraseLength,
onItemSelected: (SeedPhraseLength length) {
widget.privacySettingsViewModel.setSeedPhraseLength(length);
},
);
}),
Observer(builder: (_) {
return SettingsPickerCell<SeedPhraseLength>(
title: S.current.seed_phrase_length,
items: SeedPhraseLength.values,
selectedItem: widget.privacySettingsViewModel.seedPhraseLength,
onItemSelected: (SeedPhraseLength length) {
widget.privacySettingsViewModel.setSeedPhraseLength(length);
},
);
}),
if (widget.privacySettingsViewModel.hasSeedTypeOption)
Observer(builder: (_) {
return SettingsChoicesCell(
ChoicesListItem<SeedType>(
title: S.current.seedtype,
items: SeedType.all,
selectedItem: widget.privacySettingsViewModel.seedType,
onItemSelected: widget.privacySettingsViewModel.setSeedType,
),
);
}),
],
),
bottomSectionPadding: EdgeInsets.all(24),
+30 -13
View File
@@ -14,17 +14,20 @@ import 'package:cake_wallet/src/widgets/seed_language_selector.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart';
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
import 'package:cake_wallet/entities/seed_type.dart';
import 'package:cake_wallet/store/settings_store.dart';
class NewWalletPage extends BasePage {
NewWalletPage(this._walletNewVM);
NewWalletPage(this._walletNewVM, this._settingsStore);
final WalletNewVM _walletNewVM;
final SettingsStore _settingsStore;
final walletNameImage = Image.asset('assets/images/wallet_name.png');
@@ -35,14 +38,15 @@ class NewWalletPage extends BasePage {
@override
Widget body(BuildContext context) => WalletNameForm(
_walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage);
_walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage, _settingsStore);
}
class WalletNameForm extends StatefulWidget {
WalletNameForm(this._walletNewVM, this.walletImage);
WalletNameForm(this._walletNewVM, this.walletImage, this._settingsStore);
final WalletNewVM _walletNewVM;
final Image walletImage;
final SettingsStore _settingsStore;
@override
_WalletNameFormState createState() => _WalletNameFormState(_walletNewVM);
@@ -125,15 +129,20 @@ class _WalletNameFormState extends State<WalletNameForm> {
hintStyle: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor),
color:
Theme.of(context).extension<NewWalletTheme>()!.hintTextColor),
hintText: S.of(context).wallet_name,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).extension<NewWalletTheme>()!.underlineColor,
color: Theme.of(context)
.extension<NewWalletTheme>()!
.underlineColor,
width: 1.0)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).extension<NewWalletTheme>()!.underlineColor,
color: Theme.of(context)
.extension<NewWalletTheme>()!
.underlineColor,
width: 1.0),
),
suffixIcon: Semantics(
@@ -160,7 +169,9 @@ class _WalletNameFormState extends State<WalletNameForm> {
height: 34,
child: Image.asset(
'assets/images/refresh_icon.png',
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor,
color: Theme.of(context)
.extension<SendPageTheme>()!
.textFieldButtonIconColor,
),
),
),
@@ -184,10 +195,15 @@ class _WalletNameFormState extends State<WalletNameForm> {
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
),
),
Padding(
padding: EdgeInsets.only(top: 24),
child: SeedLanguageSelector(
key: _languageSelectorKey, initialSelected: defaultSeedLanguage),
Observer(
builder: (BuildContext build) => Padding(
padding: EdgeInsets.only(top: 24),
child: SeedLanguageSelector(
key: _languageSelectorKey,
initialSelected: defaultSeedLanguage,
seedType: widget._settingsStore.moneroSeedType,
),
),
)
]
],
@@ -237,9 +253,10 @@ class _WalletNameFormState extends State<WalletNameForm> {
buttonAction: () => Navigator.of(context).pop());
});
} else {
final isPolyseed = widget._settingsStore.moneroSeedType == SeedType.polyseed;
_walletNewVM.create(
options: _walletNewVM.hasLanguageSelector
? _languageSelectorKey.currentState!.selected
? [_languageSelectorKey.currentState!.selected, isPolyseed]
: null);
}
}
@@ -1,17 +1,17 @@
import 'package:cake_wallet/core/wallet_name_validator.dart';
import 'package:cake_wallet/entities/generate_name.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
import 'package:cake_wallet/src/widgets/seed_widget.dart';
import 'package:cake_wallet/entities/seed_type.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/core/wallet_name_validator.dart';
import 'package:cake_wallet/src/widgets/picker.dart';
import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
import 'package:cake_wallet/src/widgets/seed_widget.dart';
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:polyseed/polyseed.dart';
class WalletRestoreFromSeedForm extends StatefulWidget {
WalletRestoreFromSeedForm(
@@ -34,8 +34,7 @@ class WalletRestoreFromSeedForm extends StatefulWidget {
final void Function(String)? onLanguageChange;
@override
WalletRestoreFromSeedFormState createState() =>
WalletRestoreFromSeedFormState('English');
WalletRestoreFromSeedFormState createState() => WalletRestoreFromSeedFormState('English');
}
class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
@@ -44,77 +43,116 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
blockchainHeightKey = GlobalKey<BlockchainHeightState>(),
formKey = GlobalKey<FormState>(),
languageController = TextEditingController(),
nameTextEditingController = TextEditingController();
nameTextEditingController = TextEditingController(),
seedTypeController = TextEditingController();
final GlobalKey<SeedWidgetState> seedWidgetStateKey;
final GlobalKey<BlockchainHeightState> blockchainHeightKey;
final TextEditingController languageController;
final TextEditingController nameTextEditingController;
final TextEditingController seedTypeController;
final GlobalKey<FormState> formKey;
String language;
bool isPolyseed = false;
@override
void initState() {
_setLanguageLabel(language);
_setSeedType(SeedType.defaultSeedType);
super.initState();
}
void onSeedChange(String seed) {
if (widget.type == WalletType.monero && Polyseed.isValidSeed(seed)) {
final lang = PolyseedLang.getByPhrase(seed);
_changeSeedType(SeedType.polyseed);
_changeLanguage(lang.nameEnglish);
}
widget.onSeedChange?.call(seed);
}
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(left: 24, right: 24),
child: Column(children: [
Form(
key: formKey,
child: Stack(
alignment: Alignment.centerRight,
children: [
BaseTextFormField(
controller: nameTextEditingController,
hintText: S.of(context).wallet_name,
suffixIcon: IconButton(
onPressed: () async {
final rName = await generateName();
FocusManager.instance.primaryFocus?.unfocus();
key: formKey,
child: Stack(
alignment: Alignment.centerRight,
children: [
BaseTextFormField(
controller: nameTextEditingController,
hintText: S.of(context).wallet_name,
suffixIcon: IconButton(
onPressed: () async {
final rName = await generateName();
FocusManager.instance.primaryFocus?.unfocus();
setState(() {
nameTextEditingController.text = rName;
nameTextEditingController.selection =
TextSelection.fromPosition(TextPosition(
offset: nameTextEditingController.text.length));
});
},
icon: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.0),
color: Theme.of(context).hintColor,
),
width: 34,
height: 34,
child: Image.asset(
'assets/images/refresh_icon.png',
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor,
setState(() {
nameTextEditingController.text = rName;
nameTextEditingController.selection = TextSelection.fromPosition(
TextPosition(offset: nameTextEditingController.text.length));
});
},
icon: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.0),
color: Theme.of(context).hintColor,
),
width: 34,
height: 34,
child: Image.asset(
'assets/images/refresh_icon.png',
color: Theme.of(context)
.extension<SendPageTheme>()!
.textFieldButtonIconColor,
),
),
),
validator: WalletNameValidator(),
),
),
validator: WalletNameValidator(),
),
],
)),
],
)),
Container(height: 20),
SeedWidget(
key: seedWidgetStateKey,
language: language,
type: widget.type,
onSeedChange: widget.onSeedChange),
onSeedChange: onSeedChange),
if (widget.type == WalletType.monero)
GestureDetector(
onTap: () async {
await showPopUp<void>(
context: context,
builder: (_) => Picker(
items: SeedType.all,
selectedAtIndex: isPolyseed ? 1 : 0,
mainAxisAlignment: MainAxisAlignment.start,
onItemSelected: _changeSeedType,
isSeparated: false,
));
},
child: Container(
color: Colors.transparent,
padding: EdgeInsets.only(top: 20.0),
child: IgnorePointer(
child: BaseTextFormField(
controller: seedTypeController,
enableInteractiveSelection: false,
readOnly: true)))),
if (widget.displayLanguageSelector)
GestureDetector(
onTap: () async {
await showPopUp<void>(
context: context,
builder: (_) => SeedLanguagePicker(
selected: language, onItemSelected: _changeLanguage));
selected: language,
onItemSelected: _changeLanguage,
seedType: isPolyseed ? SeedType.polyseed : SeedType.legacy,
));
},
child: Container(
color: Colors.transparent,
@@ -124,24 +162,35 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
controller: languageController,
enableInteractiveSelection: false,
readOnly: true)))),
if (widget.displayBlockHeightSelector)
if (!isPolyseed && widget.displayBlockHeightSelector)
BlockchainHeightWidget(
focusNode: widget.blockHeightFocusNode,
key: blockchainHeightKey,
onHeightOrDateEntered: widget.onHeightOrDateEntered,
hasDatePicker: widget.type == WalletType.monero)
hasDatePicker: widget.type == WalletType.monero),
]));
}
void _changeLanguage(String language) {
final setLang = isPolyseed ? "POLYSEED_$language" : language;
setState(() {
this.language = language;
seedWidgetStateKey.currentState!.changeSeedLanguage(language);
_setLanguageLabel(language);
widget.onLanguageChange?.call(language);
this.language = setLang;
seedWidgetStateKey.currentState!.changeSeedLanguage(setLang);
_setLanguageLabel(setLang);
widget.onLanguageChange?.call(setLang);
});
}
void _setLanguageLabel(String language) =>
languageController.text = '$language (Seed language)';
languageController.text = '${language.replaceAll("POLYSEED_", "")} (Seed language)';
void _changeSeedType(SeedType item) {
_setSeedType(item);
_changeLanguage('English');
}
void _setSeedType(SeedType item) {
setState(() => isPolyseed = item == SeedType.polyseed);
seedTypeController.text = item.toString();
}
}
@@ -1,29 +1,30 @@
import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/nano/nano.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_keys_form.dart';
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_form.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
import 'package:cw_core/nano_account_info_response.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:keyboard_actions/keyboard_actions.dart';
import 'package:mobx/mobx.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:polyseed/polyseed.dart';
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_keys_form.dart';
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_form.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
class WalletRestorePage extends BasePage {
WalletRestorePage(this.walletRestoreViewModel)
@@ -48,27 +49,13 @@ class WalletRestorePage extends BasePage {
}
},
onSeedChange: (String seed) {
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
final hasHeight = walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey
.currentState!.restoreHeightController.text.isNotEmpty;
if (hasHeight) {
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
}
} else {
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
}
final isPolyseed =
walletRestoreViewModel.type == WalletType.monero && Polyseed.isValidSeed(seed);
_validateOnChange(isPolyseed: isPolyseed);
},
onLanguageChange: (_) {
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
final hasHeight = walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey
.currentState!.restoreHeightController.text.isNotEmpty;
if (hasHeight) {
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
}
} else {
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
}
onLanguageChange: (String language) {
final isPolyseed = language.startsWith("POLYSEED_");
_validateOnChange(isPolyseed: isPolyseed);
}));
break;
case WalletRestoreMode.keys:
@@ -163,7 +150,8 @@ class WalletRestorePage extends BasePage {
color: Theme.of(context).colorScheme.background,
child: Center(
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
constraints:
BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
@@ -219,8 +207,8 @@ class WalletRestorePage extends BasePage {
const SizedBox(height: 25),
GestureDetector(
onTap: () {
Navigator.of(context)
.pushNamed(Routes.advancedPrivacySettings, arguments: walletRestoreViewModel.type);
Navigator.of(context).pushNamed(Routes.advancedPrivacySettings,
arguments: walletRestoreViewModel.type);
},
child: Text(S.of(context).advanced_privacy_settings),
),
@@ -235,9 +223,26 @@ class WalletRestorePage extends BasePage {
);
}
void _validateOnChange({bool isPolyseed = false}) {
if (!isPolyseed && walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
final hasHeight = walletRestoreFromSeedFormKey
.currentState?.blockchainHeightKey.currentState?.restoreHeightController.text.isNotEmpty;
if (hasHeight == true) {
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
}
} else {
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
}
}
bool _isValidSeed() {
final seedWords =
walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.text.split(' ');
final seedPhrase =
walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.text;
if (walletRestoreViewModel.type == WalletType.monero && Polyseed.isValidSeed(seedPhrase))
return true;
final seedWords = seedPhrase.split(' ');
if ((walletRestoreViewModel.type == WalletType.monero ||
walletRestoreViewModel.type == WalletType.haven) &&
@@ -282,7 +287,8 @@ class WalletRestorePage extends BasePage {
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
credentials['height'] =
walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey.currentState!.height;
walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey.currentState?.height ??
-1;
}
credentials['name'] =
@@ -1,95 +0,0 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/src/widgets/seed_language_selector.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
class SeedLanguage extends BasePage {
SeedLanguage({required this.onConfirm});
final Function(BuildContext, String) onConfirm;
final walletNameImage = Image.asset('assets/images/wallet_name.png');
final walletNameLightImage =
Image.asset('assets/images/wallet_name_light.png');
@override
String get title => S.current.wallet_list_restore_wallet;
@override
Widget body(BuildContext context) =>
SeedLanguageForm(
onConfirm: onConfirm,
walletImage: currentTheme.type == ThemeType.dark
? walletNameImage : walletNameLightImage);
}
class SeedLanguageForm extends StatefulWidget {
SeedLanguageForm({required this.onConfirm, required this.walletImage});
final Function(BuildContext, String) onConfirm;
final Image walletImage;
@override
SeedLanguageFormState createState() => SeedLanguageFormState();
}
class SeedLanguageFormState extends State<SeedLanguageForm> {
static const aspectRatioImage = 1.22;
final _languageSelectorKey = GlobalKey<SeedLanguageSelectorState>();
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(top: 24),
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
content:
Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
Padding(
padding: EdgeInsets.only(left: 12, right: 12),
child: AspectRatio(
aspectRatio: aspectRatioImage,
child: FittedBox(child: widget.walletImage,
fit: BoxFit.fill)),
),
Padding(
padding: EdgeInsets.only(top: 40),
child: Text(
S.of(context).seed_language_choose,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w500,
color:
Theme.of(context).extension<CakeTextTheme>()!.titleColor),
),
),
Padding(
padding: EdgeInsets.only(top: 24),
child: SeedLanguageSelector(
key: _languageSelectorKey,
initialSelected: defaultSeedLanguage),
)
]),
bottomSectionPadding:
EdgeInsets.only(left: 24, right: 24, bottom: 24),
bottomSection: Observer(
builder: (context) {
return PrimaryButton(
onPressed: () => widget.onConfirm(
context, _languageSelectorKey.currentState!.selected),
text: S.of(context).seed_language_next,
color: Colors.green,
textColor: Colors.white);
},
)),
);
}
}
@@ -1,82 +0,0 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:cake_wallet/generated/i18n.dart';
List<Image> flagImages = [
Image.asset('assets/images/flags/usa.png'),
Image.asset('assets/images/flags/chn.png'),
Image.asset('assets/images/flags/nld.png'),
Image.asset('assets/images/flags/deu.png'),
Image.asset('assets/images/flags/jpn.png'),
Image.asset('assets/images/flags/prt.png'),
Image.asset('assets/images/flags/rus.png'),
Image.asset('assets/images/flags/esp.png'),
Image.asset('assets/images/flags/fra.png'),
Image.asset('assets/images/flags/ita.png'),
];
const List<String> languageCodes = [
'Eng',
'Chi',
'Ned',
'Ger',
'Jap',
'Por',
'Rus',
'Esp',
'Fre',
'Ita',
];
const defaultSeedLanguage = 'English';
const List<String> seedLanguages = [
defaultSeedLanguage,
'Chinese (simplified)',
'Dutch',
'German',
'Japanese',
'Portuguese',
'Russian',
'Spanish',
'French',
'Italian',
];
enum Places { topLeft, topRight, bottomLeft, bottomRight, inside }
class SeedLanguagePicker extends StatefulWidget {
SeedLanguagePicker({Key? key, this.selected = defaultSeedLanguage, required this.onItemSelected})
: super(key: key);
final String selected;
final Function(String) onItemSelected;
@override
SeedLanguagePickerState createState() =>
SeedLanguagePickerState(selected: selected, onItemSelected: onItemSelected);
}
class SeedLanguagePickerState extends State<SeedLanguagePicker> {
SeedLanguagePickerState({required this.selected, required this.onItemSelected});
final String selected;
final Function(String) onItemSelected;
@override
Widget build(BuildContext context) {
return Picker(
selectedAtIndex: seedLanguages.indexOf(selected),
items: seedLanguages,
images: flagImages,
isGridView: true,
title: S.of(context).seed_choose,
hintText: S.of(context).seed_choose,
matchingCriteria: (String language, String searchText) {
return language.toLowerCase().contains(searchText);
},
onItemSelected: onItemSelected,
);
}
}
+93
View File
@@ -0,0 +1,93 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/entities/seed_type.dart';
class SeedLanguagePickerOption {
SeedLanguagePickerOption(this.name, this.nameLocalized, this.image, this.supportedSeedTypes);
final String name;
final String nameLocalized;
final Image image;
final List<SeedType> supportedSeedTypes;
}
final List<SeedLanguagePickerOption> seedLanguages = [
SeedLanguagePickerOption('English', S.current.seed_language_english,
Image.asset('assets/images/flags/usa.png'), [SeedType.legacy, SeedType.polyseed]),
SeedLanguagePickerOption('Chinese (simplified)', S.current.seed_language_chinese,
Image.asset('assets/images/flags/chn.png'), [SeedType.legacy, SeedType.polyseed]),
SeedLanguagePickerOption('Chinese (Traditional)', S.current.seed_language_chinese_traditional,
Image.asset('assets/images/flags/chn.png'), [SeedType.polyseed]),
SeedLanguagePickerOption('Dutch', S.current.seed_language_dutch,
Image.asset('assets/images/flags/nld.png'), [SeedType.legacy]),
SeedLanguagePickerOption('German', S.current.seed_language_german,
Image.asset('assets/images/flags/deu.png'), [SeedType.legacy]),
SeedLanguagePickerOption('Japanese', S.current.seed_language_japanese,
Image.asset('assets/images/flags/jpn.png'), [SeedType.legacy, SeedType.polyseed]),
SeedLanguagePickerOption('Korean', S.current.seed_language_korean,
Image.asset('assets/images/flags/kor.png'), [SeedType.polyseed]),
SeedLanguagePickerOption('Portuguese', S.current.seed_language_portuguese,
Image.asset('assets/images/flags/prt.png'), [SeedType.legacy, SeedType.polyseed]),
SeedLanguagePickerOption('Russian', S.current.seed_language_russian,
Image.asset('assets/images/flags/rus.png'), [SeedType.legacy]),
SeedLanguagePickerOption('Czech', S.current.seed_language_czech,
Image.asset('assets/images/flags/czk.png'), [SeedType.polyseed]),
SeedLanguagePickerOption('Spanish', S.current.seed_language_spanish,
Image.asset('assets/images/flags/esp.png'), [SeedType.legacy, SeedType.polyseed]),
SeedLanguagePickerOption('French', S.current.seed_language_french,
Image.asset('assets/images/flags/fra.png'), [SeedType.legacy, SeedType.polyseed]),
SeedLanguagePickerOption('Italian', S.current.seed_language_italian,
Image.asset('assets/images/flags/ita.png'), [SeedType.legacy, SeedType.polyseed]),
];
const defaultSeedLanguage = 'English';
enum Places { topLeft, topRight, bottomLeft, bottomRight, inside }
class SeedLanguagePicker extends StatefulWidget {
SeedLanguagePicker(
{Key? key,
this.selected = defaultSeedLanguage,
this.seedType = SeedType.defaultSeedType,
required this.onItemSelected})
: super(key: key);
final SeedType seedType;
final String selected;
final Function(String) onItemSelected;
@override
SeedLanguagePickerState createState() => SeedLanguagePickerState(
selected: selected, onItemSelected: onItemSelected, seedType: seedType);
}
class SeedLanguagePickerState extends State<SeedLanguagePicker> {
SeedLanguagePickerState(
{required this.selected, required this.onItemSelected, required this.seedType});
final SeedType seedType;
final String selected;
final Function(String) onItemSelected;
@override
Widget build(BuildContext context) {
final availableSeedLanguages = seedLanguages
.where((SeedLanguagePickerOption e) => e.supportedSeedTypes.contains(seedType));
return Picker(
selectedAtIndex: availableSeedLanguages.map((e) => e.name).toList().indexOf(selected),
items: availableSeedLanguages.map((e) => e.name).toList(),
images: availableSeedLanguages.map((e) => e.image).toList(),
isGridView: true,
title: S.of(context).seed_choose,
hintText: S.of(context).seed_choose,
matchingCriteria: (String language, String searchText) {
return language.toLowerCase().contains(searchText);
},
onItemSelected: onItemSelected,
);
}
}
+7 -17
View File
@@ -1,14 +1,15 @@
import 'package:cake_wallet/entities/seed_type.dart';
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
class SeedLanguageSelector extends StatefulWidget {
SeedLanguageSelector({Key? key, required this.initialSelected})
SeedLanguageSelector({Key? key, required this.initialSelected, this.seedType = SeedType.defaultSeedType})
: super(key: key);
final String initialSelected;
final SeedType seedType;
@override
SeedLanguageSelectorState createState() =>
@@ -18,30 +19,19 @@ class SeedLanguageSelector extends StatefulWidget {
class SeedLanguageSelectorState extends State<SeedLanguageSelector> {
SeedLanguageSelectorState({required this.selected});
final seedLocales = [
S.current.seed_language_english,
S.current.seed_language_chinese,
S.current.seed_language_dutch,
S.current.seed_language_german,
S.current.seed_language_japanese,
S.current.seed_language_portuguese,
S.current.seed_language_russian,
S.current.seed_language_spanish,
S.current.seed_language_french,
S.current.seed_language_italian,
];
String selected;
@override
Widget build(BuildContext context) {
return SelectButton(
image: null,
text: seedLocales[seedLanguages.indexOf(selected)],
text: seedLanguages.firstWhere((e) => e.name == selected).nameLocalized,
onTap: () async {
await showPopUp<String>(
context: context,
builder: (_) => SeedLanguagePicker(
selected: this.selected,
seedType: widget.seedType,
onItemSelected: (String selected) =>
setState(() => this.selected = selected)));
},