diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 7abed8c07..fad546d90 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -129,7 +129,7 @@ abstract class ElectrumWalletBase extends WalletBase startSync() async { try { - syncStatus = StartingSyncStatus(); + syncStatus = AttemptingSyncStatus(); await walletAddresses.discoverAddresses(); await updateTransactions(); _subscribeForUpdates(); diff --git a/cw_core/lib/sync_status.dart b/cw_core/lib/sync_status.dart index fabec67c8..4983967d0 100644 --- a/cw_core/lib/sync_status.dart +++ b/cw_core/lib/sync_status.dart @@ -28,7 +28,7 @@ class NotConnectedSyncStatus extends SyncStatus { double progress() => 0.0; } -class StartingSyncStatus extends SyncStatus { +class AttemptingSyncStatus extends SyncStatus { @override double progress() => 0.0; } diff --git a/cw_haven/lib/haven_wallet.dart b/cw_haven/lib/haven_wallet.dart index 4f360bdff..cf7c9dcdd 100644 --- a/cw_haven/lib/haven_wallet.dart +++ b/cw_haven/lib/haven_wallet.dart @@ -135,7 +135,7 @@ abstract class HavenWalletBase extends WalletBase SendPage(sendViewModel: getIt.get(), - settingsViewModel: getIt.get())); + () => SendPage(sendViewModel: getIt.get())); getIt.registerFactory(() => SendTemplatePage( sendTemplateViewModel: getIt.get())); @@ -434,12 +439,20 @@ Future setup( getIt.get(param1: account))); getIt.registerFactory(() { - final appStore = getIt.get(); - final yatStore = getIt.get(); - return SettingsViewModel(appStore.settingsStore, yatStore, appStore.wallet!); + return DisplaySettingsViewModel(getIt.get()); }); - getIt.registerFactory(() => SettingsPage(getIt.get())); + getIt.registerFactory(() { + return PrivacySettingsViewModel(getIt.get()); + }); + + getIt.registerFactory(() { + return OtherSettingsViewModel(getIt.get(), getIt.get().wallet!); + }); + + getIt.registerFactory(() { + return SecuritySettingsViewModel(getIt.get()); + }); getIt .registerFactory(() => WalletSeedViewModel(getIt.get().wallet!)); @@ -475,7 +488,15 @@ Future setup( _nodeSource, appStore.wallet!, appStore.settingsStore); }); - getIt.registerFactory(() => NodeListPage(getIt.get())); + getIt.registerFactory(() => ConnectionSyncPage(getIt.get(), getIt.get())); + + getIt.registerFactory(() => SecurityBackupPage(getIt.get())); + + getIt.registerFactory(() => PrivacyPage(getIt.get())); + + getIt.registerFactory(() => DisplaySettingsPage(getIt.get())); + + getIt.registerFactory(() => OtherSettingsPage(getIt.get())); getIt.registerFactory(() => NodeCreateOrEditViewModel(_nodeSource, getIt.get().wallet!)); @@ -494,7 +515,6 @@ Future setup( getIt.get(), getIt.get().settingsStore, getIt.get(), - getIt.get(), )); getIt.registerFactory(() => ExchangeTradeViewModel( diff --git a/lib/entities/priority_for_wallet_type.dart b/lib/entities/priority_for_wallet_type.dart new file mode 100644 index 000000000..927ab8803 --- /dev/null +++ b/lib/entities/priority_for_wallet_type.dart @@ -0,0 +1,21 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/haven/haven.dart'; +import 'package:cake_wallet/monero/monero.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_type.dart'; + +List priorityForWalletType(WalletType type) { + switch (type) { + case WalletType.monero: + return monero!.getTransactionPriorities(); + case WalletType.bitcoin: + return bitcoin!.getTransactionPriorities(); + case WalletType.litecoin: + return bitcoin!.getLitecoinTransactionPriorities(); + case WalletType.haven: + return haven!.getTransactionPriorities(); + default: + return []; + } +} + diff --git a/lib/router.dart b/lib/router.dart index b255ce8b9..4d3d61f5f 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -5,6 +5,10 @@ import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart'; import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart'; import 'package:cake_wallet/src/screens/buy/onramper_page.dart'; import 'package:cake_wallet/src/screens/buy/pre_order_page.dart'; +import 'package:cake_wallet/src/screens/settings/display_settings_page.dart'; +import 'package:cake_wallet/src/screens/settings/other_settings_page.dart'; +import 'package:cake_wallet/src/screens/settings/privacy_page.dart'; +import 'package:cake_wallet/src/screens/settings/security_backup_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_cards_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dart'; @@ -16,6 +20,7 @@ import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; +import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; 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'; @@ -36,7 +41,6 @@ import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart'; import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart'; -import 'package:cake_wallet/src/screens/nodes/nodes_list_page.dart'; import 'package:cake_wallet/src/screens/receive/receive_page.dart'; import 'package:cake_wallet/src/screens/subaddress/address_edit_or_create_page.dart'; import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart'; @@ -56,7 +60,6 @@ import 'package:cake_wallet/src/screens/contact/contact_page.dart'; import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart'; import 'package:cake_wallet/src/screens/restore/restore_wallet_from_seed_details.dart'; import 'package:cake_wallet/src/screens/exchange/exchange_page.dart'; -import 'package:cake_wallet/src/screens/settings/settings.dart'; import 'package:cake_wallet/src/screens/rescan/rescan_page.dart'; import 'package:cake_wallet/src/screens/faq/faq_page.dart'; import 'package:cake_wallet/src/screens/trade_details/trade_details_page.dart'; @@ -274,10 +277,26 @@ Route createRoute(RouteSettings settings) { param2: false), onWillPop: () async => false)); - case Routes.nodeList: + case Routes.connectionSync: return CupertinoPageRoute( - builder: (_) => getIt.get()); + builder: (_) => getIt.get()); + case Routes.securityBackupPage: + return CupertinoPageRoute( + builder: (_) => getIt.get()); + + case Routes.privacyPage: + return CupertinoPageRoute( + builder: (_) => getIt.get()); + + case Routes.displaySettingsPage: + return CupertinoPageRoute( + builder: (_) => getIt.get()); + + case Routes.otherSettingsPage: + return CupertinoPageRoute( + builder: (_) => getIt.get()); + case Routes.newNode: return CupertinoPageRoute( builder: (_) => getIt.get()); @@ -360,9 +379,6 @@ Route createRoute(RouteSettings settings) { return CupertinoPageRoute( builder: (_) => getIt.get()); - case Routes.settings: - return MaterialPageRoute(builder: (_) => getIt.get()); - case Routes.rescan: return MaterialPageRoute(builder: (_) => getIt.get()); diff --git a/lib/routes.dart b/lib/routes.dart index 3a781ac3a..d738b13e8 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -21,7 +21,6 @@ class Routes { static const seedLanguage = '/seed_language'; static const walletList = '/view_model.wallet_list'; static const auth = '/auth'; - static const nodeList = '/node_list'; static const newNode = '/new_node_list'; static const login = '/login'; static const splash = '/splash'; @@ -77,4 +76,9 @@ class Routes { static const ioniaMoreOptionsPage = '/ionia_more_options_page'; static const ioniaCustomRedeemPage = '/ionia_custom_redeem_page'; static const onramperPage = '/onramper'; + static const connectionSync = '/connection_sync_page'; + static const securityBackupPage = '/security_and_backup_page'; + static const privacyPage = '/privacy_page'; + static const displaySettingsPage = '/display_settings_page'; + static const otherSettingsPage = '/other_settings_page'; } diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index fe8414134..c21365aa4 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -60,7 +60,7 @@ class DashboardPage extends BasePage { Widget middle(BuildContext context) { return SyncIndicator(dashboardViewModel: walletViewModel, onTap: () => Navigator.of(context, rootNavigator: true) - .pushNamed(Routes.nodeList)); + .pushNamed(Routes.connectionSync)); } @override diff --git a/lib/src/screens/dashboard/wallet_menu.dart b/lib/src/screens/dashboard/wallet_menu.dart index 68e7cc76d..bc1f20a5d 100644 --- a/lib/src/screens/dashboard/wallet_menu.dart +++ b/lib/src/screens/dashboard/wallet_menu.dart @@ -1,81 +1,64 @@ import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/src/screens/dashboard/wallet_menu_item.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/auth/auth_page.dart'; -import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; -import 'package:cake_wallet/wallet_type_utils.dart'; // FIXME: terrible design class WalletMenu { WalletMenu(this.context, this.reconnect, this.hasRescan) : items = [] { items.addAll([ - WalletMenuItem( - title: S.current.reconnect, - image: Image.asset('assets/images/reconnect_menu.png', - height: 16, width: 16), - handler: () => _presentReconnectAlert(context)), - if (hasRescan) - WalletMenuItem( - title: S.current.rescan, - image: Image.asset('assets/images/filter_icon.png', - height: 16, width: 16, color: Palette.darkBlue), - handler: () => Navigator.of(context).pushNamed(Routes.rescan)), - WalletMenuItem( - title: S.current.wallets, - image: Image.asset('assets/images/wallet_menu.png', - height: 16, width: 16), - handler: () => Navigator.of(context).pushNamed(Routes.walletList)), - WalletMenuItem( - title: S.current.nodes, - image: Image.asset('assets/images/nodes_menu.png', - height: 16, width: 16), - handler: () => Navigator.of(context).pushNamed(Routes.nodeList)), - WalletMenuItem( - title: S.current.show_keys, - image: - Image.asset('assets/images/key_menu.png', height: 16, width: 16), - handler: () { - Navigator.of(context).pushNamed(Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { - if (isAuthenticatedSuccessfully) { - auth.close(route: Routes.showKeys); - } - }); - }), - WalletMenuItem( - title: S.current.address_book_menu, - image: Image.asset('assets/images/open_book_menu.png', - height: 16, width: 16), - handler: () => Navigator.of(context).pushNamed(Routes.addressBook)), - WalletMenuItem( - title: S.current.backup, - image: Image.asset('assets/images/restore_wallet.png', - height: 16, - width: 16, - color: Palette.darkBlue), - handler: () { - Navigator.of(context).pushNamed( - Routes.auth, - arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { - if (isAuthenticatedSuccessfully) { - auth.close(route:Routes.backup); - } - }); - }), - WalletMenuItem( - title: S.current.settings_title, - image: Image.asset('assets/images/settings_menu.png', - height: 16, width: 16), - handler: () => Navigator.of(context).pushNamed(Routes.settings)), - WalletMenuItem( - title: S.current.settings_support, - image: Image.asset('assets/images/question_mark.png', - height: 16, width: 16, color: Palette.darkBlue), - handler: () => Navigator.of(context).pushNamed(Routes.support)), + WalletMenuItem( + title: S.current.connection_sync, + image: Image.asset('assets/images/nodes_menu.png', + height: 16, width: 16), + handler: () => Navigator.of(context).pushNamed(Routes.connectionSync), + ), + WalletMenuItem( + title: S.current.wallets, + image: Image.asset('assets/images/wallet_menu.png', + height: 16, width: 16), + handler: () => Navigator.of(context).pushNamed(Routes.walletList), + ), + WalletMenuItem( + title: S.current.security_and_backup, + image: + Image.asset('assets/images/key_menu.png', height: 16, width: 16), + handler: () { + Navigator.of(context).pushNamed(Routes.securityBackupPage); + }), + WalletMenuItem( + title: S.current.privacy, + image: + Image.asset('assets/images/eye_menu.png', height: 16, width: 16), + handler: () { + Navigator.of(context).pushNamed(Routes.privacyPage); + }), + WalletMenuItem( + title: S.current.address_book_menu, + image: Image.asset('assets/images/open_book_menu.png', + height: 16, width: 16), + handler: () => Navigator.of(context).pushNamed(Routes.addressBook), + ), + WalletMenuItem( + title: S.current.display_settings, + image: Image.asset('assets/images/eye_menu.png', + height: 16, width: 16), + handler: () => Navigator.of(context).pushNamed(Routes.displaySettingsPage), + ), + WalletMenuItem( + title: S.current.other_settings, + image: Image.asset('assets/images/settings_menu.png', + height: 16, width: 16), + handler: () => Navigator.of(context).pushNamed(Routes.otherSettingsPage), + ), + WalletMenuItem( + title: S.current.settings_support, + image: Image.asset('assets/images/question_mark.png', + height: 16, width: 16, color: Palette.darkBlue), + handler: () => Navigator.of(context).pushNamed(Routes.support), + ), ]); } @@ -86,23 +69,6 @@ class WalletMenu { void action(int index) { final item = items[index]; - item?.handler(); - } - - Future _presentReconnectAlert(BuildContext context) async { - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: S.of(context).reconnection, - alertContent: S.of(context).reconnect_alert_text, - rightButtonText: S.of(context).ok, - leftButtonText: S.of(context).cancel, - actionRightButton: () async { - Navigator.of(context).pop(); - await reconnect?.call(); - }, - actionLeftButton: () => Navigator.of(context).pop()); - }); + item.handler(); } } diff --git a/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart b/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart index 2fbb1d57d..1c13f7a88 100644 --- a/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart +++ b/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart @@ -118,7 +118,7 @@ class IoniaManageCardsPage extends BasePage { width: 32, padding: EdgeInsets.all(8), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.15), + color: Theme.of(context).textTheme!.headline6!.backgroundColor!, border: Border.all( color: Colors.white.withOpacity(0.2), ), diff --git a/lib/src/screens/ionia/widgets/ionia_filter_modal.dart b/lib/src/screens/ionia/widgets/ionia_filter_modal.dart index ec6e84cc0..2b885f736 100644 --- a/lib/src/screens/ionia/widgets/ionia_filter_modal.dart +++ b/lib/src/screens/ionia/widgets/ionia_filter_modal.dart @@ -20,7 +20,7 @@ class IoniaFilterModal extends StatelessWidget { padding: EdgeInsets.all(10), child: Image.asset( 'assets/images/mini_search_icon.png', - color: Theme.of(context).accentColor, + color: Theme.of(context).textTheme.subtitle2!.color!, ), ); return Scaffold( @@ -53,7 +53,7 @@ class IoniaFilterModal extends StatelessWidget { prefixIcon: searchIcon, hintText: S.of(context).search_category, contentPadding: EdgeInsets.only(bottom: 5), - fillColor: Theme.of(context).textTheme!.subtitle1!.backgroundColor!, + fillColor: Theme.of(context).primaryTextTheme!.caption!.decorationColor!.withOpacity(0.5), border: OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.circular(8), diff --git a/lib/src/screens/nodes/nodes_list_page.dart b/lib/src/screens/nodes/nodes_list_page.dart deleted file mode 100644 index 556a0fd06..000000000 --- a/lib/src/screens/nodes/nodes_list_page.dart +++ /dev/null @@ -1,166 +0,0 @@ -import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:cw_core/node.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/palette.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/screens/nodes/widgets/node_list_row.dart'; -import 'package:cake_wallet/src/widgets/standard_list.dart'; -import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; -import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart'; -import 'package:flutter_slidable/flutter_slidable.dart'; - -class NodeListPage extends BasePage { - NodeListPage(this.nodeListViewModel); - - @override - String get title => S.current.nodes; - - final NodeListViewModel nodeListViewModel; - - @override - Widget trailing(context) { - return Container( - height: 32, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(16)), - color: Theme.of(context).accentTextTheme.caption!.color!), - child: ButtonTheme( - minWidth: double.minPositive, - child: TextButton( - onPressed: () async { - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: S.of(context).node_reset_settings_title, - alertContent: - S.of(context).nodes_list_reset_to_default_message, - rightButtonText: S.of(context).reset, - leftButtonText: S.of(context).cancel, - actionRightButton: () async { - Navigator.of(context).pop(); - await nodeListViewModel.reset(); - }, - actionLeftButton: () => Navigator.of(context).pop()); - }); - }, - child: Text( - S.of(context).reset, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14.0, - fontWeight: FontWeight.w600, - color: Palette.blueCraiola), - )), - ), - ); - } - - @override - Widget body(BuildContext context) { - return Container( - padding: EdgeInsets.only(top: 10), - child: Observer( - builder: (BuildContext context) { - return SectionStandardList( - sectionCount: 2, - context: context, - itemCounter: (int sectionIndex) { - if (sectionIndex == 0) { - return 1; - } - - return nodeListViewModel.nodes.length; - }, - itemBuilder: (_, sectionIndex, index) { - if (sectionIndex == 0) { - return NodeHeaderListRow( - title: S.of(context).add_new_node, - onTap: (_) async => await Navigator.of(context) - .pushNamed(Routes.newNode)); - } - - final node = nodeListViewModel.nodes[index]; - final isSelected = - node.keyIndex == nodeListViewModel.currentNode.keyIndex; - final nodeListRow = NodeListRow( - title: node.uriRaw, - isSelected: isSelected, - isAlive: node.requestNode(), - onTap: (_) async { - if (isSelected) { - return; - } - - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: - S.of(context).change_current_node_title, - alertContent: S - .of(context) - .change_current_node(node.uriRaw), - leftButtonText: S.of(context).cancel, - rightButtonText: S.of(context).change, - actionLeftButton: () => - Navigator.of(context).pop(), - actionRightButton: () async { - await nodeListViewModel.setAsCurrent(node); - Navigator.of(context).pop(); - }); - }); - }); - - final dismissibleRow = Slidable( - key: Key('${node.keyIndex}'), - startActionPane: _actionPane(context, node), - endActionPane: _actionPane(context, node), - child: nodeListRow, - ); - - return isSelected ? nodeListRow : dismissibleRow; - }); - }, - ), - ); - } - - ActionPane _actionPane(BuildContext context, Node node) => ActionPane( - motion: const ScrollMotion(), - extentRatio: 0.3, - children: [ - SlidableAction( - onPressed: (context) async { - final confirmed = await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: S.of(context).remove_node, - alertContent: - S.of(context).remove_node_message, - rightButtonText: S.of(context).remove, - leftButtonText: S.of(context).cancel, - actionRightButton: () => - Navigator.pop(context, true), - actionLeftButton: () => - Navigator.pop(context, false)); - }) ?? - false; - - if (confirmed) { - await nodeListViewModel.delete(node); - } - }, - backgroundColor: Colors.red, - foregroundColor: Colors.white, - icon: CupertinoIcons.delete, - label: S.of(context).delete, - ), - ], - ); -} diff --git a/lib/src/screens/nodes/widgets/node_list_row.dart b/lib/src/screens/nodes/widgets/node_list_row.dart index 3008d450c..580aba170 100644 --- a/lib/src/screens/nodes/widgets/node_list_row.dart +++ b/lib/src/screens/nodes/widgets/node_list_row.dart @@ -37,7 +37,10 @@ class NodeHeaderListRow extends StandardListRow { @override Widget buildTrailing(BuildContext context) { - return Icon(Icons.add, - color: Theme.of(context).accentTextTheme!.subtitle1!.color!, size: 24.0); + return SizedBox( + width: 20, + child: Icon(Icons.add, + color: Theme.of(context).accentTextTheme!.subtitle1!.color!, size: 24.0), + ); } } diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index e0cfff517..b051a3afb 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,4 +1,3 @@ -import 'dart:ui'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart'; import 'package:cake_wallet/src/screens/send/widgets/send_card.dart'; @@ -6,8 +5,6 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:cake_wallet/src/widgets/template_tile.dart'; import 'package:cake_wallet/view_model/send/output.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; @@ -28,13 +25,11 @@ import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'package:cw_core/crypto_currency.dart'; class SendPage extends BasePage { - SendPage({required this.sendViewModel,required this.settingsViewModel }) : _formKey = GlobalKey(),fiatFromSettings = settingsViewModel.fiatCurrency; + SendPage({required this.sendViewModel}) : _formKey = GlobalKey(); final SendViewModel sendViewModel; - final SettingsViewModel settingsViewModel; final GlobalKey _formKey; final controller = PageController(initialPage: 0); - final FiatCurrency fiatFromSettings ; bool _effectsInstalled = false; @@ -55,7 +50,7 @@ class SendPage extends BasePage { @override void onClose(BuildContext context) { - settingsViewModel.setFiatCurrency(fiatFromSettings); + sendViewModel.onClose(); Navigator.of(context).pop(); } @@ -236,7 +231,7 @@ class SendPage extends BasePage { if(template.isCurrencySelected){ output.setCryptoAmount(template.amount); }else{ - settingsViewModel.setFiatCurrency(fiatFromTemplate); + sendViewModel.setFiatCurrency(fiatFromTemplate); output.setFiatAmount(template.amountFiat); } output.resetParsedAddress(); diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index dc589923f..d5775e2b5 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -1,11 +1,10 @@ -import 'dart:ui'; +import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:cake_wallet/view_model/send/output.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart new file mode 100644 index 000000000..0e56d6e58 --- /dev/null +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -0,0 +1,155 @@ +import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cw_core/node.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/nodes/widgets/node_list_row.dart'; +import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; + +class ConnectionSyncPage extends BasePage { + ConnectionSyncPage(this.nodeListViewModel, this.dashboardViewModel); + + @override + String get title => S.current.connection_sync; + + final NodeListViewModel nodeListViewModel; + final DashboardViewModel dashboardViewModel; + + @override + Widget body(BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 10), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SettingsCellWithArrow( + title: S.current.reconnect, + handler: (context) => _presentReconnectAlert(context), + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + SettingsCellWithArrow( + title: S.current.rescan, + handler: (context) => Navigator.of(context).pushNamed(Routes.rescan), + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + NodeHeaderListRow( + title: S.of(context).add_new_node, + onTap: (_) async => await Navigator.of(context).pushNamed(Routes.newNode), + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + SizedBox(height: 100), + Observer( + builder: (BuildContext context) { + return Flexible( + child: SectionStandardList( + sectionCount: 1, + context: context, + dividerPadding: EdgeInsets.symmetric(horizontal: 24), + itemCounter: (int sectionIndex) { + return nodeListViewModel.nodes.length; + }, + itemBuilder: (_, sectionIndex, index) { + final node = nodeListViewModel.nodes[index]; + final isSelected = node.keyIndex == nodeListViewModel.currentNode.keyIndex; + final nodeListRow = NodeListRow( + title: node.uriRaw, + isSelected: isSelected, + isAlive: node.requestNode(), + onTap: (_) async { + if (isSelected) { + return; + } + + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).change_current_node_title, + alertContent: S.of(context).change_current_node(node.uriRaw), + leftButtonText: S.of(context).cancel, + rightButtonText: S.of(context).change, + actionLeftButton: () => Navigator.of(context).pop(), + actionRightButton: () async { + await nodeListViewModel.setAsCurrent(node); + Navigator.of(context).pop(); + }, + ); + }); + }, + ); + + final dismissibleRow = Slidable( + key: Key('${node.keyIndex}'), + startActionPane: _actionPane(context, node), + endActionPane: _actionPane(context, node), + child: nodeListRow, + ); + + return isSelected ? nodeListRow : dismissibleRow; + }, + ), + ); + }, + ), + ], + ), + ); + } + + Future _presentReconnectAlert(BuildContext context) async { + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).reconnection, + alertContent: S.of(context).reconnect_alert_text, + rightButtonText: S.of(context).ok, + leftButtonText: S.of(context).cancel, + actionRightButton: () async { + Navigator.of(context).pop(); + await dashboardViewModel.reconnect(); + }, + actionLeftButton: () => Navigator.of(context).pop()); + }, + ); + } + + ActionPane _actionPane(BuildContext context, Node node) => ActionPane( + motion: const ScrollMotion(), + extentRatio: 0.3, + children: [ + SlidableAction( + onPressed: (context) async { + final confirmed = await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).remove_node, + alertContent: S.of(context).remove_node_message, + rightButtonText: S.of(context).remove, + leftButtonText: S.of(context).cancel, + actionRightButton: () => Navigator.pop(context, true), + actionLeftButton: () => Navigator.pop(context, false)); + }) ?? + false; + + if (confirmed) { + await nodeListViewModel.delete(node); + } + }, + backgroundColor: Colors.red, + foregroundColor: Colors.white, + icon: CupertinoIcons.delete, + label: S.of(context).delete, + ), + ], + ); +} diff --git a/lib/src/screens/settings/display_settings_page.dart b/lib/src/screens/settings/display_settings_page.dart new file mode 100644 index 000000000..cd413ff45 --- /dev/null +++ b/lib/src/screens/settings/display_settings_page.dart @@ -0,0 +1,80 @@ +import 'package:cake_wallet/entities/fiat_currency.dart'; +import 'package:cake_wallet/entities/language_service.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.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'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:cake_wallet/themes/theme_list.dart'; +import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; +import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart'; +import 'package:cake_wallet/wallet_type_utils.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class DisplaySettingsPage extends BasePage { + DisplaySettingsPage(this._displaySettingsViewModel); + + @override + String get title => S.current.display_settings; + + final DisplaySettingsViewModel _displaySettingsViewModel; + + @override + Widget body(BuildContext context) { + return Observer(builder: (_) { + return Container( + padding: EdgeInsets.only(top: 10), + child: Column( + children: [ + SettingsSwitcherCell( + title: S.current.settings_display_balance, + value: _displaySettingsViewModel.shouldDisplayBalance, + onValueChange: (_, bool value) { + _displaySettingsViewModel.setShouldDisplayBalance(value); + }), + if (!isHaven) + SettingsPickerCell( + title: S.current.settings_currency, + searchHintText: S.current.search_currency, + items: FiatCurrency.all, + selectedItem: _displaySettingsViewModel.fiatCurrency, + onItemSelected: (FiatCurrency currency) => _displaySettingsViewModel.setFiatCurrency(currency), + images: FiatCurrency.all.map((e) => Image.asset("assets/images/flags/${e.countryCode}.png")).toList(), + isGridView: true, + matchingCriteria: (FiatCurrency currency, String searchText) { + return currency.title.toLowerCase().contains(searchText) || + currency.fullName.toLowerCase().contains(searchText); + }, + ), + SettingsPickerCell( + title: S.current.settings_change_language, + searchHintText: S.current.search_language, + items: LanguageService.list.keys.toList(), + displayItem: (dynamic code) { + return LanguageService.list[code] ?? ''; + }, + selectedItem: _displaySettingsViewModel.languageCode, + onItemSelected: _displaySettingsViewModel.onLanguageSelected, + images: LanguageService.list.keys + .map((e) => Image.asset("assets/images/flags/${LanguageService.localeCountryCode[e]}.png")) + .toList(), + matchingCriteria: (String code, String searchText) { + return LanguageService.list[code]?.toLowerCase().contains(searchText) ?? false; + }, + ), + SettingsChoicesCell( + ChoicesListItem( + title: S.current.color_theme, + items: ThemeList.all, + selectedItem: _displaySettingsViewModel.theme, + onItemSelected: (ThemeBase theme) => _displaySettingsViewModel.setTheme(theme), + ), + ), + ], + ), + ); + }); + } +} diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart new file mode 100644 index 000000000..e055e2e8e --- /dev/null +++ b/lib/src/screens/settings/other_settings_page.dart @@ -0,0 +1,45 @@ +import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/base_page.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_version_cell.dart'; +import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class OtherSettingsPage extends BasePage { + OtherSettingsPage(this._otherSettingsViewModel); + + @override + String get title => S.current.other_settings; + + final OtherSettingsViewModel _otherSettingsViewModel; + + @override + Widget body(BuildContext context) { + return Observer(builder: (_) { + return Container( + padding: EdgeInsets.only(top: 10), + child: Column(children: [ + SettingsPickerCell( + title: S.current.settings_fee_priority, + items: priorityForWalletType(_otherSettingsViewModel.walletType), + displayItem: _otherSettingsViewModel.getDisplayPriority, + selectedItem: _otherSettingsViewModel.transactionPriority, + onItemSelected: _otherSettingsViewModel.onDisplayPrioritySelected, + ), + SettingsCellWithArrow( + title: S.current.settings_terms_and_conditions, + handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.readDisclaimer), + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + Spacer(), + SettingsVersionCell(title: S.of(context).version(_otherSettingsViewModel.currentVersion)) + ]), + ); + }); + } +} diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart new file mode 100644 index 000000000..128d864f4 --- /dev/null +++ b/lib/src/screens/settings/privacy_page.dart @@ -0,0 +1,43 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class PrivacyPage extends BasePage { + PrivacyPage(this._privacySettingsViewModel); + + @override + String get title => S.current.privacy_settings; + + final PrivacySettingsViewModel _privacySettingsViewModel; + + @override + Widget body(BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 10), + child: Observer(builder: (_) { + return Observer(builder: (_) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SettingsSwitcherCell( + title: S.current.disable_exchange, + value: _privacySettingsViewModel.disableExchange, + onValueChange: (BuildContext context, bool value) { + _privacySettingsViewModel.setEnableExchange(value); + }), + SettingsSwitcherCell( + title: S.current.settings_save_recipient_address, + value: _privacySettingsViewModel.shouldSaveRecipientAddress, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setShouldSaveRecipientAddress(value); + }) + ], + ); + }); + }), + ); + } +} diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart new file mode 100644 index 000000000..224c941ee --- /dev/null +++ b/lib/src/screens/settings/security_backup_page.dart @@ -0,0 +1,84 @@ +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/auth/auth_page.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class SecurityBackupPage extends BasePage { + SecurityBackupPage(this._securitySettingsViewModel); + + @override + String get title => S.current.security_and_backup; + + final SecuritySettingsViewModel _securitySettingsViewModel; + + @override + Widget body(BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 10), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + SettingsCellWithArrow( + title: S.current.show_keys, + handler: (_) => Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { + if (isAuthenticatedSuccessfully) { + auth.close(route: Routes.showKeys); + } + }), + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + SettingsCellWithArrow( + title: S.current.create_backup, + handler: (_) => Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { + if (isAuthenticatedSuccessfully) { + auth.close(route: Routes.backup); + } + }), + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + SettingsCellWithArrow( + title: S.current.settings_change_pin, + handler: (_) => Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { + auth.close( + route: isAuthenticatedSuccessfully ? Routes.setupPin : null, + arguments: (PinCodeState setupPinContext, String _) { + setupPinContext.close(); + }, + ); + })), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + Observer(builder: (_) { + return SettingsSwitcherCell( + title: S.current.settings_allow_biometrical_authentication, + value: _securitySettingsViewModel.allowBiometricalAuthentication, + onValueChange: (BuildContext context, bool value) { + if (value) { + Navigator.of(context).pushNamed(Routes.auth, + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { + if (isAuthenticatedSuccessfully) { + if (await _securitySettingsViewModel.biometricAuthenticated()) { + _securitySettingsViewModel.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); + } + } else { + _securitySettingsViewModel.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully); + } + + auth.close(); + }); + } else { + _securitySettingsViewModel.setAllowBiometricalAuthentication(value); + } + }); + }), + ]), + ); + } +} diff --git a/lib/src/screens/settings/settings.dart b/lib/src/screens/settings/settings.dart deleted file mode 100644 index 3f6f41e7b..000000000 --- a/lib/src/screens/settings/settings.dart +++ /dev/null @@ -1,98 +0,0 @@ -import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart'; -import 'package:cake_wallet/src/screens/settings/widgets/settings_version_cell.dart'; -import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; -import 'package:cake_wallet/view_model/settings/version_list_item.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; -import 'package:cake_wallet/view_model/settings/link_list_item.dart'; -import 'package:cake_wallet/view_model/settings/picker_list_item.dart'; -import 'package:cake_wallet/view_model/settings/regular_list_item.dart'; -import 'package:cake_wallet/view_model/settings/switcher_list_item.dart'; -import 'package:cake_wallet/src/screens/settings/widgets/settings_link_provider_cell.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'; -import 'package:cake_wallet/src/widgets/standard_list.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; - -class SettingsPage extends BasePage { - SettingsPage(this.settingsViewModel); - - final SettingsViewModel settingsViewModel; - - @override - String get title => S.current.settings_title; - - @override - Widget body(BuildContext context) { - // FIX-ME: Added `context` it was not used here before, maby bug ? - return SectionStandardList( - context: context, - sectionCount: settingsViewModel.sections.length, - itemCounter: (int sectionIndex) { - if (sectionIndex < settingsViewModel.sections.length) { - return settingsViewModel.sections[sectionIndex].length; - } - - return 0; - }, - itemBuilder: (_, sectionIndex, itemIndex) { - final item = settingsViewModel.sections[sectionIndex][itemIndex]; - - if (item is PickerListItem) { - return Observer(builder: (_) { - return SettingsPickerCell( - displayItem: item.displayItem, - title: item.title, - selectedItem: item.selectedItem(), - items: item.items, - onItemSelected: (dynamic value) => item.onItemSelected(value), - images: item.images, - searchHintText: item.searchHintText, - isGridView: item.isGridView, - matchingCriteria: (dynamic value, String searchText) => item.matchingCriteria(value, searchText), - ); - }); - } - - if (item is SwitcherListItem) { - return Observer(builder: (_) { - return SettingsSwitcherCell( - title: item.title, - value: item.value(), - onValueChange: item.onValueChange); - }); - } - - if (item is RegularListItem) { - return SettingsCellWithArrow( - title: item.title, handler: item.handler); - } - - if (item is LinkListItem) { - return SettingsLinkProviderCell( - title: item.title, - icon: item.icon, - link: item.link, - linkTitle: item.linkTitle); - } - - if (item is VersionListItem) { - return Observer(builder: (_) { - return SettingsVersionCell( - title: - S.of(context).version(settingsViewModel.currentVersion)); - }); - } - - if (item is ChoicesListItem) { - return SettingsChoicesCell(item); - } - - return Container(); - }); - } -} diff --git a/lib/src/widgets/standard_list.dart b/lib/src/widgets/standard_list.dart index ae8978eb4..f5abdd900 100644 --- a/lib/src/widgets/standard_list.dart +++ b/lib/src/widgets/standard_list.dart @@ -123,6 +123,7 @@ class SectionStandardList extends StatelessWidget { required this.itemBuilder, required this.sectionCount, required BuildContext context, + this.dividerPadding = const EdgeInsets.only(left: 24), this.themeColor, this.dividerThemeColor, this.sectionTitleBuilder, @@ -149,6 +150,7 @@ class SectionStandardList extends StatelessWidget { final List totalRows; final Color? themeColor; final Color? dividerThemeColor; + final EdgeInsets dividerPadding; List transform( bool hasTopSeparator, @@ -178,7 +180,7 @@ class SectionStandardList extends StatelessWidget { items.add(sectionIndex + 1 != sectionCount ? SectionHeaderListRow() - : StandardListSeparator(padding: EdgeInsets.only(left: 24))); + : StandardListSeparator(padding: dividerPadding)); } return items; diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 725208324..68947d170 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -6,8 +6,8 @@ import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart'; import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:cake_wallet/exchange/simpleswap/simpleswap_request.dart'; +import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/sync_status.dart'; @@ -42,7 +42,7 @@ class ExchangeViewModel = ExchangeViewModelBase with _$ExchangeViewModel; abstract class ExchangeViewModelBase with Store { ExchangeViewModelBase(this.wallet, this.trades, this._exchangeTemplateStore, - this.tradesStore, this._settingsStore, this.sharedPreferences, this._settingsViewModel) + this.tradesStore, this._settingsStore, this.sharedPreferences) : _cryptoNumberFormat = NumberFormat(), isReverse = false, isFixedRateMode = false, @@ -189,6 +189,19 @@ abstract class ExchangeViewModelBase with Store { ObservableList get templates => _exchangeTemplateStore.templates; + + @computed + TransactionPriority get transactionPriority { + final priority = _settingsStore.priority[wallet.type]; + + if (priority == null) { + throw Exception('Unexpected type ${wallet.type.toString()}'); + } + + return priority; + } + + bool get hasAllAmount => wallet.type == WalletType.bitcoin && depositCurrency == wallet.currency; @@ -198,11 +211,11 @@ abstract class ExchangeViewModelBase with Store { switch (wallet.type) { case WalletType.monero: case WalletType.haven: - return _settingsViewModel.transactionPriority == monero!.getMoneroTransactionPrioritySlow(); + return transactionPriority == monero!.getMoneroTransactionPrioritySlow(); case WalletType.bitcoin: - return _settingsViewModel.transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow(); + return transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow(); case WalletType.litecoin: - return _settingsViewModel.transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow(); + return transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow(); default: return false; } @@ -220,8 +233,6 @@ abstract class ExchangeViewModelBase with Store { final SettingsStore _settingsStore; - final SettingsViewModel _settingsViewModel; - double _bestRate = 0.0; late Timer bestRateSync; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index cdef6faba..25a5cc7ee 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -1,10 +1,10 @@ import 'package:cake_wallet/entities/balance_display_mode.dart'; +import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cake_wallet/view_model/send/send_template_view_model.dart'; -import 'package:cake_wallet/view_model/settings/settings_view_model.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/entities/template.dart'; @@ -42,7 +42,8 @@ abstract class SendViewModelBase with Store { : state = InitialExecutionState(), currencies = _wallet.balance.keys.toList(), selectedCryptoCurrency = _wallet.currency, - outputs = ObservableList() { + outputs = ObservableList(), + fiatFromSettings = _settingsStore.fiatCurrency { final priority = _settingsStore.priority[_wallet.type]; final priorities = priorityForWalletType(_wallet.type); @@ -52,7 +53,7 @@ abstract class SendViewModelBase with Store { outputs.add(Output(_wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency)); } - + @observable ExecutionState state; @@ -133,11 +134,13 @@ abstract class SendViewModelBase with Store { Validator get textValidator => TextValidator(); + final FiatCurrency fiatFromSettings; + @observable PendingTransaction? pendingTransaction; @computed - String get balance => balanceViewModel.availableBalance ?? '0.0'; + String get balance => balanceViewModel.availableBalance; @computed bool get isReadyForSend => _wallet.syncStatus is SyncedSyncStatus; @@ -166,6 +169,9 @@ abstract class SendViewModelBase with Store { bool get hasCurrecyChanger => walletType == WalletType.haven; + @computed + FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency; + final WalletBase _wallet; final SettingsStore _settingsStore; final SendTemplateViewModel sendTemplateViewModel; @@ -208,7 +214,7 @@ abstract class SendViewModelBase with Store { state = TransactionCommitting(); await pendingTransaction!.commit(); - if (pendingTransaction!.id?.isNotEmpty ?? false) { + if (pendingTransaction!.id.isNotEmpty) { _settingsStore.shouldSaveRecipientAddress ? await transactionDescriptionBox.add(TransactionDescription( id: pendingTransaction!.id, @@ -283,4 +289,12 @@ abstract class SendViewModelBase with Store { bool _isEqualCurrency(String currency) => currency.toLowerCase() == _wallet.currency.title.toLowerCase(); + + @action + void onClose() => + _settingsStore.fiatCurrency = fiatFromSettings; + + @action + void setFiatCurrency(FiatCurrency fiat) => + _settingsStore.fiatCurrency = fiat; } diff --git a/lib/view_model/settings/display_settings_view_model.dart b/lib/view_model/settings/display_settings_view_model.dart new file mode 100644 index 000000000..4e73b3399 --- /dev/null +++ b/lib/view_model/settings/display_settings_view_model.dart @@ -0,0 +1,57 @@ +import 'package:cake_wallet/entities/balance_display_mode.dart'; +import 'package:cake_wallet/entities/fiat_currency.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:mobx/mobx.dart'; + +part 'display_settings_view_model.g.dart'; + +class DisplaySettingsViewModel = DisplaySettingsViewModelBase with _$DisplaySettingsViewModel; + +abstract class DisplaySettingsViewModelBase with Store { + DisplaySettingsViewModelBase( + this._settingsStore, + ); + + final SettingsStore _settingsStore; + + @computed + FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency; + + @computed + String get languageCode => _settingsStore.languageCode; + + @computed + BalanceDisplayMode get balanceDisplayMode => _settingsStore.balanceDisplayMode; + + @computed + bool get shouldDisplayBalance => balanceDisplayMode == BalanceDisplayMode.displayableBalance; + + @computed + ThemeBase get theme => _settingsStore.currentTheme; + + @action + void setBalanceDisplayMode(BalanceDisplayMode value) => _settingsStore.balanceDisplayMode = value; + + @action + void setShouldDisplayBalance(bool value) { + if (value) { + _settingsStore.balanceDisplayMode = BalanceDisplayMode.displayableBalance; + } else { + _settingsStore.balanceDisplayMode = BalanceDisplayMode.hiddenBalance; + } + } + + @action + void onLanguageSelected(String code) { + _settingsStore.languageCode = code; + } + + @action + void setTheme(ThemeBase newTheme) { + _settingsStore.currentTheme = newTheme; + } + + @action + void setFiatCurrency(FiatCurrency value) => _settingsStore.fiatCurrency = value; +} diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart new file mode 100644 index 000000000..c57af50d9 --- /dev/null +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -0,0 +1,64 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cw_core/balance.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:mobx/mobx.dart'; +import 'package:package_info/package_info.dart'; + +part 'other_settings_view_model.g.dart'; + +class OtherSettingsViewModel = OtherSettingsViewModelBase with _$OtherSettingsViewModel; + +abstract class OtherSettingsViewModelBase with Store { + OtherSettingsViewModelBase(this._settingsStore, this._wallet) + : walletType = _wallet.type, + currentVersion = '' { + PackageInfo.fromPlatform() + .then((PackageInfo packageInfo) => currentVersion = packageInfo.version); + + final priority = _settingsStore.priority[_wallet.type]; + final priorities = priorityForWalletType(_wallet.type); + + if (!priorities.contains(priority)) { + _settingsStore.priority[_wallet.type] = priorities.first; + } + } + + final WalletType walletType; + final WalletBase, TransactionInfo> _wallet; + + @observable + String currentVersion; + + final SettingsStore _settingsStore; + + @computed + TransactionPriority get transactionPriority { + final priority = _settingsStore.priority[walletType]; + + if (priority == null) { + throw Exception('Unexpected type ${walletType.toString()}'); + } + + return priority; + } + + String getDisplayPriority(dynamic priority) { + final _priority = priority as TransactionPriority; + + if (_wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin) { + final rate = bitcoin!.getFeeRate(_wallet, _priority); + return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); + } + + return priority.toString(); + } + + void onDisplayPrioritySelected(TransactionPriority priority) => + _settingsStore.priority[_wallet.type] = priority; +} diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart new file mode 100644 index 000000000..88311bf1f --- /dev/null +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -0,0 +1,24 @@ +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:mobx/mobx.dart'; + +part 'privacy_settings_view_model.g.dart'; + +class PrivacySettingsViewModel = PrivacySettingsViewModelBase with _$PrivacySettingsViewModel; + +abstract class PrivacySettingsViewModelBase with Store { + PrivacySettingsViewModelBase(this._settingsStore); + + final SettingsStore _settingsStore; + + @computed + bool get disableExchange => _settingsStore.disableExchange; + + @computed + bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress; + + @action + void setShouldSaveRecipientAddress(bool value) => _settingsStore.shouldSaveRecipientAddress = value; + + @action + void setEnableExchange(bool value) => _settingsStore.disableExchange = value; +} diff --git a/lib/view_model/settings/security_settings_view_model.dart b/lib/view_model/settings/security_settings_view_model.dart new file mode 100644 index 000000000..4a88b633f --- /dev/null +++ b/lib/view_model/settings/security_settings_view_model.dart @@ -0,0 +1,25 @@ +import 'package:cake_wallet/entities/biometric_auth.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:mobx/mobx.dart'; + +part 'security_settings_view_model.g.dart'; + +class SecuritySettingsViewModel = SecuritySettingsViewModelBase with _$SecuritySettingsViewModel; + +abstract class SecuritySettingsViewModelBase with Store { + SecuritySettingsViewModelBase(this._settingsStore) : _biometricAuth = BiometricAuth(); + + final BiometricAuth _biometricAuth; + final SettingsStore _settingsStore; + + @computed + bool get allowBiometricalAuthentication => _settingsStore.allowBiometricalAuthentication; + + @action + Future biometricAuthenticated() async { + return await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated(); + } + + @action + void setAllowBiometricalAuthentication(bool value) => _settingsStore.allowBiometricalAuthentication = value; +} diff --git a/lib/view_model/settings/settings_view_model.dart b/lib/view_model/settings/settings_view_model.dart deleted file mode 100644 index f85d2c459..000000000 --- a/lib/view_model/settings/settings_view_model.dart +++ /dev/null @@ -1,342 +0,0 @@ -import 'package:cake_wallet/entities/language_service.dart'; -import 'package:cake_wallet/store/yat/yat_store.dart'; -import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:mobx/mobx.dart'; -import 'package:package_info/package_info.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cake_wallet/entities/biometric_auth.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/entities/balance_display_mode.dart'; -import 'package:cake_wallet/entities/fiat_currency.dart'; -import 'package:cw_core/node.dart'; -import 'package:cake_wallet/monero/monero.dart'; -import 'package:cake_wallet/haven/haven.dart'; -import 'package:cake_wallet/entities/action_list_display_mode.dart'; -import 'package:cake_wallet/view_model/settings/version_list_item.dart'; -import 'package:cake_wallet/view_model/settings/picker_list_item.dart'; -import 'package:cake_wallet/view_model/settings/regular_list_item.dart'; -import 'package:cake_wallet/view_model/settings/settings_list_item.dart'; -import 'package:cake_wallet/view_model/settings/switcher_list_item.dart'; -import 'package:cake_wallet/src/screens/auth/auth_page.dart'; -import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cw_core/transaction_history.dart'; -import 'package:cw_core/balance.dart'; -import 'package:cw_core/transaction_info.dart'; -import 'package:cw_core/transaction_priority.dart'; -import 'package:cake_wallet/themes/theme_base.dart'; -import 'package:cake_wallet/themes/theme_list.dart'; -import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; -import 'package:cake_wallet/wallet_type_utils.dart'; - -part 'settings_view_model.g.dart'; - -class SettingsViewModel = SettingsViewModelBase with _$SettingsViewModel; - -List priorityForWalletType(WalletType type) { - switch (type) { - case WalletType.monero: - return monero!.getTransactionPriorities(); - case WalletType.bitcoin: - return bitcoin!.getTransactionPriorities(); - case WalletType.litecoin: - return bitcoin!.getLitecoinTransactionPriorities(); - case WalletType.haven: - return haven!.getTransactionPriorities(); - default: - return []; - } -} - -abstract class SettingsViewModelBase with Store { - SettingsViewModelBase( - this._settingsStore, - this._yatStore, - WalletBase, - TransactionInfo> - wallet) - : itemHeaders = {}, - _walletType = wallet.type, - _biometricAuth = BiometricAuth(), - sections = >[], - currentVersion = '' { - PackageInfo.fromPlatform().then( - (PackageInfo packageInfo) => currentVersion = packageInfo.version); - - final priority = _settingsStore.priority[wallet.type]; - final priorities = priorityForWalletType(wallet.type); - - if (!priorities.contains(priority)) { - _settingsStore.priority[wallet.type] = priorities.first; - } - - //var connectYatUrl = YatLink.baseUrl + YatLink.signInSuffix; - //final connectYatUrlParameters = - // _yatStore.defineQueryParameters(); - - //if (connectYatUrlParameters.isNotEmpty) { - // connectYatUrl += YatLink.queryParameter + connectYatUrlParameters; - //} - - //var manageYatUrl = YatLink.baseUrl + YatLink.managePath; - //final manageYatUrlParameters = - // _yatStore.defineQueryParameters(); - - //if (manageYatUrlParameters.isNotEmpty) { - // manageYatUrl += YatLink.queryParameter + manageYatUrlParameters; - //} - - //var createNewYatUrl = YatLink.startFlowUrl; - //final createNewYatUrlParameters = - // _yatStore.defineQueryParameters(); - - //if (createNewYatUrlParameters.isNotEmpty) { - // createNewYatUrl += '?sub1=' + createNewYatUrlParameters; - //} - - - sections = [ - [ - SwitcherListItem( - title: S.current.settings_display_balance, - value: () => balanceDisplayMode == BalanceDisplayMode.displayableBalance, - onValueChange: (_, bool value) { - if (value) { - _settingsStore.balanceDisplayMode = BalanceDisplayMode.displayableBalance; - } else { - _settingsStore.balanceDisplayMode = BalanceDisplayMode.hiddenBalance; - } - }, - ), - if (!isHaven) - PickerListItem( - title: S.current.settings_currency, - searchHintText: S.current.search_currency, - items: FiatCurrency.all, - selectedItem: () => fiatCurrency, - onItemSelected: (FiatCurrency currency) => - setFiatCurrency(currency), - images: FiatCurrency.all.map( - (e) => Image.asset("assets/images/flags/${e.countryCode}.png")) - .toList(), - isGridView: true, - matchingCriteria: (FiatCurrency currency, String searchText) { - return currency.title.toLowerCase().contains(searchText) || currency.fullName.toLowerCase().contains(searchText); - }, - ), - PickerListItem( - title: S.current.settings_fee_priority, - items: priorityForWalletType(wallet.type), - displayItem: (dynamic priority) { - final _priority = priority as TransactionPriority; - - if (wallet.type == WalletType.bitcoin - || wallet.type == WalletType.litecoin) { - final rate = bitcoin!.getFeeRate(wallet, _priority); - return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); - } - - return priority.toString(); - }, - selectedItem: () => transactionPriority, - onItemSelected: (TransactionPriority priority) => - _settingsStore.priority[wallet.type] = priority), - SwitcherListItem( - title: S.current.settings_save_recipient_address, - value: () => shouldSaveRecipientAddress, - onValueChange: (_, bool value) => - setShouldSaveRecipientAddress(value)) - ], - [ - RegularListItem( - title: S.current.settings_change_pin, - handler: (BuildContext context) { - Navigator.of(context).pushNamed(Routes.auth, arguments: - (bool isAuthenticatedSuccessfully, AuthPageState auth) { - auth.close( - route: isAuthenticatedSuccessfully ? Routes.setupPin : null, - arguments: (PinCodeState setupPinContext, - String _) { - setupPinContext.close(); - }, - ); - }); - }), - PickerListItem( - title: S.current.settings_change_language, - searchHintText: S.current.search_language, - items: LanguageService.list.keys.toList(), - displayItem: (dynamic code) { - return LanguageService.list[code] ?? ''; - }, - selectedItem: () => _settingsStore.languageCode, - onItemSelected: (String code) { - _settingsStore.languageCode = code; - }, - images: LanguageService.list.keys.map( - (e) => Image.asset("assets/images/flags/${LanguageService.localeCountryCode[e]}.png")) - .toList(), - matchingCriteria: (String code, String searchText) { - return LanguageService.list[code]?.toLowerCase().contains(searchText) ?? false; - }, - ), - SwitcherListItem( - title: S.current.settings_allow_biometrical_authentication, - value: () => allowBiometricalAuthentication, - onValueChange: (BuildContext context, bool value) { - if (value) { - Navigator.of(context).pushNamed(Routes.auth, arguments: - (bool isAuthenticatedSuccessfully, - AuthPageState auth) async { - if (isAuthenticatedSuccessfully) { - if (await _biometricAuth.canCheckBiometrics() && - await _biometricAuth.isAuthenticated()) { - setAllowBiometricalAuthentication( - isAuthenticatedSuccessfully); - } - } else { - setAllowBiometricalAuthentication( - isAuthenticatedSuccessfully); - } - - auth.close(); - }); - } else { - setAllowBiometricalAuthentication(value); - } - }), - SwitcherListItem( - title: S.current.disable_exchange, - value: () => _settingsStore.disableExchange, - onValueChange: (BuildContext context, bool value) { - _settingsStore.disableExchange = value; - }), - ChoicesListItem( - title: S.current.color_theme, - items: ThemeList.all, - selectedItem: theme, - onItemSelected: (ThemeBase theme) => _settingsStore.currentTheme = theme, - ), - ], - //[ - //if (_yatStore.emoji.isNotEmpty) ...[ - // LinkListItem( - // title: S.current.manage_yats, - // link: manageYatUrl, - // linkTitle: ''), - //] else ...[ - //LinkListItem( - // title: S.current.connect_yats, - // link: connectYatUrl, - // linkTitle: ''), - //LinkListItem( - // title: 'Create new Yats', - // link: createNewYatUrl, - // linkTitle: '') - //] - //], - [ - RegularListItem( - title: S.current.settings_terms_and_conditions, - handler: (BuildContext context) => - Navigator.of(context).pushNamed(Routes.readDisclaimer), - ) - ], - [VersionListItem(title: currentVersion)] - ]; - } - - @observable - String currentVersion; - - @computed - Node get node => _settingsStore.getCurrentNode(_walletType); - - @computed - FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency; - - @computed - ObservableList get actionlistDisplayMode => - _settingsStore.actionlistDisplayMode; - - @computed - TransactionPriority get transactionPriority { - final priority = _settingsStore.priority[_walletType]; - - if (priority == null) { - throw Exception('Unexpected type ${_walletType.toString()}'); - } - - return priority; - } - - @computed - BalanceDisplayMode get balanceDisplayMode => - _settingsStore.balanceDisplayMode; - - @computed - bool get shouldSaveRecipientAddress => - _settingsStore.shouldSaveRecipientAddress; - - @computed - bool get allowBiometricalAuthentication => - _settingsStore.allowBiometricalAuthentication; - - @computed - ThemeBase get theme => _settingsStore.currentTheme; - - bool get isBitcoinBuyEnabled => _settingsStore.isBitcoinBuyEnabled; - - final Map itemHeaders; - List> sections; - final SettingsStore _settingsStore; - final YatStore _yatStore; - final WalletType _walletType; - final BiometricAuth _biometricAuth; - - @action - void setBalanceDisplayMode(BalanceDisplayMode value) => - _settingsStore.balanceDisplayMode = value; - - @action - void setFiatCurrency(FiatCurrency value) => - _settingsStore.fiatCurrency = value; - - @action - void setShouldSaveRecipientAddress(bool value) => - _settingsStore.shouldSaveRecipientAddress = value; - - @action - void setAllowBiometricalAuthentication(bool value) => - _settingsStore.allowBiometricalAuthentication = value; - - @action - void toggleTransactionsDisplay() => - actionlistDisplayMode.contains(ActionListDisplayMode.transactions) - ? _hideTransaction() - : _showTransaction(); - - @action - void toggleTradesDisplay() => - actionlistDisplayMode.contains(ActionListDisplayMode.trades) - ? _hideTrades() - : _showTrades(); - - @action - void _hideTransaction() => - actionlistDisplayMode.remove(ActionListDisplayMode.transactions); - - @action - void _hideTrades() => - actionlistDisplayMode.remove(ActionListDisplayMode.trades); - - @action - void _showTransaction() => - actionlistDisplayMode.add(ActionListDisplayMode.transactions); - - @action - void _showTrades() => actionlistDisplayMode.add(ActionListDisplayMode.trades); -} diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index 8992071fd..f8729715b 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -184,7 +184,7 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.monero: return 'https://monero.com/tx/${txId}'; case WalletType.bitcoin: - return 'https://www.blockchain.com/btc/tx/${txId}'; + return 'https://mempool.space/tx/${txId}'; case WalletType.litecoin: return 'https://blockchair.com/litecoin/transaction/${txId}'; case WalletType.haven: @@ -199,7 +199,7 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.monero: return S.current.view_transaction_on + 'Monero.com'; case WalletType.bitcoin: - return S.current.view_transaction_on + 'Blockchain.com'; + return S.current.view_transaction_on + 'mempool.space'; case WalletType.litecoin: return S.current.view_transaction_on + 'Blockchair.com'; case WalletType.haven: diff --git a/model_generator.sh b/model_generator.sh new file mode 100644 index 000000000..f4ef8bdad --- /dev/null +++ b/model_generator.sh @@ -0,0 +1,5 @@ +cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +flutter packages pub run build_runner build --delete-conflicting-outputs \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index f5170b84e..95fd0b6ff 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "GETRENNT", "sync_status_connecting" : "VERBINDEN", "sync_status_connected" : "VERBUNDEN", + "sync_status_attempting_sync" : "SYNC VERSUCHEN", "transaction_priority_slow" : "Langsam", @@ -652,5 +653,12 @@ "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", + "connection_sync": "Verbindung und Synchronisierung", + "security_and_backup": "Sicherheit und Datensicherung", + "create_backup": "Backup erstellen", + "privacy_settings": "Datenschutzeinstellungen", + "privacy": "Datenschutz", + "display_settings": "Anzeigeeinstellungen", + "other_settings": "Andere Einstellungen", "disable_exchange": "Exchange deaktivieren" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index b62dbd984..a470ccd70 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "DISCONNECTED", "sync_status_connecting" : "CONNECTING", "sync_status_connected" : "CONNECTED", + "sync_status_attempting_sync" : "ATTEMPTING SYNC", "transaction_priority_slow" : "Slow", @@ -652,5 +653,12 @@ "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", + "connection_sync": "Connection and sync", + "security_and_backup": "Security and backup", + "create_backup": "Create backup", + "privacy_settings": "Privacy settings", + "privacy": "Privacy", + "display_settings": "Display settings", + "other_settings": "Other settings", "disable_exchange": "Disable exchange" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index beff1af8d..ad0476df4 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "DESCONECTADO", "sync_status_connecting" : "CONECTANDO", "sync_status_connected" : "CONECTADO", + "sync_status_attempting_sync" : "INTENTAR SINCRONIZAR", "transaction_priority_slow" : "Lento", @@ -652,5 +653,12 @@ "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", + "connection_sync": "Conexión y sincronización", + "security_and_backup": "Seguridad y respaldo", + "create_backup": "Crear copia de seguridad", + "privacy_settings": "Configuración de privacidad", + "privacy": "Privacidad", + "display_settings": "Configuración de pantalla", + "other_settings": "Otras configuraciones", "disable_exchange": "Deshabilitar intercambio" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index fa1d01e22..9666df9cb 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -354,6 +354,7 @@ "sync_status_failed_connect" : "DÉCONNECTÉ", "sync_status_connecting" : "CONNEXION EN COURS", "sync_status_connected" : "CONNECTÉ", + "sync_status_attempting_sync" : "TENTATIVE DE SYNCHRONISATION", "transaction_priority_slow" : "Lent", @@ -650,5 +651,12 @@ "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", + "connection_sync": "Connexion et synchronisation", + "security_and_backup": "Sécurité et sauvegarde", + "create_backup": "Créer une sauvegarde", + "privacy_settings": "Paramètres de confidentialité", + "privacy": "Confidentialité", + "display_settings": "Paramètres d'affichage", + "other_settings": "Autres paramètres", "disable_exchange": "Désactiver l'échange" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index c7b6ece40..c7144d14a 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "डिस्कनेक्ट किया गया", "sync_status_connecting" : "कनेक्ट", "sync_status_connected" : "जुड़े हुए", + "sync_status_attempting_sync" : "सिंक करने का प्रयास", "transaction_priority_slow" : "धीरे", @@ -652,5 +653,12 @@ "use_suggested": "सुझाए गए का प्रयोग करें", "do_not_share_warning_text" : "इन्हें समर्थन सहित किसी और के साथ साझा न करें।\n\nवे आपका पैसा चुरा लेंगे!", "help": "मदद करना", + "connection_sync": "कनेक्शन और सिंक", + "security_and_backup": "सुरक्षा और बैकअप", + "create_backup": "बैकअप बनाएँ", + "privacy_settings": "गोपनीयता सेटिंग्स", + "privacy": "गोपनीयता", + "display_settings": "प्रदर्शन सेटिंग्स", + "other_settings": "अन्य सेटिंग्स", "disable_exchange": "एक्सचेंज अक्षम करें" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 532a4d63a..897075ce7 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "ISKLJUČENO", "sync_status_connecting" : "SPAJANJE", "sync_status_connected" : "SPOJENO", + "sync_status_attempting_sync" : "POKUŠAJ SINKRONIZACIJE", "transaction_priority_slow" : "Sporo", @@ -652,5 +653,12 @@ "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", + "connection_sync": "Povezivanje i sinkronizacija", + "security_and_backup": "Sigurnost i sigurnosna kopija", + "create_backup": "Stvori sigurnosnu kopiju", + "privacy_settings": "Postavke privatnosti", + "privacy": "Privatnost", + "display_settings": "Postavke zaslona", + "other_settings": "Ostale postavke", "disable_exchange": "Onemogući exchange" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index cb5209fc3..a8e30ae06 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "DISCONNESSO", "sync_status_connecting" : "CONNESSIONE", "sync_status_connected" : "CONNESSO", + "sync_status_attempting_sync" : "TENTATIVO DI SINCRONIZZAZIONE", "transaction_priority_slow" : "Bassa", @@ -652,5 +653,12 @@ "use_suggested": "Usa suggerito", "do_not_share_warning_text" : "Non condividerli con nessun altro, incluso il supporto.\n\nTi ruberanno i soldi!", "help": "aiuto", + "connection_sync": "Connessione e sincronizzazione", + "security_and_backup": "Sicurezza e backup", + "create_backup": "Crea backup", + "privacy_settings": "Impostazioni privacy", + "privacy": "Privacy", + "display_settings": "Impostazioni di visualizzazione", + "other_settings": "Altre impostazioni", "disable_exchange": "Disabilita scambio" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 2d1c291ce..d5553ff10 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "切断されました", "sync_status_connecting" : "接続中", "sync_status_connected" : "接続済み", + "sync_status_attempting_sync" : "同期を試みています", "transaction_priority_slow" : "スロー", @@ -652,5 +653,12 @@ "use_suggested": "推奨を使用", "do_not_share_warning_text" : "サポートを含め、これらを他の誰とも共有しないでください。\n\n彼らはあなたのお金を盗みます!", "help": "ヘルプ", + "connection_sync": "接続と同期", + "security_and_backup": "セキュリティとバックアップ", + "create_backup": "バックアップを作成", + "privacy_settings": "プライバシー設定", + "privacy": "プライバシー", + "display_settings": "表示設定", + "other_settings": "その他の設定", "disable_exchange": "交換を無効にする" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index f24e736cb..a374e18ad 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "연결 해제", "sync_status_connecting" : "연결 중", "sync_status_connected" : "연결됨", + "sync_status_attempting_sync" : "동기화 시도 중", "transaction_priority_slow" : "느린", @@ -652,5 +653,12 @@ "use_suggested": "추천 사용", "do_not_share_warning_text" : "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n그들은 당신의 돈을 훔칠 것입니다!", "help": "돕다", + "connection_sync": "연결 및 동기화", + "security_and_backup": "보안 및 백업", + "create_backup": "백업 생성", + "privacy_settings": "개인정보 설정", + "privacy": "프라이버시", + "display_settings": "디스플레이 설정", + "other_settings": "기타 설정", "disable_exchange": "교환 비활성화" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 5663b0357..286735406 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "LOSGEKOPPELD", "sync_status_connecting" : "AANSLUITING", "sync_status_connected" : "VERBONDEN", + "sync_status_attempting_sync" : "SYNCHRONISATIE PROBEREN", "transaction_priority_slow" : "Langzaam", @@ -652,5 +653,12 @@ "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", + "connection_sync": "Verbinding en synchronisatie", + "security_and_backup": "Beveiliging en back-up", + "create_backup": "Maak een back-up", + "privacy_settings": "Privacy-instellingen", + "privacy": "Privacy", + "display_settings": "Weergave-instellingen", + "other_settings": "Andere instellingen", "disable_exchange": "Uitwisseling uitschakelen" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index f2a414ae2..9ec4ce591 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "NIEPOWIĄZANY", "sync_status_connecting" : "ZŁĄCZONY", "sync_status_connected" : "POŁĄCZONY", + "sync_status_attempting_sync" : "PRÓBA SYNCHRONIZACJI", "transaction_priority_slow" : "Powolny", @@ -652,5 +653,12 @@ "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", + "connection_sync": "Połączenie i synchronizacja", + "security_and_backup": "Bezpieczeństwo i kopia zapasowa", + "create_backup": "Utwórz kopię zapasową", + "privacy_settings": "Ustawienia prywatności", + "privacy": "Prywatność", + "display_settings": "Ustawienia wyświetlania", + "other_settings": "Inne ustawienia", "disable_exchange": "Wyłącz wymianę" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 25318dc2d..6dc3df4e0 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "DESCONECTADO", "sync_status_connecting" : "CONECTANDO", "sync_status_connected" : "CONECTADO", + "sync_status_attempting_sync" : "TENTANDO SINCRONIZAR", "transaction_priority_slow" : "Lenta", @@ -652,5 +653,12 @@ "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", + "connection_sync": "Conexão e sincronização", + "security_and_backup": "Segurança e backup", + "create_backup": "Criar backup", + "privacy_settings": "Configurações de privacidade", + "privacy": "Privacidade", + "display_settings": "Configurações de exibição", + "other_settings": "Outras configurações", "disable_exchange": "Desativar troca" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index a907e5765..e08cc74a3 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "ОТКЛЮЧЕНО", "sync_status_connecting" : "ПОДКЛЮЧЕНИЕ", "sync_status_connected" : "ПОДКЛЮЧЕНО", + "sync_status_attempting_sync" : "ПОПЫТКА СИНХРОНИЗАЦИИ", "transaction_priority_slow" : "Медленный", @@ -652,5 +653,12 @@ "use_suggested": "Использовать предложенный", "do_not_share_warning_text" : "Не делитесь ими с кем-либо еще, в том числе со службой поддержки.\n\nОни украдут ваши деньги!", "help": "помощь", + "connection_sync": "Подключение и синхронизация", + "security_and_backup": "Безопасность и резервное копирование", + "create_backup": "Создать резервную копию", + "privacy_settings": "Настройки конфиденциальности", + "privacy": "Конфиденциальность", + "display_settings": "Настройки отображения", + "other_settings": "Другие настройки", "disable_exchange": "Отключить обмен" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 91042e91b..3c98cb126 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -355,6 +355,7 @@ "sync_status_failed_connect" : "ВІДКЛЮЧЕНО", "sync_status_connecting" : "ПІДКЛЮЧЕННЯ", "sync_status_connected" : "ПІДКЛЮЧЕНО", + "sync_status_attempting_sync" : "СПРОБА СИНХРОНІЗАЦІЇ", "transaction_priority_slow" : "Повільний", @@ -651,5 +652,12 @@ "use_suggested": "Використати запропоноване", "do_not_share_warning_text" : "Не повідомляйте їх нікому, включно зі службою підтримки.\n\nВони вкрадуть ваші гроші!", "help": "допомога", + "connection_sync": "Підключення та синхронізація", + "security_and_backup": "Безпека та резервне копіювання", + "create_backup": "Створити резервну копію", + "privacy_settings": "Налаштування конфіденційності", + "privacy": "Конфіденційність", + "display_settings": "Налаштування дисплея", + "other_settings": "Інші налаштування", "disable_exchange": "Вимкнути exchange" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 958e80d14..8434fa93c 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -356,6 +356,7 @@ "sync_status_failed_connect" : "断线", "sync_status_connecting" : "连接中", "sync_status_connected" : "已连接", + "sync_status_attempting_sync" : "嘗試同步", "transaction_priority_slow" : "慢速", @@ -650,5 +651,12 @@ "use_suggested": "使用建议", "do_not_share_warning_text" : "不要與其他任何人分享這些內容,包括支持。\n\n他們會偷你的錢!", "help": "帮助", + "connection_sync": "连接和同步", + "security_and_backup": "安全和备份", + "create_backup": "创建备份", + "privacy_settings": "隐私设置", + "privacy":"隐私", + "display_settings": "显示设置", + "other_settings": "其他设置", "disable_exchange": "禁用交换" }