Merge branch 'main' into CW-529-Modify-2FA-introduction-screens

This commit is contained in:
Serhii
2023-12-13 14:44:38 +02:00
192 changed files with 4245 additions and 1139 deletions
+58 -24
View File
@@ -1,18 +1,26 @@
import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart';
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/entities/buy_provider_types.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/option_tile.dart';
import 'package:cake_wallet/themes/extensions/option_tile_theme.dart';
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:flutter/material.dart';
class BuyOptionsPage extends BasePage {
BuyOptionsPage(this.dashboardViewModel);
final DashboardViewModel dashboardViewModel;
final iconDarkRobinhood = 'assets/images/robinhood_dark.png';
final iconLightRobinhood = 'assets/images/robinhood_light.png';
final iconDarkOnramper = 'assets/images/onramper_dark.png';
final iconLightOnramper = 'assets/images/onramper_light.png';
final iconDarkDFX = 'assets/images/dfx_dark.png';
final iconLightDFX = 'assets/images/dfx_light.png';
@override
String get title => S.current.buy;
@@ -22,11 +30,19 @@ class BuyOptionsPage extends BasePage {
@override
Widget body(BuildContext context) {
final isLightMode = Theme.of(context).extension<OptionTileTheme>()?.useDarkImage ?? false;
final iconRobinhood =
Image.asset(isLightMode ? iconLightRobinhood : iconDarkRobinhood, height: 40, width: 40);
final iconOnramper =
Image.asset(isLightMode ? iconLightOnramper : iconDarkOnramper, height: 40, width: 40);
final isLightMode =
Theme.of(context).extension<OptionTileTheme>()?.useDarkImage ?? false;
final iconRobinhood = Image.asset(
isLightMode ? iconLightRobinhood : iconDarkRobinhood,
height: 40,
width: 40);
final iconOnramper = Image.asset(
isLightMode ? iconLightOnramper : iconDarkOnramper,
height: 40,
width: 40);
final iconDFX = Image.asset(isLightMode ? iconLightDFX : iconDarkDFX,
height: 40, width: 40);
final availableProviders = dashboardViewModel.availableProviders;
return Container(
child: Center(
@@ -34,26 +50,42 @@ class BuyOptionsPage extends BasePage {
constraints: BoxConstraints(maxWidth: 330),
child: Column(
children: [
Padding(
padding: EdgeInsets.only(top: 24),
child: OptionTile(
image: iconOnramper,
title: "Onramper",
description: S.of(context).onramper_option_description,
onPressed: () async =>
await getIt.get<OnRamperBuyProvider>().launchProvider(context),
if (availableProviders.contains(BuyProviderType.Onramper))
Padding(
padding: EdgeInsets.only(top: 24),
child: OptionTile(
image: iconOnramper,
title: "Onramper",
description: S.of(context).onramper_option_description,
onPressed: () async => await getIt
.get<OnRamperBuyProvider>()
.launchProvider(context),
),
),
),
Padding(
padding: EdgeInsets.only(top: 24),
child: OptionTile(
image: iconRobinhood,
title: "Robinhood Connect",
description: S.of(context).robinhood_option_description,
onPressed: () async =>
await getIt.get<RobinhoodBuyProvider>().launchProvider(context),
if (availableProviders.contains(BuyProviderType.Robinhood))
Padding(
padding: EdgeInsets.only(top: 24),
child: OptionTile(
image: iconRobinhood,
title: "Robinhood Connect",
description: S.of(context).robinhood_option_description,
onPressed: () async => await getIt
.get<RobinhoodBuyProvider>()
.launchProvider(context),
),
),
if (availableProviders.contains(BuyProviderType.DFX))
Padding(
padding: EdgeInsets.only(top: 24),
child: OptionTile(
image: iconDFX,
title: "DFX Connect",
description: S.of(context).dfx_option_description,
onPressed: () async => await getIt
.get<DFXBuyProvider>()
.launchProvider(context),
),
),
),
Spacer(),
Padding(
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
@@ -63,7 +95,9 @@ class BuyOptionsPage extends BasePage {
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.normal,
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
color: Theme.of(context)
.extension<TransactionTradeTheme>()!
.detailsTitlesColor,
),
),
),
@@ -191,7 +191,10 @@ class _DashboardPageView extends BasePage {
radius: 6.0,
dotWidth: 6.0,
dotHeight: 6.0,
dotColor: Theme.of(context).indicatorColor,
dotColor: Theme.of(context)
.extension<DashboardPageTheme>()!
.indicatorDotTheme
.indicatorColor,
activeDotColor: Theme.of(context)
.extension<DashboardPageTheme>()!
.indicatorDotTheme
@@ -33,6 +33,7 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
final litecoinIcon = Image.asset('assets/images/litecoin_icon.png', height: 24, width: 24);
final havenIcon = Image.asset('assets/images/haven_logo.png', height: 24, width: 24);
final ethereumIcon = Image.asset('assets/images/eth_icon.png', height: 24, width: 24);
final polygonIcon = Image.asset('assets/images/matic_icon.png', height: 24, width: 24);
final bitcoinCashIcon = Image.asset('assets/images/bch_icon.png', height: 24, width: 24);
final nanoIcon = Image.asset('assets/images/nano_icon.png', height: 24, width: 24);
final bananoIcon = Image.asset('assets/images/nano_icon.png', height: 24, width: 24);
@@ -150,6 +151,8 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
return nanoIcon;
case WalletType.banano:
return bananoIcon;
case WalletType.polygon:
return polygonIcon;
default:
return nonWalletTypeIcon;
}
@@ -1,5 +1,6 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/dashboard/pages/nft_listing_page.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/home_screen_account_widget.dart';
@@ -13,7 +14,6 @@ import 'package:cake_wallet/utils/feature_flag.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
@@ -32,12 +32,12 @@ class BalancePage extends StatelessWidget {
Widget build(BuildContext context) {
return Observer(
builder: (context) {
final isEthereumWallet = dashboardViewModel.type == WalletType.ethereum;
final isEVMCompatible = isEVMCompatibleChain(dashboardViewModel.type);
return DefaultTabController(
length: isEthereumWallet ? 2 : 1,
length: isEVMCompatible ? 2 : 1,
child: Column(
children: [
if (isEthereumWallet)
if (isEVMCompatible)
Align(
alignment: Alignment.centerLeft,
child: Padding(
@@ -66,7 +66,7 @@ class BalancePage extends StatelessWidget {
physics: NeverScrollableScrollPhysics(),
children: [
CryptoBalanceWidget(dashboardViewModel: dashboardViewModel),
if (isEthereumWallet) NFTListingPage(nftViewModel: nftViewModel)
if (isEVMCompatible) NFTListingPage(nftViewModel: nftViewModel)
],
),
),
@@ -32,7 +32,8 @@ class MenuWidgetState extends State<MenuWidget> {
this.ethereumIcon = Image.asset('assets/images/eth_icon.png'),
this.nanoIcon = Image.asset('assets/images/nano_icon.png'),
this.bananoIcon = Image.asset('assets/images/nano_icon.png'),
this.bitcoinCashIcon = Image.asset('assets/images/bch_icon.png');
this.bitcoinCashIcon = Image.asset('assets/images/bch_icon.png'),
this.polygonIcon = Image.asset('assets/images/matic_icon.png');
final largeScreen = 731;
@@ -54,6 +55,8 @@ class MenuWidgetState extends State<MenuWidget> {
Image bitcoinCashIcon;
Image nanoIcon;
Image bananoIcon;
Image polygonIcon;
@override
void initState() {
@@ -219,6 +222,8 @@ class MenuWidgetState extends State<MenuWidget> {
return nanoIcon;
case WalletType.banano:
return bananoIcon;
case WalletType.polygon:
return polygonIcon;
default:
throw Exception('No icon for ${type.toString()}');
}
@@ -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';
@@ -8,6 +9,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.
import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart';
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
import 'package:cake_wallet/view_model/seed_type_view_model.dart';
import 'package:cake_wallet/view_model/settings/choices_list_item.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter/material.dart';
@@ -17,25 +19,30 @@ import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
class AdvancedPrivacySettingsPage extends BasePage {
AdvancedPrivacySettingsPage(this.advancedPrivacySettingsViewModel, this.nodeViewModel);
AdvancedPrivacySettingsPage(
this.advancedPrivacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel);
final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel;
final NodeCreateOrEditViewModel nodeViewModel;
final SeedTypeViewModel seedTypeViewModel;
@override
String get title => S.current.privacy_settings;
@override
Widget body(BuildContext context) =>
AdvancedPrivacySettingsBody(advancedPrivacySettingsViewModel, nodeViewModel);
Widget body(BuildContext context) => AdvancedPrivacySettingsBody(
advancedPrivacySettingsViewModel, nodeViewModel, seedTypeViewModel);
}
class AdvancedPrivacySettingsBody extends StatefulWidget {
const AdvancedPrivacySettingsBody(this.privacySettingsViewModel, this.nodeViewModel, {Key? key})
const AdvancedPrivacySettingsBody(
this.privacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel,
{Key? key})
: super(key: key);
final AdvancedPrivacySettingsViewModel privacySettingsViewModel;
final NodeCreateOrEditViewModel nodeViewModel;
final SeedTypeViewModel seedTypeViewModel;
@override
_AdvancedPrivacySettingsBodyState createState() => _AdvancedPrivacySettingsBodyState();
@@ -58,7 +65,7 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
Observer(builder: (_) {
return SettingsChoicesCell(
ChoicesListItem<FiatApiMode>(
title: S.current.disable_fiat,
title: S.current.fiat_api,
items: FiatApiMode.all,
selectedItem: widget.privacySettingsViewModel.fiatApiMode,
onItemSelected: (FiatApiMode mode) =>
@@ -97,16 +104,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.seedTypeViewModel.moneroSeedType,
onItemSelected: widget.seedTypeViewModel.setMoneroSeedType,
),
);
}),
],
),
bottomSectionPadding: EdgeInsets.all(24),
+64 -24
View File
@@ -1,10 +1,13 @@
import 'package:cake_wallet/entities/generate_name.dart';
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
import 'package:cake_wallet/src/widgets/picker.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/main.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/themes/theme_base.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/seed_type_view_model.dart';
import 'package:mobx/mobx.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter/material.dart';
@@ -14,17 +17,19 @@ 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';
class NewWalletPage extends BasePage {
NewWalletPage(this._walletNewVM);
NewWalletPage(this._walletNewVM, this._seedTypeViewModel);
final WalletNewVM _walletNewVM;
final SeedTypeViewModel _seedTypeViewModel;
final walletNameImage = Image.asset('assets/images/wallet_name.png');
@@ -35,14 +40,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, _seedTypeViewModel);
}
class WalletNameForm extends StatefulWidget {
WalletNameForm(this._walletNewVM, this.walletImage);
WalletNameForm(this._walletNewVM, this.walletImage, this._seedTypeViewModel);
final WalletNewVM _walletNewVM;
final Image walletImage;
final SeedTypeViewModel _seedTypeViewModel;
@override
_WalletNameFormState createState() => _WalletNameFormState(_walletNewVM);
@@ -84,6 +90,8 @@ class _WalletNameFormState extends State<WalletNameForm> {
});
}
});
_setSeedType(SeedType.defaultSeedType);
super.initState();
}
@@ -125,15 +133,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 +173,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,
),
),
),
@@ -172,22 +187,40 @@ class _WalletNameFormState extends State<WalletNameForm> {
),
),
),
if (_walletNewVM.hasLanguageSelector) ...[
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),
if (_walletNewVM.hasSeedType) ...[
Observer(
builder: (BuildContext build) => Padding(
padding: EdgeInsets.only(top: 24),
child: SelectButton(
text: widget._seedTypeViewModel.moneroSeedType.title,
onTap: () async {
await showPopUp<void>(
context: context,
builder: (_) => Picker(
items: SeedType.all,
selectedAtIndex: isPolyseed ? 1 : 0,
onItemSelected: _setSeedType,
isSeparated: false,
),
);
},
),
),
),
],
Observer(
builder: (BuildContext build) => Padding(
padding: EdgeInsets.only(top: 10),
child: SeedLanguageSelector(
key: _languageSelectorKey,
initialSelected: defaultSeedLanguage,
seedType: _walletNewVM.hasSeedType
? widget._seedTypeViewModel.moneroSeedType
: SeedType.legacy,
),
),
),
Padding(
padding: EdgeInsets.only(top: 24),
child: SeedLanguageSelector(
key: _languageSelectorKey, initialSelected: defaultSeedLanguage),
)
]
],
@@ -215,7 +248,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
Navigator.of(context)
.pushNamed(Routes.advancedPrivacySettings, arguments: _walletNewVM.type);
},
child: Text(S.of(context).advanced_privacy_settings),
child: Text(S.of(context).advanced_settings),
),
],
)),
@@ -239,8 +272,15 @@ class _WalletNameFormState extends State<WalletNameForm> {
} else {
_walletNewVM.create(
options: _walletNewVM.hasLanguageSelector
? _languageSelectorKey.currentState!.selected
? [_languageSelectorKey.currentState!.selected, isPolyseed]
: null);
}
}
bool get isPolyseed => widget._seedTypeViewModel.moneroSeedType == SeedType.polyseed;
void _setSeedType(SeedType item) {
widget._seedTypeViewModel.setMoneroSeedType(item);
_languageSelectorKey.currentState?.selected = defaultSeedLanguage; // Reset Seed language
}
}
@@ -1,5 +1,6 @@
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/currency.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -23,6 +24,13 @@ class CurrencyInputField extends StatelessWidget {
final TextEditingController controller;
final bool isLight;
String get _currencyName {
if (selectedCurrency is CryptoCurrency) {
return (selectedCurrency as CryptoCurrency).title.toUpperCase();
}
return selectedCurrency.name.toUpperCase();
}
@override
Widget build(BuildContext context) {
final arrowBottomPurple = Image.asset(
@@ -74,7 +82,7 @@ class CurrencyInputField extends StatelessWidget {
child: arrowBottomPurple,
),
Text(
selectedCurrency.name.toUpperCase(),
_currencyName,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,
@@ -83,7 +91,7 @@ class CurrencyInputField extends StatelessWidget {
),
if (selectedCurrency.tag != null)
Padding(
padding: const EdgeInsets.only(right: 3.0),
padding: const EdgeInsets.symmetric(horizontal: 3.0),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
@@ -133,7 +133,7 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> {
widget.walletRestoreViewModel.type == WalletType.banano;
return AddressTextField(
controller: privateKeyController,
placeholder: nanoBased ? S.of(context).seed_key : S.of(context).private_key,
placeholder: nanoBased ? S.of(context).seed_hex_form : S.of(context).private_key,
options: [AddressTextFieldOption.paste],
buttonColor: Theme.of(context).hintColor,
onPushPasteButton: (_) {
@@ -1,17 +1,19 @@
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:cake_wallet/view_model/seed_type_view_model.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:mobx/mobx.dart';
import 'package:polyseed/polyseed.dart';
class WalletRestoreFromSeedForm extends StatefulWidget {
WalletRestoreFromSeedForm(
@@ -19,6 +21,7 @@ class WalletRestoreFromSeedForm extends StatefulWidget {
required this.displayLanguageSelector,
required this.displayBlockHeightSelector,
required this.type,
required this.seedTypeViewModel,
this.blockHeightFocusNode,
this.onHeightOrDateEntered,
this.onSeedChange,
@@ -28,14 +31,14 @@ class WalletRestoreFromSeedForm extends StatefulWidget {
final WalletType type;
final bool displayLanguageSelector;
final bool displayBlockHeightSelector;
final SeedTypeViewModel seedTypeViewModel;
final FocusNode? blockHeightFocusNode;
final Function(bool)? onHeightOrDateEntered;
final void Function(String)? onSeedChange;
final void Function(String)? onLanguageChange;
@override
WalletRestoreFromSeedFormState createState() =>
WalletRestoreFromSeedFormState('English');
WalletRestoreFromSeedFormState createState() => WalletRestoreFromSeedFormState('English');
}
class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
@@ -44,104 +47,189 @@ 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;
late ReactionDisposer moneroSeedTypeReaction;
String language;
@override
void initState() {
_setSeedType(widget.seedTypeViewModel.moneroSeedType);
_setLanguageLabel(language);
moneroSeedTypeReaction =
reaction((_) => widget.seedTypeViewModel.moneroSeedType, (SeedType item) {
_setSeedType(item);
_changeLanguage('English');
});
super.initState();
}
@override
void dispose() {
super.dispose();
moneroSeedTypeReaction();
}
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,
suffixIcon: expandIcon,
),
),
),
),
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,
padding: EdgeInsets.only(top: 20.0),
child: IgnorePointer(
child: BaseTextFormField(
controller: languageController,
enableInteractiveSelection: false,
readOnly: true)))),
if (widget.displayBlockHeightSelector)
child: Container(
color: Colors.transparent,
padding: EdgeInsets.only(top: 20.0),
child: IgnorePointer(
child: BaseTextFormField(
controller: languageController,
enableInteractiveSelection: false,
readOnly: true,
suffixIcon: expandIcon,
),
),
),
),
if (!isPolyseed && widget.displayBlockHeightSelector)
BlockchainHeightWidget(
focusNode: widget.blockHeightFocusNode,
key: blockchainHeightKey,
onHeightOrDateEntered: widget.onHeightOrDateEntered,
hasDatePicker: widget.type == WalletType.monero)
hasDatePicker: widget.type == WalletType.monero),
]));
}
bool get isPolyseed => widget.seedTypeViewModel.moneroSeedType == SeedType.polyseed;
Widget get expandIcon => Container(
padding: EdgeInsets.all(18),
width: 24,
height: 24,
child: Image.asset(
'assets/images/arrow_bottom_purple_icon.png',
height: 8,
color: Theme.of(context).hintColor,
),
);
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');
widget.seedTypeViewModel.setMoneroSeedType(item);
}
void _setSeedType(SeedType item) {
seedTypeController.text = item.toString();
}
}
@@ -1,32 +1,34 @@
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/seed_type_view_model.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)
WalletRestorePage(this.walletRestoreViewModel, this.seedTypeViewModel)
: walletRestoreFromSeedFormKey = GlobalKey<WalletRestoreFromSeedFormState>(),
walletRestoreFromKeysFormKey = GlobalKey<WalletRestoreFromKeysFromState>(),
_pages = [],
@@ -36,6 +38,7 @@ class WalletRestorePage extends BasePage {
switch (mode) {
case WalletRestoreMode.seed:
_pages.add(WalletRestoreFromSeedForm(
seedTypeViewModel: seedTypeViewModel,
displayBlockHeightSelector:
walletRestoreViewModel.hasBlockchainHeightLanguageSelector,
displayLanguageSelector: walletRestoreViewModel.hasSeedLanguageSelector,
@@ -48,27 +51,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:
@@ -104,6 +93,7 @@ class WalletRestorePage extends BasePage {
));
final WalletRestoreViewModel walletRestoreViewModel;
final SeedTypeViewModel seedTypeViewModel;
final PageController _controller;
final List<Widget> _pages;
final GlobalKey<WalletRestoreFromSeedFormState> walletRestoreFromSeedFormKey;
@@ -163,7 +153,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,10 +210,10 @@ 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),
child: Text(S.of(context).advanced_settings),
),
],
),
@@ -235,9 +226,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 +290,8 @@ class WalletRestorePage extends BasePage {
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
credentials['height'] =
walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey.currentState!.height;
walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey.currentState?.height ??
-1;
}
credentials['name'] =
+4 -4
View File
@@ -2,9 +2,9 @@ import 'dart:async';
import 'package:cake_wallet/core/auth_service.dart';
import 'package:cake_wallet/core/totp_request_details.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart';
import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/utils/payment_request.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
@@ -169,7 +169,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
);
launchUri = null;
} else if (isWalletConnectLink) {
if (widget.appStore.wallet!.type == WalletType.ethereum) {
if (isEVMCompatibleChain(widget.appStore.wallet!.type)) {
widget.navigatorKey.currentState?.pushNamed(
Routes.walletConnectConnectionsListing,
arguments: launchUri,
@@ -179,7 +179,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
_nonETHWalletErrorToast(S.current.switchToETHWallet);
}
}
launchUri = null;
return WillPopScope(
onWillPop: () async => false,
@@ -205,7 +205,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
String? _getRouteToGo() {
if (isWalletConnectLink) {
if (widget.appStore.wallet!.type != WalletType.ethereum) {
if (isEVMCompatibleChain(widget.appStore.wallet!.type)) {
_nonETHWalletErrorToast(S.current.switchToETHWallet);
return null;
}
@@ -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,
);
}
}
@@ -1,4 +1,5 @@
import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
@@ -8,7 +9,6 @@ import 'package:cake_wallet/utils/feature_flag.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/generated/i18n.dart';
@@ -85,7 +85,7 @@ class ConnectionSyncPage extends BasePage {
);
},
),
if (dashboardViewModel.wallet.type == WalletType.ethereum) ...[
if (isEVMCompatibleChain(dashboardViewModel.wallet.type)) ...[
WalletConnectTile(
onTap: () => Navigator.of(context).pushNamed(Routes.walletConnectConnectionsListing),
),
@@ -101,6 +101,7 @@ class ConnectionSyncPage extends BasePage {
);
}
Future<void> _presentReconnectAlert(BuildContext context) async {
await showPopUp<void>(
context: context,
@@ -1,5 +1,3 @@
import 'package:cake_wallet/buy/buy_provider.dart';
import 'package:cake_wallet/entities/buy_provider_types.dart';
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart';
@@ -42,9 +40,10 @@ class OtherSettingsPage extends BasePage {
handler: (BuildContext context) =>
Navigator.of(context).pushNamed(Routes.changeRep),
),
if(_otherSettingsViewModel.isEnabledBuyAction)
SettingsPickerCell(
title: S.current.default_buy_provider,
items: BuyProviderType.values,
items: _otherSettingsViewModel.availableBuyProviders,
displayItem: _otherSettingsViewModel.getBuyProviderType,
selectedItem: _otherSettingsViewModel.buyProviderType,
onItemSelected: _otherSettingsViewModel.onBuyProviderTypeSelected,
@@ -87,6 +87,14 @@ class PrivacyPage extends BasePage {
onValueChange: (BuildContext _, bool value) {
_privacySettingsViewModel.setUseEtherscan(value);
}),
if (_privacySettingsViewModel.canUsePolygonScan)
SettingsSwitcherCell(
title: S.current.polygonscan_history,
value: _privacySettingsViewModel.usePolygonScan,
onValueChange: (BuildContext _, bool value) {
_privacySettingsViewModel.setUsePolygonScan(value);
},
),
SettingsCellWithArrow(
title: S.current.domain_looks_up,
handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage),
+33 -33
View File
@@ -4,7 +4,7 @@ import 'dart:io';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:flutter/material.dart';
import 'package:tor/tor.dart';
// import 'package:tor/tor.dart';
class TorPage extends BasePage {
final AppStore appStore;
@@ -40,44 +40,44 @@ class _TorPageBodyState extends State<TorPageBody> {
connecting = true; // Update flag
});
await Tor.init();
// Start the proxy
await Tor.instance.start();
// Toggle started flag.
setState(() {
torEnabled = Tor.instance.enabled; // Update flag
connecting = false;
});
final node = widget.appStore.settingsStore.getCurrentNode(widget.appStore.wallet!.type);
if (node.socksProxyAddress?.isEmpty ?? true) {
node.socksProxyAddress = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}";
}
widget.appStore.wallet!.connectToNode(node: node);
// await Tor.init();
//
// // Start the proxy
// await Tor.instance.start();
//
// // Toggle started flag.
// setState(() {
// torEnabled = Tor.instance.enabled; // Update flag
// connecting = false;
// });
//
// final node = widget.appStore.settingsStore.getCurrentNode(widget.appStore.wallet!.type);
// if (node.socksProxyAddress?.isEmpty ?? true) {
// node.socksProxyAddress = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}";
// }
// widget.appStore.wallet!.connectToNode(node: node);
print('Done awaiting; tor should be running');
}
Future<void> endTor() async {
// Start the proxy
Tor.instance.disable();
// Toggle started flag.
setState(() {
torEnabled = Tor.instance.enabled; // Update flag
});
print('Done awaiting; tor should be stopped');
}
@override
void initState() {
super.initState();
torEnabled = Tor.instance.enabled;
// // Start the proxy
// Tor.instance.disable();
//
// // Toggle started flag.
// setState(() {
// torEnabled = Tor.instance.enabled; // Update flag
// });
//
// print('Done awaiting; tor should be stopped');
}
//
// @override
// void initState() {
// super.initState();
//
// torEnabled = Tor.instance.enabled;
// }
@override
void dispose() {
@@ -57,6 +57,8 @@ class ChatwootWidgetState extends State<ChatwootWidget> {
return true;
}
Future<void> storeCookie(String value) async =>
await widget.secureStorage.write(key: COOKIE_KEY, value: value);
Future<void> storeCookie(String value) async {
await widget.secureStorage.delete(key: COOKIE_KEY);
await widget.secureStorage.write(key: COOKIE_KEY, value: value);
}
}
@@ -31,6 +31,8 @@ class WalletConnectConnectionsView extends StatelessWidget {
final actualLinkList = launchUri.query.split("uri=");
if (actualLinkList.length <= 1) return;
final query = actualLinkList[1];
final uri = Uri.decodeComponent(query);
@@ -14,12 +14,14 @@ import 'connection_widget.dart';
class ConnectionRequestWidget extends StatefulWidget {
const ConnectionRequestWidget({
required this.wallet,
required this.chaindIdNamespace,
this.authRequest,
this.sessionProposal,
Key? key,
}) : super(key: key);
final Web3Wallet wallet;
final String chaindIdNamespace;
final AuthRequestModel? authRequest;
final SessionRequestModel? sessionProposal;
@@ -52,23 +54,26 @@ class _ConnectionRequestWidgetState extends State<ConnectionRequestWidget> {
return _ConnectionMetadataDisplayWidget(
metadata: metadata,
wallet: widget.wallet,
authRequest: widget.authRequest,
sessionProposal: widget.sessionProposal,
wallet: widget.wallet,
chaindIdNamespace: widget.chaindIdNamespace,
);
}
}
class _ConnectionMetadataDisplayWidget extends StatelessWidget {
const _ConnectionMetadataDisplayWidget({
required this.metadata,
required this.wallet,
this.authRequest,
required this.metadata,
required this.sessionProposal,
required this.chaindIdNamespace,
this.authRequest,
});
final ConnectionMetadata? metadata;
final Web3Wallet wallet;
final String chaindIdNamespace;
final AuthRequestModel? authRequest;
final SessionRequestModel? sessionProposal;
@@ -114,7 +119,11 @@ class _ConnectionMetadataDisplayWidget extends StatelessWidget {
const SizedBox(height: 8),
Visibility(
visible: authRequest != null,
child: _AuthRequestWidget(wallet: wallet, authRequest: authRequest),
child: _AuthRequestWidget(
wallet: wallet,
authRequest: authRequest,
chaindIdNamespace: chaindIdNamespace,
),
//If authRequest is null, sessionProposal is not null.
replacement: _SessionProposalWidget(sessionProposal: sessionProposal!),
@@ -126,16 +135,21 @@ class _ConnectionMetadataDisplayWidget extends StatelessWidget {
}
class _AuthRequestWidget extends StatelessWidget {
const _AuthRequestWidget({required this.wallet, this.authRequest});
const _AuthRequestWidget({
required this.wallet,
required this.chaindIdNamespace,
this.authRequest,
});
final Web3Wallet wallet;
final String chaindIdNamespace;
final AuthRequestModel? authRequest;
@override
Widget build(BuildContext context) {
final model = ConnectionModel(
text: wallet.formatAuthMessage(
iss: 'did:pkh:eip155:1:${authRequest!.iss}',
iss: 'did:pkh:$chaindIdNamespace:${authRequest!.iss}',
cacaoPayload: CacaoRequestPayload.fromPayloadParams(
authRequest!.request.payloadParams,
),
@@ -49,6 +49,7 @@ class WalletListBodyState extends State<WalletListBody> {
final ethereumIcon = Image.asset('assets/images/eth_icon.png', height: 24, width: 24);
final bitcoinCashIcon = Image.asset('assets/images/bch_icon.png', height: 24, width: 24);
final nanoIcon = Image.asset('assets/images/nano_icon.png', height: 24, width: 24);
final polygonIcon = Image.asset('assets/images/matic_icon.png', height: 24, width: 24);
final scrollController = ScrollController();
final double tileHeight = 60;
Flushbar<void>? _progressBar;
@@ -256,6 +257,8 @@ class WalletListBodyState extends State<WalletListBody> {
return bitcoinCashIcon;
case WalletType.nano:
return nanoIcon;
case WalletType.polygon:
return polygonIcon;
default:
return nonWalletTypeIcon;
}
+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,
);
}
}
+17 -24
View File
@@ -1,49 +1,42 @@
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/entities/seed_type.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';
import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:flutter/material.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() =>
SeedLanguageSelectorState(selected: initialSelected);
SeedLanguageSelectorState createState() => SeedLanguageSelectorState(selected: initialSelected);
}
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} (${S.of(context).seed_language})",
onTap: () async {
await showPopUp<String>(
context: context,
builder: (_) => SeedLanguagePicker(
selected: this.selected,
onItemSelected: (String selected) =>
setState(() => this.selected = selected)));
context: context,
builder: (_) => SeedLanguagePicker(
selected: this.selected,
seedType: widget.seedType,
onItemSelected: (String selected) => setState(() => this.selected = selected),
),
);
},
);
}