diff --git a/lib/di.dart b/lib/di.dart index c62dc9790..1febcd9e5 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -35,6 +35,7 @@ import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart'; import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart'; import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart'; +import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cake_wallet/core/backup_service.dart'; import 'package:cw_core/wallet_service.dart'; @@ -159,6 +160,7 @@ import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart'; import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart'; import 'package:cake_wallet/core/wallet_loading_service.dart'; +import 'package:cw_core/crypto_currency.dart'; final getIt = GetIt.instance; @@ -349,7 +351,7 @@ Future setup( onAuthenticationFinished: onAuthFinished, closable: closable ?? false)); - getIt.registerFactory(() => + getIt.registerFactory(() => BalancePage(dashboardViewModel: getIt.get(), settingsStore: getIt.get())); getIt.registerFactory(() => DashboardPage( balancePage: getIt.get(), walletViewModel: getIt.get(), addressListViewModel: getIt.get())); @@ -471,12 +473,11 @@ Future setup( (ContactRecord? contact, _) => ContactViewModel(_contactSource, contact: contact)); - getIt.registerFactory( - () => ContactListViewModel(_contactSource, _walletInfoSource)); + getIt.registerFactoryParam( + (CryptoCurrency? cur, _) => ContactListViewModel(_contactSource, _walletInfoSource, cur)); - getIt.registerFactoryParam( - (bool isEditable, _) => ContactListPage(getIt.get(), - isEditable: isEditable)); + getIt.registerFactoryParam((CryptoCurrency? cur, _) + => ContactListPage(getIt.get(param1: cur))); getIt.registerFactoryParam( (ContactRecord? contact, _) => @@ -498,8 +499,12 @@ Future setup( getIt.registerFactory(() => OtherSettingsPage(getIt.get())); - getIt.registerFactory(() => - NodeCreateOrEditViewModel(_nodeSource, getIt.get().wallet!)); + getIt.registerFactoryParam( + (WalletType? type, _) => NodeCreateOrEditViewModel( + _nodeSource, + type ?? getIt.get().wallet!.type, + getIt.get(), + )); getIt.registerFactory( () => NodeCreateOrEditPage(getIt.get())); @@ -698,7 +703,7 @@ Future setup( getIt.registerFactoryParam( (String qrData, bool isLight) => FullscreenQRPage(qrData: qrData, isLight: isLight,)); - + getIt.registerFactory(() => IoniaApi()); getIt.registerFactory(() => AnyPayApi()); @@ -718,7 +723,7 @@ Future setup( getIt.registerFactoryParam((double amount, merchant) { return IoniaMerchPurchaseViewModel( - ioniaAnyPayService: getIt.get(), + ioniaAnyPayService: getIt.get(), amount: amount, ioniaMerchant: merchant, sendViewModel: getIt.get() @@ -761,31 +766,31 @@ Future setup( ioniaService: getIt.get(), giftCard: giftCard); }); - + getIt.registerFactoryParam((List args, _) { final amount = args[0] as double; final merchant = args[1] as IoniaMerchant; final tip = args[2] as IoniaTip; - + return IoniaCustomTipViewModel(amount: amount, tip: tip, ioniaMerchant: merchant); }); - + getIt.registerFactoryParam((IoniaGiftCard giftCard, _) { return IoniaGiftCardDetailPage(getIt.get(param1: giftCard)); }); getIt.registerFactoryParam((List args, _){ final giftCard = args.first as IoniaGiftCard; - - return IoniaMoreOptionsPage(giftCard); + + return IoniaMoreOptionsPage(giftCard); }); getIt.registerFactoryParam((IoniaGiftCard giftCard, _) => IoniaCustomRedeemViewModel(giftCard)); getIt.registerFactoryParam((List args, _){ final giftCard = args.first as IoniaGiftCard; - - return IoniaCustomRedeemPage(getIt.get(param1: giftCard) ); + + return IoniaCustomRedeemPage(getIt.get(param1: giftCard) ); }); @@ -814,5 +819,8 @@ Future setup( (IoniaAnyPayPaymentInfo paymentInfo, AnyPayPaymentCommittedInfo committedInfo) => IoniaPaymentStatusPage(getIt.get(param1: paymentInfo, param2: committedInfo))); + getIt.registerFactoryParam((type, _) => + AdvancedPrivacySettingsViewModel(type, getIt.get())); + _isSetupFinished = true; } diff --git a/lib/main.dart b/lib/main.dart index e1fade7b4..11eee146b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -261,7 +261,7 @@ class AppState extends State with SingleTickerProviderStateMixin { final statusBarColor = Colors.transparent; final authenticationStore = getIt.get(); final initialRoute = - authenticationStore.state == AuthenticationState.denied + authenticationStore.state == AuthenticationState.uninitialized ? Routes.disclaimer : Routes.login; final currentTheme = settingsStore.currentTheme; diff --git a/lib/reactions/bootstrap.dart b/lib/reactions/bootstrap.dart index 8d9950e64..a40a17088 100644 --- a/lib/reactions/bootstrap.dart +++ b/lib/reactions/bootstrap.dart @@ -22,9 +22,9 @@ Future bootstrap(GlobalKey navigatorKey) async { final currentWalletName = getIt .get() .getString(PreferencesKey.currentWalletName); - authenticationStore.state = currentWalletName == null - ? AuthenticationState.denied - : AuthenticationState.installed; + if (currentWalletName != null) { + authenticationStore.state = AuthenticationState.installed; + } startAuthenticationStateChange(authenticationStore, navigatorKey); startCurrentWalletChangeReaction( diff --git a/lib/reactions/on_authentication_state_change.dart b/lib/reactions/on_authentication_state_change.dart index c91f5277e..edadf33b0 100644 --- a/lib/reactions/on_authentication_state_change.dart +++ b/lib/reactions/on_authentication_state_change.dart @@ -26,10 +26,5 @@ void startAuthenticationStateChange(AuthenticationStore authenticationStore, await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false); return; } - - if (state == AuthenticationState.denied) { - await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.welcome, (_) => false); - return; - } }); } diff --git a/lib/router.dart b/lib/router.dart index 4d3d61f5f..b59294428 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -15,6 +15,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dar import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_tip_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; +import 'package:cake_wallet/src/screens/new_wallet/advanced_privacy_settings_page.dart'; import 'package:cake_wallet/src/screens/order_details/order_details_page.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; @@ -25,6 +26,8 @@ import 'package:cake_wallet/src/screens/support/support_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.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:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; @@ -77,6 +80,7 @@ import 'package:cake_wallet/src/screens/ionia/ionia.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart'; import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart'; import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; +import 'package:cw_core/crypto_currency.dart'; late RouteSettings currentRouteSettings; @@ -317,11 +321,13 @@ Route createRoute(RouteSettings settings) { case Routes.addressBook: return MaterialPageRoute( - builder: (_) => getIt.get(param1: true)); + builder: (_) => + getIt.get()); case Routes.pickerAddressBook: + final selectedCurrency = settings.arguments as CryptoCurrency; return MaterialPageRoute( - builder: (_) => getIt.get(param1: false)); + builder: (_) => getIt.get(param1: selectedCurrency)); case Routes.addressBookAddContact: return CupertinoPageRoute( @@ -491,6 +497,15 @@ Route createRoute(RouteSettings settings) { case Routes.onramperPage: return CupertinoPageRoute(builder: (_) => getIt.get()); + case Routes.advancedPrivacySettings: + final type = settings.arguments as WalletType; + + return CupertinoPageRoute( + builder: (_) => AdvancedPrivacySettingsPage( + getIt.get(param1: type), + getIt.get(param1: type), + )); + default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/routes.dart b/lib/routes.dart index d738b13e8..5ea250310 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -81,4 +81,5 @@ class Routes { static const privacyPage = '/privacy_page'; static const displaySettingsPage = '/display_settings_page'; static const otherSettingsPage = '/other_settings_page'; + static const advancedPrivacySettings = '/advanced_privacy_settings'; } diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 7912472d8..7cd7a0157 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -9,24 +9,22 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; import 'package:cake_wallet/src/widgets/collapsible_standart_list.dart'; class ContactListPage extends BasePage { - ContactListPage(this.contactListViewModel, {this.isEditable = true}); + ContactListPage(this.contactListViewModel); final ContactListViewModel contactListViewModel; - final bool isEditable; @override String get title => S.current.address_book; @override Widget? trailing(BuildContext context) { - if (!isEditable) { + if (!contactListViewModel.isEditable) { return null; } @@ -60,11 +58,14 @@ class ContactListPage extends BasePage { @override Widget body(BuildContext context) { + return Container( padding: EdgeInsets.only(top: 20.0, bottom: 20.0), child: Observer( - builder: (_) { - return CollapsibleSectionList( + builder: (_) { + final contacts = contactListViewModel.contactsToShow; + final walletContacts = contactListViewModel.walletContactsToShow; + return CollapsibleSectionList( context: context, sectionCount: 2, themeColor: Theme.of(context).primaryTextTheme.headline6!.color!, @@ -82,35 +83,37 @@ class ContactListPage extends BasePage { child: Text(title, style: TextStyle(fontSize: 36))); }, itemCounter: (int sectionIndex) => sectionIndex == 0 - ? contactListViewModel.walletContacts.length - : contactListViewModel.contacts.length, + ? walletContacts.length + : contacts.length, itemBuilder: (_, sectionIndex, index) { if (sectionIndex == 0) { - final walletInfo = contactListViewModel.walletContacts[index]; + final walletInfo = walletContacts[index]; return generateRaw(context, walletInfo); } - final contact = contactListViewModel.contacts[index]; + final contact = contacts[index]; final content = generateRaw(context, contact); - return !isEditable - ? content - : Slidable( + return contactListViewModel.isEditable + ? Slidable( key: Key('${contact.key}'), endActionPane: _actionPane(context, contact), child: content, - ); + ) + : content; }, - ); - }, - )); + );}) + ); } Widget generateRaw(BuildContext context, ContactBase contact) { - final image = _getCurrencyImage(contact.type); + final image = contact.type.iconPath; + final currencyIcon = image != null ? Image.asset(image, height: 24, width: 24) + : const SizedBox(height: 24, width: 24); + return GestureDetector( onTap: () async { - if (!isEditable) { + if (!contactListViewModel.isEditable) { Navigator.of(context).pop(contact); return; } @@ -131,12 +134,10 @@ class ContactListPage extends BasePage { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, children: [ - image ?? Offstage(), + currencyIcon, Expanded( child: Padding( - padding: image != null - ? EdgeInsets.only(left: 12) - : EdgeInsets.only(left: 0), + padding: EdgeInsets.only(left: 12), child: Text( contact.name, style: TextStyle( @@ -152,69 +153,6 @@ class ContactListPage extends BasePage { ); } - Image? _getCurrencyImage(CryptoCurrency currency) { - Image? image; - - switch (currency) { - case CryptoCurrency.xmr: - image = - Image.asset('assets/images/monero_logo.png', height: 24, width: 24); - break; - case CryptoCurrency.ada: - image = Image.asset('assets/images/ada.png', height: 24, width: 24); - break; - case CryptoCurrency.bch: - image = Image.asset('assets/images/bch.png', height: 24, width: 24); - break; - case CryptoCurrency.bnb: - image = Image.asset('assets/images/bnb.png', height: 24, width: 24); - break; - case CryptoCurrency.btc: - image = Image.asset('assets/images/bitcoin.png', height: 24, width: 24); - break; - case CryptoCurrency.dai: - image = Image.asset('assets/images/dai.png', height: 24, width: 24); - break; - case CryptoCurrency.dash: - image = Image.asset('assets/images/dash.png', height: 24, width: 24); - break; - case CryptoCurrency.eos: - image = Image.asset('assets/images/eos.png', height: 24, width: 24); - break; - case CryptoCurrency.eth: - image = Image.asset('assets/images/eth.png', height: 24, width: 24); - break; - case CryptoCurrency.ltc: - image = - Image.asset('assets/images/litecoin.png', height: 24, width: 24); - break; - case CryptoCurrency.nano: - image = Image.asset('assets/images/nano.png', height: 24, width: 24); - break; - case CryptoCurrency.trx: - image = Image.asset('assets/images/trx.png', height: 24, width: 24); - break; - case CryptoCurrency.usdt: - image = Image.asset('assets/images/usdt.png', height: 24, width: 24); - break; - case CryptoCurrency.usdterc20: - image = Image.asset('assets/images/usdterc.png', height: 24, width: 24); - break; - case CryptoCurrency.xlm: - image = Image.asset('assets/images/xlm.png', height: 24, width: 24); - break; - case CryptoCurrency.xrp: - image = Image.asset('assets/images/xrp.png', height: 24, width: 24); - break; - case CryptoCurrency.xhv: - image = Image.asset('assets/images/haven_logo.png', height: 24, width: 24); - break; - default: - image = null; - } - return image; - } - Future showAlertDialog(BuildContext context) async { return await showPopUp( context: context, diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index 98843b1fb..40aa679a4 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -395,7 +395,8 @@ class ExchangeCardState extends State { buttonColor: widget.addressButtonsColor, validator: widget.addressTextFieldValidator, onPushPasteButton: widget.onPushPasteButton, - onPushAddressBookButton: widget.onPushAddressBookButton + onPushAddressBookButton: widget.onPushAddressBookButton, + selectedCurrency: _selectedCurrency ), ) diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart new file mode 100644 index 000000000..ff1c83f90 --- /dev/null +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -0,0 +1,104 @@ +import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.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:flutter_mobx/flutter_mobx.dart'; +import 'package:flutter/material.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'; + +class AdvancedPrivacySettingsPage extends BasePage { + AdvancedPrivacySettingsPage(this.advancedPrivacySettingsViewModel, this.nodeViewModel); + + final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel; + final NodeCreateOrEditViewModel nodeViewModel; + + @override + String get title => S.current.privacy_settings; + + @override + Widget body(BuildContext context) => + AdvancedPrivacySettingsBody(advancedPrivacySettingsViewModel, nodeViewModel); +} + +class AdvancedPrivacySettingsBody extends StatefulWidget { + const AdvancedPrivacySettingsBody(this.privacySettingsViewModel, this.nodeViewModel, {Key? key}) + : super(key: key); + + final AdvancedPrivacySettingsViewModel privacySettingsViewModel; + final NodeCreateOrEditViewModel nodeViewModel; + + @override + _AdvancedPrivacySettingsBodyState createState() => _AdvancedPrivacySettingsBodyState(); +} + +class _AdvancedPrivacySettingsBodyState extends State { + _AdvancedPrivacySettingsBodyState(); + + final _formKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 24), + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(bottom: 24), + content: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ...widget.privacySettingsViewModel.settings.map( + (item) => Observer( + builder: (_) => SettingsSwitcherCell( + title: item.title, + value: item.value(), + onValueChange: item.onValueChange, + ), + ), + ), + Observer( + builder: (_) { + if (widget.privacySettingsViewModel.addCustomNode) { + return Padding( + padding: EdgeInsets.only(left: 24, right: 24, top: 24), + child: NodeForm( + formKey: _formKey, + nodeViewModel: widget.nodeViewModel, + ), + ); + } + return const SizedBox(); + }, + ), + ], + ), + bottomSectionPadding: EdgeInsets.all(24), + bottomSection: Column( + children: [ + LoadingPrimaryButton( + onPressed: () { + widget.nodeViewModel.save(saveAsCurrent: true); + Navigator.pop(context); + }, + text: S.of(context).continue_text, + color: Theme.of(context).accentTextTheme.bodyText1!.color!, + textColor: Colors.white, + ), + const SizedBox(height: 25), + Padding( + padding: EdgeInsets.symmetric(horizontal: MediaQuery.of(context).size.width * 0.15), + child: Text( + S.of(context).settings_can_be_changed_later, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).accentTextTheme.headline2?.color, + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index cd08cfb61..9e0cd898c 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -200,18 +200,30 @@ class _WalletNameFormState extends State { ] ]), bottomSectionPadding: - EdgeInsets.only(left: 24, right: 24, bottom: 24), - bottomSection: Observer( - builder: (context) { - return LoadingPrimaryButton( - onPressed: _confirmForm, - text: S.of(context).seed_language_next, - color: Colors.green, - textColor: Colors.white, - isLoading: _walletNewVM.state is IsExecutingState, - isDisabled: _walletNewVM.name.isEmpty, - ); - }, + EdgeInsets.all(24), + bottomSection: Column( + children: [ + Observer( + builder: (context) { + return LoadingPrimaryButton( + onPressed: _confirmForm, + text: S.of(context).seed_language_next, + color: Colors.green, + textColor: Colors.white, + isLoading: _walletNewVM.state is IsExecutingState, + isDisabled: _walletNewVM.name.isEmpty, + ); + }, + ), + const SizedBox(height: 25), + GestureDetector( + onTap: () { + Navigator.of(context) + .pushNamed(Routes.advancedPrivacySettings, arguments: _walletNewVM.type); + }, + child: Text(S.of(context).advanced_privacy_settings), + ), + ], )), ); } diff --git a/lib/src/screens/nodes/node_create_or_edit_page.dart b/lib/src/screens/nodes/node_create_or_edit_page.dart index e84b6bdad..8173af2f0 100644 --- a/lib/src/screens/nodes/node_create_or_edit_page.dart +++ b/lib/src/screens/nodes/node_create_or_edit_page.dart @@ -1,16 +1,13 @@ import 'package:cake_wallet/core/execution_state.dart'; +import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/core/node_address_validator.dart'; -import 'package:cake_wallet/core/node_port_validator.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; -import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; @@ -108,91 +105,10 @@ class NodeCreateOrEditPage extends BasePage { padding: EdgeInsets.only(left: 24, right: 24), child: ScrollableWithBottomSection( contentPadding: EdgeInsets.only(bottom: 24.0), - content: Form( - key: _formKey, - child: Column( - children: [ - Row( - children: [ - Expanded( - child: BaseTextFormField( - controller: _addressController, - hintText: S.of(context).node_address, - validator: NodeAddressValidator(), - ) - ) - ], - ), - SizedBox(height: 10.0), - Row( - children: [ - Expanded( - child: BaseTextFormField( - controller: _portController, - hintText: S.of(context).node_port, - keyboardType: TextInputType.numberWithOptions( - signed: false, decimal: false), - validator: NodePortValidator(), - ) - ) - ], - ), - SizedBox(height: 10.0), - if (nodeCreateOrEditViewModel.hasAuthCredentials) ...[ - Row( - children: [ - Expanded( - child: BaseTextFormField( - controller: _loginController, - hintText: S.of(context).login, - ) - ) - ], - ), - SizedBox(height: 10.0), - Row( - children: [ - Expanded( - child: BaseTextFormField( - controller: _passwordController, - hintText: S.of(context).password, - ) - ) - ], - ), - Padding( - padding: EdgeInsets.only(top: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Observer( - builder: (_) => StandardCheckbox( - value: nodeCreateOrEditViewModel.useSSL, - onChanged: (value) => - nodeCreateOrEditViewModel.useSSL = value, - caption: S.of(context).use_ssl, - )) - ], - )), - Padding( - padding: EdgeInsets.only(top: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Observer( - builder: (_) => StandardCheckbox( - value: nodeCreateOrEditViewModel.trusted, - onChanged: (value) => - nodeCreateOrEditViewModel.trusted = value, - caption: S.of(context).trusted, - )) - ], - )), - ] - ], - )), + content: NodeForm( + formKey: _formKey, + nodeViewModel: nodeCreateOrEditViewModel, + ), bottomSectionPadding: EdgeInsets.only(bottom: 24), bottomSection: Observer( builder: (_) => Row( diff --git a/lib/src/screens/nodes/widgets/node_form.dart b/lib/src/screens/nodes/widgets/node_form.dart new file mode 100644 index 000000000..52851e063 --- /dev/null +++ b/lib/src/screens/nodes/widgets/node_form.dart @@ -0,0 +1,151 @@ +import 'package:cake_wallet/core/node_address_validator.dart'; +import 'package:cake_wallet/core/node_port_validator.dart'; +import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; +import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:mobx/mobx.dart'; + +class NodeForm extends StatelessWidget { + NodeForm({ + required this.nodeViewModel, + required this.formKey, + }) : _addressController = TextEditingController(), + _portController = TextEditingController(), + _loginController = TextEditingController(), + _passwordController = TextEditingController() { + reaction((_) => nodeViewModel.address, (String address) { + if (address != _addressController.text) { + _addressController.text = address; + } + }); + + reaction((_) => nodeViewModel.port, (String port) { + if (port != _portController.text) { + _portController.text = port; + } + }); + + if (nodeViewModel.hasAuthCredentials) { + reaction((_) => nodeViewModel.login, (String login) { + if (login != _loginController.text) { + _loginController.text = login; + } + }); + + reaction((_) => nodeViewModel.password, (String password) { + if (password != _passwordController.text) { + _passwordController.text = password; + } + }); + } + + _addressController + .addListener(() => nodeViewModel.address = _addressController.text); + _portController + .addListener(() => nodeViewModel.port = _portController.text); + _loginController + .addListener(() => nodeViewModel.login = _loginController.text); + _passwordController + .addListener(() => nodeViewModel.password = _passwordController.text); + } + + final NodeCreateOrEditViewModel nodeViewModel; + final GlobalKey formKey; + + final TextEditingController _addressController; + final TextEditingController _portController; + final TextEditingController _loginController; + final TextEditingController _passwordController; + + @override + Widget build(BuildContext context) { + return Form( + key: formKey, + child: Column( + children: [ + Row( + children: [ + Expanded( + child: BaseTextFormField( + controller: _addressController, + hintText: S.of(context).node_address, + validator: NodeAddressValidator(), + ), + ) + ], + ), + SizedBox(height: 10.0), + Row( + children: [ + Expanded( + child: BaseTextFormField( + controller: _portController, + hintText: S.of(context).node_port, + keyboardType: TextInputType.numberWithOptions( + signed: false, decimal: false), + validator: NodePortValidator(), + )) + ], + ), + SizedBox(height: 10.0), + if (nodeViewModel.hasAuthCredentials) ...[ + Row( + children: [ + Expanded( + child: BaseTextFormField( + controller: _loginController, + hintText: S.of(context).login, + )) + ], + ), + SizedBox(height: 10.0), + Row( + children: [ + Expanded( + child: BaseTextFormField( + controller: _passwordController, + hintText: S.of(context).password, + )) + ], + ), + Padding( + padding: EdgeInsets.only(top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Observer( + builder: (_) => StandardCheckbox( + value: nodeViewModel.useSSL, + onChanged: (value) => nodeViewModel.useSSL = value, + caption: S.of(context).use_ssl, + ), + ) + ], + ), + ), + Padding( + padding: EdgeInsets.only(top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Observer( + builder: (_) => StandardCheckbox( + value: nodeViewModel.trusted, + onChanged: (value) => nodeViewModel.trusted = value, + caption: S.of(context).trusted, + ), + ), + ], + ), + ), + ] + ], + ), + ); + } +} diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 261f5dde5..8f0d6675d 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -154,6 +154,7 @@ class SendCardState extends State await output.fetchParsedAddress(context); }, validator: validator, + selectedCurrency: sendViewModel.currency, ); }), if (output.isParsedAddress) Padding( diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart index 35bf3ed85..7e0727312 100644 --- a/lib/src/widgets/address_text_field.dart +++ b/lib/src/widgets/address_text_field.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/entities/qr_scanner.dart'; import 'package:cake_wallet/entities/contact_base.dart'; +import 'package:cw_core/crypto_currency.dart'; enum AddressTextFieldOption { paste, qrCode, addressBook } @@ -26,7 +27,8 @@ class AddressTextField extends StatelessWidget { this.hintStyle, this.validator, this.onPushPasteButton, - this.onPushAddressBookButton}); + this.onPushAddressBookButton, + this.selectedCurrency}); static const prefixIconWidth = 34.0; static const prefixIconHeight = 34.0; @@ -47,6 +49,7 @@ class AddressTextField extends StatelessWidget { final FocusNode? focusNode; final Function(BuildContext context)? onPushPasteButton; final Function(BuildContext context)? onPushAddressBookButton; + final CryptoCurrency? selectedCurrency; @override Widget build(BuildContext context) { @@ -207,7 +210,7 @@ class AddressTextField extends StatelessWidget { Future _presetAddressBookPicker(BuildContext context) async { final contact = await Navigator.of(context, rootNavigator: true) - .pushNamed(Routes.pickerAddressBook); + .pushNamed(Routes.pickerAddressBook,arguments: selectedCurrency); if (contact is ContactBase && contact.address != null) { controller?.text = contact.address; diff --git a/lib/store/authentication_store.dart b/lib/store/authentication_store.dart index 626ca2a91..b734d7acb 100644 --- a/lib/store/authentication_store.dart +++ b/lib/store/authentication_store.dart @@ -4,7 +4,7 @@ part 'authentication_store.g.dart'; class AuthenticationStore = AuthenticationStoreBase with _$AuthenticationStore; -enum AuthenticationState { uninitialized, installed, allowed, denied } +enum AuthenticationState { uninitialized, installed, allowed } abstract class AuthenticationStoreBase with Store { AuthenticationStoreBase() : state = AuthenticationState.uninitialized; @@ -17,7 +17,4 @@ abstract class AuthenticationStoreBase with Store { @action void allowed() => state = AuthenticationState.allowed; - - @action - void denied() => state = AuthenticationState.denied; } diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart new file mode 100644 index 000000000..ef9ab878f --- /dev/null +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -0,0 +1,51 @@ +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/view_model/settings/switcher_list_item.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/generated/i18n.dart'; + +part 'advanced_privacy_settings_view_model.g.dart'; + +class AdvancedPrivacySettingsViewModel = AdvancedPrivacySettingsViewModelBase + with _$AdvancedPrivacySettingsViewModel; + +abstract class AdvancedPrivacySettingsViewModelBase with Store { + AdvancedPrivacySettingsViewModelBase(this.type, this._settingsStore) + : _disableFiat = false, + _addCustomNode = false { + settings = [ + // TODO: uncomment when Disable Fiat PR is merged + // SwitcherListItem( + // title: S.current.disable_fiat, + // value: () => _disableFiat, + // onValueChange: (_, bool value) => _disableFiat = value, + // ), + SwitcherListItem( + title: S.current.disable_exchange, + value: () => _settingsStore.disableExchange, + onValueChange: (_, bool value) { + _settingsStore.disableExchange = value; + }, + ), + SwitcherListItem( + title: S.current.add_custom_node, + value: () => _addCustomNode, + onValueChange: (_, bool value) => _addCustomNode = value, + ), + ]; + } + + late List settings; + + @observable + bool _disableFiat = false; + + @observable + bool _addCustomNode = false; + + final WalletType type; + final SettingsStore _settingsStore; + + @computed + bool get addCustomNode => _addCustomNode; +} diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart index ec145ad44..5b0187fc8 100644 --- a/lib/view_model/contact_list/contact_list_view_model.dart +++ b/lib/view_model/contact_list/contact_list_view_model.dart @@ -7,27 +7,26 @@ import 'package:mobx/mobx.dart'; import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/contact.dart'; import 'package:cake_wallet/utils/mobx.dart'; +import 'package:cw_core/crypto_currency.dart'; part 'contact_list_view_model.g.dart'; -class ContactListViewModel = ContactListViewModelBase - with _$ContactListViewModel; +class ContactListViewModel = ContactListViewModelBase with _$ContactListViewModel; abstract class ContactListViewModelBase with Store { - ContactListViewModelBase(this.contactSource, this.walletInfoSource) + ContactListViewModelBase(this.contactSource, this.walletInfoSource, this._currency) : contacts = ObservableList(), walletContacts = [] { walletInfoSource.values.forEach((info) { if (info.addresses?.isNotEmpty ?? false) { info.addresses?.forEach((address, label) { - final name = label.isNotEmpty - ? info.name + ' ($label)' - : info.name; + final name = label.isNotEmpty ? info.name + ' ($label)' : info.name; walletContacts.add(WalletContact( - address, - name, - walletTypeToCryptoCurrency(info.type))); + address, + name, + walletTypeToCryptoCurrency(info.type), + )); }); } }); @@ -41,7 +40,18 @@ abstract class ContactListViewModelBase with Store { final Box walletInfoSource; final ObservableList contacts; final List walletContacts; + final CryptoCurrency? _currency; StreamSubscription? _subscription; + bool get isEditable => _currency == null; + Future delete(ContactRecord contact) async => contact.original.delete(); + + @computed + List get contactsToShow => + contacts.where((element) => _currency == null || element.type == _currency).toList(); + + @computed + List get walletContactsToShow => + walletContacts.where((element) => _currency == null || element.type == _currency).toList(); } diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index e24692059..a8f184589 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -1,7 +1,7 @@ import 'package:cake_wallet/core/execution_state.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; -import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/node.dart'; import 'package:cw_core/wallet_type.dart'; @@ -11,7 +11,7 @@ class NodeCreateOrEditViewModel = NodeCreateOrEditViewModelBase with _$NodeCreateOrEditViewModel; abstract class NodeCreateOrEditViewModelBase with Store { - NodeCreateOrEditViewModelBase(this._nodeSource, this._wallet) + NodeCreateOrEditViewModelBase(this._nodeSource, this._walletType, this._settingsStore) : state = InitialExecutionState(), connectionState = InitialExecutionState(), useSSL = false, @@ -49,8 +49,8 @@ abstract class NodeCreateOrEditViewModelBase with Store { bool get isReady => address.isNotEmpty && port.isNotEmpty; - bool get hasAuthCredentials => _wallet.type == WalletType.monero || - _wallet.type == WalletType.haven; + bool get hasAuthCredentials => _walletType == WalletType.monero || + _walletType == WalletType.haven; String get uri { var uri = address; @@ -62,8 +62,9 @@ abstract class NodeCreateOrEditViewModelBase with Store { return uri; } - final WalletBase _wallet; + final WalletType _walletType; final Box _nodeSource; + final SettingsStore _settingsStore; @action void reset() { @@ -76,13 +77,18 @@ abstract class NodeCreateOrEditViewModelBase with Store { } @action - Future save() async { + Future save({bool saveAsCurrent = false}) async { try { state = IsExecutingState(); final node = - Node(uri: uri, type: _wallet.type, login: login, password: password, + Node(uri: uri, type: _walletType, login: login, password: password, useSSL: useSSL, trusted: trusted); await _nodeSource.add(node); + + if (saveAsCurrent) { + _settingsStore.nodes[_walletType] = node; + } + state = ExecutedSuccessfullyState(); } catch (e) { state = FailureState(e.toString()); @@ -94,7 +100,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { try { connectionState = IsExecutingState(); final node = - Node(uri: uri, type: _wallet.type, login: login, password: password); + Node(uri: uri, type: _walletType, login: login, password: password); final isAlive = await node.requestNode(); connectionState = ExecutedSuccessfullyState(payload: isAlive); } catch (e) { diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 915e43e5d..c2ca48044 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -654,7 +654,6 @@ "use_suggested": "Vorgeschlagen verwenden", "do_not_share_warning_text" : "Teilen Sie diese nicht mit anderen, einschließlich des Supports.\n\nSie werden Ihr Geld stehlen!", "help": "hilfe", - "disable_exchange": "Exchange deaktivieren", "connection_sync": "Verbindung und Synchronisierung", "security_and_backup": "Sicherheit und Datensicherung", "create_backup": "Backup erstellen", @@ -662,6 +661,10 @@ "privacy": "Datenschutz", "display_settings": "Anzeigeeinstellungen", "other_settings": "Andere Einstellungen", + "disable_exchange": "Exchange deaktivieren", + "advanced_privacy_settings": "Erweiterte Datenschutzeinstellungen", + "settings_can_be_changed_later": "Diese Einstellungen können später in den App-Einstellungen geändert werden", + "add_custom_node": "Neuen benutzerdefinierten Knoten hinzufügen", "disable_fiat": "Fiat deaktivieren", "fiat_api": "Fiat API", "disabled": "Deaktiviert", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index a997b9f1f..6611db7ec 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -654,7 +654,6 @@ "use_suggested": "Use Suggested", "do_not_share_warning_text" : "Do not share these with anyone else, including support.\n\nThey will steal your money!", "help": "help", - "disable_exchange": "Disable exchange", "connection_sync": "Connection and sync", "security_and_backup": "Security and backup", "create_backup": "Create backup", @@ -662,6 +661,10 @@ "privacy": "Privacy", "display_settings": "Display settings", "other_settings": "Other settings", + "disable_exchange": "Disable exchange", + "advanced_privacy_settings": "Advanced Privacy Settings", + "settings_can_be_changed_later": "These settings can be changed later in the app settings", + "add_custom_node": "Add New Custom Node", "disable_fiat": "Disable fiat", "fiat_api": "Fiat API", "disabled": "Disabled", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 959b2a9a2..b3ba1d09a 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -654,7 +654,6 @@ "use_suggested": "Usar sugerido", "do_not_share_warning_text" : "No comparta estos con nadie más, incluido el soporte.\n\n¡Te robarán tu dinero!", "help": "ayuda", - "disable_exchange": "Deshabilitar intercambio", "connection_sync": "Conexión y sincronización", "security_and_backup": "Seguridad y respaldo", "create_backup": "Crear copia de seguridad", @@ -662,6 +661,10 @@ "privacy": "Privacidad", "display_settings": "Configuración de pantalla", "other_settings": "Otras configuraciones", + "disable_exchange": "Deshabilitar intercambio", + "advanced_privacy_settings": "Configuración avanzada de privacidad", + "settings_can_be_changed_later": "Estas configuraciones se pueden cambiar más tarde en la configuración de la aplicación", + "add_custom_node": "Agregar nuevo nodo personalizado", "disable_fiat": "Deshabilitar fiat", "fiat_api": "Fiat API", "disabled": "Desactivado", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index d82cad2f9..b6f20d28e 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -652,7 +652,6 @@ "use_suggested": "Utilisation suggérée", "do_not_share_warning_text" : "Ne les partagez avec personne d'autre, y compris avec l'assistance.\n\nIls vont voler votre argent!", "help": "aider", - "disable_exchange": "Désactiver l'échange", "connection_sync": "Connexion et synchronisation", "security_and_backup": "Sécurité et sauvegarde", "create_backup": "Créer une sauvegarde", @@ -660,6 +659,10 @@ "privacy": "Confidentialité", "display_settings": "Paramètres d'affichage", "other_settings": "Autres paramètres", + "disable_exchange": "Désactiver l'échange", + "advanced_privacy_settings": "Paramètres de confidentialité avancés", + "settings_can_be_changed_later": "Ces paramètres peuvent être modifiés ultérieurement dans les paramètres de l'application", + "add_custom_node": "Ajouter un nouveau nœud personnalisé", "disable_fiat": "Désactiver fiat", "fiat_api": "Fiat API", "disabled": "Handicapé", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 42f408229..157b56377 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -654,7 +654,6 @@ "use_suggested": "सुझाए गए का प्रयोग करें", "do_not_share_warning_text" : "इन्हें समर्थन सहित किसी और के साथ साझा न करें।\n\nवे आपका पैसा चुरा लेंगे!", "help": "मदद करना", - "disable_fiat": "िएट अक्षम करें", "connection_sync": "कनेक्शन और सिंक", "security_and_backup": "सुरक्षा और बैकअप", "create_backup": "बैकअप बनाएँ", @@ -663,6 +662,10 @@ "display_settings": "प्रदर्शन सेटिंग्स", "other_settings": "अन्य सेटिंग्स", "disable_exchange": "एक्सचेंज अक्षम करें", + "advanced_privacy_settings": "उन्नत गोपनीयता सेटिंग्स", + "settings_can_be_changed_later": "इन सेटिंग्स को बाद में ऐप सेटिंग में बदला जा सकता है", + "add_custom_node": "नया कस्टम नोड जोड़ें", + "disable_exchange": "एक्सचेंज अक्षम करें", "fiat_api": "फिएट पैसे API", "disabled": "अक्षम", "enabled": "सक्रिय", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 0e026e97d..481064460 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -654,7 +654,6 @@ "use_suggested": "Koristite predloženo", "do_not_share_warning_text" : "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nUkrast će vam novac!", "help": "pomozite", - "disable_exchange": "Onemogući exchange", "connection_sync": "Povezivanje i sinkronizacija", "security_and_backup": "Sigurnost i sigurnosna kopija", "create_backup": "Stvori sigurnosnu kopiju", @@ -662,6 +661,10 @@ "privacy": "Privatnost", "display_settings": "Postavke zaslona", "other_settings": "Ostale postavke", + "disable_exchange": "Onemogući exchange", + "advanced_privacy_settings": "Napredne postavke privatnosti", + "settings_can_be_changed_later": "Te se postavke mogu promijeniti kasnije u postavkama aplikacije", + "add_custom_node": "Dodaj novi prilagođeni čvor", "disable_fiat": "Isključi, fiat", "fiat_api": "Fiat API", "disabled": "Onemogućeno", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index db2a98658..0a6700bac 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -654,7 +654,6 @@ "use_suggested": "Usa suggerito", "do_not_share_warning_text" : "Non condividerli con nessun altro, incluso il supporto.\n\nTi ruberanno i soldi!", "help": "aiuto", - "disable_exchange": "Disabilita scambio", "connection_sync": "Connessione e sincronizzazione", "security_and_backup": "Sicurezza e backup", "create_backup": "Crea backup", @@ -662,6 +661,10 @@ "privacy": "Privacy", "display_settings": "Impostazioni di visualizzazione", "other_settings": "Altre impostazioni", + "disable_exchange": "Disabilita scambio", + "advanced_privacy_settings": "Impostazioni avanzate sulla privacy", + "settings_can_be_changed_later": "Queste impostazioni possono essere modificate in seguito nelle impostazioni dell'app", + "add_custom_node": "Aggiungi nuovo nodo personalizzato", "disable_fiat": "Disabilita fiat", "fiat_api": "Fiat API", "disabled": "Disabilitato", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 21fe513e9..75588d339 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -654,7 +654,6 @@ "use_suggested": "推奨を使用", "do_not_share_warning_text" : "サポートを含め、これらを他の誰とも共有しないでください。\n\n彼らはあなたのお金を盗みます!", "help": "ヘルプ", - "disable_exchange": "交換を無効にする", "connection_sync": "接続と同期", "security_and_backup": "セキュリティとバックアップ", "create_backup": "バックアップを作成", @@ -662,6 +661,10 @@ "privacy": "プライバシー", "display_settings": "表示設定", "other_settings": "その他の設定", + "disable_exchange": "交換を無効にする", + "advanced_privacy_settings": "高度なプライバシー設定", + "settings_can_be_changed_later": "これらの設定は、後でアプリの設定で変更できます", + "add_custom_node": "新しいカスタム ノードを追加", "disable_fiat": "フィアットを無効にする", "fiat_api": "不換紙幣 API", "disabled": "無効", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 38f001df0..8d59f20fb 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -654,7 +654,6 @@ "use_suggested": "추천 사용", "do_not_share_warning_text" : "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n그들은 당신의 돈을 훔칠 것입니다!", "help": "돕다", - "disable_exchange": "교환 비활성화", "connection_sync": "연결 및 동기화", "security_and_backup": "보안 및 백업", "create_backup": "백업 생성", @@ -662,6 +661,10 @@ "privacy": "프라이버시", "display_settings": "디스플레이 설정", "other_settings": "기타 설정", + "disable_exchange": "교환 비활성화", + "advanced_privacy_settings": "고급 개인 정보 설정", + "settings_can_be_changed_later": "이 설정은 나중에 앱 설정에서 변경할 수 있습니다.", + "add_custom_node": "새 사용자 정의 노드 추가", "disable_fiat": "법정화폐 비활성화", "fiat_api": "명목 화폐 API", "disabled": "장애가 있는", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 6283518f6..9d49e0c38 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -654,7 +654,6 @@ "use_suggested": "Gebruik aanbevolen", "do_not_share_warning_text" : "Deel deze met niemand anders, ook niet met support.\n\nZe zullen je geld stelen!", "help": "helpen", - "disable_exchange": "Uitwisseling uitschakelen", "connection_sync": "Verbinding en synchronisatie", "security_and_backup": "Beveiliging en back-up", "create_backup": "Maak een back-up", @@ -662,6 +661,10 @@ "privacy": "Privacy", "display_settings": "Weergave-instellingen", "other_settings": "Andere instellingen", + "disable_exchange": "Uitwisseling uitschakelen", + "advanced_privacy_settings": "Geavanceerde privacy-instellingen", + "settings_can_be_changed_later": "Deze instellingen kunnen later worden gewijzigd in de app-instellingen", + "add_custom_node": "Voeg een nieuw aangepast knooppunt toe", "disable_fiat": "Schakel Fiat uit", "fiat_api": "Fiat API", "disabled": "Gehandicapt", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index e768d7d4d..c49888c10 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -654,7 +654,6 @@ "use_suggested": "Użyj sugerowane", "do_not_share_warning_text" : "Nie udostępniaj ich nikomu innemu, w tym wsparcia.\n\nUkradną twoje pieniądze!", "help": "pomoc", - "disable_exchange": "Wyłącz wymianę", "connection_sync": "Połączenie i synchronizacja", "security_and_backup": "Bezpieczeństwo i kopia zapasowa", "create_backup": "Utwórz kopię zapasową", @@ -662,6 +661,10 @@ "privacy": "Prywatność", "display_settings": "Ustawienia wyświetlania", "other_settings": "Inne ustawienia", + "disable_exchange": "Wyłącz wymianę", + "advanced_privacy_settings": "Zaawansowane ustawienia prywatności", + "settings_can_be_changed_later": "Te ustawienia można później zmienić w ustawieniach aplikacji", + "add_custom_node": "Dodaj nowy węzeł niestandardowy", "disable_fiat": "Wyłącz fiat", "fiat_api": "API Fiata", "disabled": "Wyłączone", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index bd9c5e474..42653a545 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -653,7 +653,6 @@ "use_suggested": "Uso sugerido", "do_not_share_warning_text" : "Não os compartilhe com mais ninguém, incluindo suporte.\n\nEles vão roubar seu dinheiro!", "help": "ajuda", - "disable_exchange": "Desativar troca", "connection_sync": "Conexão e sincronização", "security_and_backup": "Segurança e backup", "create_backup": "Criar backup", @@ -661,6 +660,10 @@ "privacy": "Privacidade", "display_settings": "Configurações de exibição", "other_settings": "Outras configurações", + "disable_exchange": "Desativar troca", + "advanced_privacy_settings": "Configurações de privacidade avançadas", + "settings_can_be_changed_later": "Essas configurações podem ser alteradas posteriormente nas configurações do aplicativo", + "add_custom_node": "Adicionar novo nó personalizado", "disable_fiat": "Desativar fiat", "fiat_api": "API da Fiat", "disabled": "Desabilitado", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 8e1e0f21c..de9d95192 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -654,7 +654,6 @@ "use_suggested": "Использовать предложенный", "do_not_share_warning_text" : "Не делитесь ими с кем-либо еще, в том числе со службой поддержки.\n\nОни украдут ваши деньги!", "help": "помощь", - "disable_exchange": "Отключить обмен", "connection_sync": "Подключение и синхронизация", "security_and_backup": "Безопасность и резервное копирование", "create_backup": "Создать резервную копию", @@ -662,6 +661,10 @@ "privacy": "Конфиденциальность", "display_settings": "Настройки отображения", "other_settings": "Другие настройки", + "disable_exchange": "Отключить обмен", + "advanced_privacy_settings": "Расширенные настройки конфиденциальности", + "settings_can_be_changed_later": "Эти настройки можно изменить позже в настройках приложения.", + "add_custom_node": "Добавить новый пользовательский узел", "disable_fiat": "Отключить фиат", "fiat_api": "Фиат API", "disabled": "Отключено", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 1f72c1052..bc7da0450 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -653,7 +653,6 @@ "use_suggested": "Використати запропоноване", "do_not_share_warning_text" : "Не повідомляйте їх нікому, включно зі службою підтримки.\n\nВони вкрадуть ваші гроші!", "help": "допомога", - "disable_exchange": "Вимкнути exchange", "connection_sync": "Підключення та синхронізація", "security_and_backup": "Безпека та резервне копіювання", "create_backup": "Створити резервну копію", @@ -661,6 +660,10 @@ "privacy": "Конфіденційність", "display_settings": "Налаштування дисплея", "other_settings": "Інші налаштування", + "disable_exchange": "Вимкнути exchange", + "advanced_privacy_settings": "Розширені налаштування конфіденційності", + "settings_can_be_changed_later": "Ці параметри можна змінити пізніше в налаштуваннях програми", + "add_custom_node": "Додати новий спеціальний вузол", "disable_fiat": "Вимкнути фиат", "fiat_api": "Фіат API", "disabled": "Вимкнено", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 12655af5a..8a36d45ca 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -652,7 +652,6 @@ "use_suggested": "使用建议", "do_not_share_warning_text" : "不要與其他任何人分享這些內容,包括支持。\n\n他們會偷你的錢!", "help": "帮助", - "disable_exchange": "禁用交换", "connection_sync": "连接和同步", "security_and_backup": "安全和备份", "create_backup": "创建备份", @@ -660,6 +659,10 @@ "privacy":"隐私", "display_settings": "显示设置", "other_settings": "其他设置", + "disable_exchange": "禁用交换", + "advanced_privacy_settings": "高级隐私设置", + "settings_can_be_changed_later": "稍后可以在应用设置中更改这些设置", + "add_custom_node": "添加新的自定义节点", "disable_fiat": "禁用法令", "fiat_api": "法币API", "disabled": "禁用",