From 8a7ef39f198eb6e4b66b15d09fef932469c27fdc Mon Sep 17 00:00:00 2001 From: Rafael Saes <76502841+saltrafael@users.noreply.github.com> Date: Fri, 14 Jul 2023 17:28:01 -0300 Subject: [PATCH] Linux: fixes for wallet rename (#1000) * fix: missing MarketPlaceViewModel register * fix: no auth route on wallet list _loadWallet * fix: fixes for wallet rename with password flow * fix: missing monero condition * fix: navigator pop * fix: going back case --- cw_monero/lib/monero_wallet.dart | 67 ++++++++++++++----- lib/core/wallet_loading_service.dart | 8 +++ lib/di.dart | 5 ++ lib/src/screens/wallet/wallet_edit_page.dart | 37 +++++++++- .../screens/wallet_list/wallet_list_page.dart | 16 +++++ .../wallet_unlock_arguments.dart | 14 ++-- .../wallet_unlock/wallet_unlock_page.dart | 21 +++++- .../wallet_list/wallet_edit_view_model.dart | 9 +-- .../wallet_unlock_loadable_view_model.dart | 41 +++++++----- .../wallet_unlock_verifiable_view_model.dart | 42 +++++++----- lib/view_model/wallet_unlock_view_model.dart | 4 +- 11 files changed, 200 insertions(+), 64 deletions(-) diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 99f10486d..4fe36f891 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -276,26 +276,59 @@ abstract class MoneroWalletBase extends WalletBase renameWalletFiles(String newWalletName) async { - final currentWalletPath = await pathForWallet(name: name, type: type); - final currentCacheFile = File(currentWalletPath); - final currentKeysFile = File('$currentWalletPath.keys'); - final currentAddressListFile = File('$currentWalletPath.address.txt'); + final currentWalletDirPath = await pathForWalletDir(name: name, type: type); - final newWalletPath = await pathForWallet(name: newWalletName, type: type); + try { + // -- rename the waller folder -- + final currentWalletDir = + Directory(await pathForWalletDir(name: name, type: type)); + final newWalletDirPath = + await pathForWalletDir(name: newWalletName, type: type); + await currentWalletDir.rename(newWalletDirPath); - // Copies current wallet files into new wallet name's dir and files - if (currentCacheFile.existsSync()) { - await currentCacheFile.copy(newWalletPath); - } - if (currentKeysFile.existsSync()) { - await currentKeysFile.copy('$newWalletPath.keys'); - } - if (currentAddressListFile.existsSync()) { - await currentAddressListFile.copy('$newWalletPath.address.txt'); - } + // -- use new waller folder to rename files with old names still -- + final renamedWalletPath = newWalletDirPath + '/$name'; - // Delete old name's dir and files - await Directory(currentWalletPath).delete(recursive: true); + final currentCacheFile = File(renamedWalletPath); + final currentKeysFile = File('$renamedWalletPath.keys'); + final currentAddressListFile = File('$renamedWalletPath.address.txt'); + + final newWalletPath = + await pathForWallet(name: newWalletName, type: type); + + if (currentCacheFile.existsSync()) { + await currentCacheFile.rename(newWalletPath); + } + if (currentKeysFile.existsSync()) { + await currentKeysFile.rename('$newWalletPath.keys'); + } + if (currentAddressListFile.existsSync()) { + await currentAddressListFile.rename('$newWalletPath.address.txt'); + } + } catch (e) { + final currentWalletPath = await pathForWallet(name: name, type: type); + + final currentCacheFile = File(currentWalletPath); + final currentKeysFile = File('$currentWalletPath.keys'); + final currentAddressListFile = File('$currentWalletPath.address.txt'); + + final newWalletPath = + await pathForWallet(name: newWalletName, type: type); + + // Copies current wallet files into new wallet name's dir and files + if (currentCacheFile.existsSync()) { + await currentCacheFile.copy(newWalletPath); + } + if (currentKeysFile.existsSync()) { + await currentKeysFile.copy('$newWalletPath.keys'); + } + if (currentAddressListFile.existsSync()) { + await currentAddressListFile.copy('$newWalletPath.address.txt'); + } + + // Delete old name's dir and files + await Directory(currentWalletDirPath).delete(recursive: true); + } } @override diff --git a/lib/core/wallet_loading_service.dart b/lib/core/wallet_loading_service.dart index 4ce9fa4dd..9596015bc 100644 --- a/lib/core/wallet_loading_service.dart +++ b/lib/core/wallet_loading_service.dart @@ -25,6 +25,14 @@ class WalletLoadingService { await keyService.deleteWalletPassword(walletName: name); await walletService.rename(name, walletPassword, newName); + + // set shared preferences flag based on previous wallet name + if (type == WalletType.monero) { + final oldNameKey = PreferencesKey.moneroWalletUpdateV1Key(name); + final isPasswordUpdated = sharedPreferences.getBool(oldNameKey) ?? false; + final newNameKey = PreferencesKey.moneroWalletUpdateV1Key(newName); + await sharedPreferences.setBool(newNameKey, isPasswordUpdated); + } } Future load(WalletType type, String name, {String? password}) async { diff --git a/lib/di.dart b/lib/di.dart index a31b00d1f..d0ff9aaef 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -42,6 +42,7 @@ import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart'; import 'package:cake_wallet/view_model/anonpay_details_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart'; @@ -898,6 +899,8 @@ Future setup({ getIt.registerFactory(() => IoniaAnyPay( getIt.get(), getIt.get(), getIt.get().wallet!)); + getIt.registerFactory(()=> MarketPlaceViewModel(getIt.get())); + getIt.registerFactory(() => IoniaGiftCardsListViewModel(ioniaService: getIt.get())); getIt.registerFactory(() => IoniaAuthViewModel(ioniaService: getIt.get())); @@ -1067,6 +1070,7 @@ Future setup({ return WalletUnlockPage( getIt.get(param1: args), args.callback, + args.authPasswordHandler, closable: closable); }, instanceName: 'wallet_unlock_loadable'); @@ -1074,6 +1078,7 @@ Future setup({ return WalletUnlockPage( getIt.get(param1: args), args.callback, + args.authPasswordHandler, closable: closable); }, instanceName: 'wallet_unlock_verifiable'); diff --git a/lib/src/screens/wallet/wallet_edit_page.dart b/lib/src/screens/wallet/wallet_edit_page.dart index 3ff27f02f..d656fb838 100644 --- a/lib/src/screens/wallet/wallet_edit_page.dart +++ b/lib/src/screens/wallet/wallet_edit_page.dart @@ -2,8 +2,12 @@ import 'package:another_flushbar/flushbar.dart'; import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/core/wallet_name_validator.dart'; import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/auth/auth_page.dart'; +import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_arguments.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart'; @@ -94,9 +98,36 @@ class WalletEditPage extends BasePage { ); } else { try { - await walletEditViewModel.changeName(editingWallet); - Navigator.of(context).pop(); - walletEditViewModel.resetState(); + bool confirmed = false; + + if (SettingsStoreBase + .walletPasswordDirectInput) { + await Navigator.of(context).pushNamed( + Routes.walletUnlockLoadable, + arguments: WalletUnlockArguments( + authPasswordHandler: + (String password) async { + await walletEditViewModel + .changeName(editingWallet, + password: password); + }, + callback: (bool + isAuthenticatedSuccessfully, + AuthPageState auth) async { + if (isAuthenticatedSuccessfully) { + auth.close(); + confirmed = true; + } + }, + walletName: editingWallet.name, + walletType: editingWallet.type)); + } else { + await walletEditViewModel + .changeName(editingWallet); + confirmed = true; + } + + if (confirmed) Navigator.of(context).pop(); } catch (e) {} } } diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 3d3e5c153..aadd74e30 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -1,7 +1,9 @@ import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/core/auth_service.dart'; +import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_arguments.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; @@ -210,6 +212,20 @@ class WalletListBodyState extends State { } Future _loadWallet(WalletListItem wallet) async { + if (SettingsStoreBase.walletPasswordDirectInput) { + Navigator.of(context).pushNamed( + Routes.walletUnlockLoadable, + arguments: WalletUnlockArguments( + callback: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { + if (isAuthenticatedSuccessfully) { + auth.close(); + setState(() {}); + } + }, walletName: wallet.name, + walletType: wallet.type)); + return; + } + await widget.authService.authenticateAction(context, onAuthSuccess: (isAuthenticatedSuccessfully) async { if (!isAuthenticatedSuccessfully) { diff --git a/lib/src/screens/wallet_unlock/wallet_unlock_arguments.dart b/lib/src/screens/wallet_unlock/wallet_unlock_arguments.dart index 34b26548c..5b6d4dd16 100644 --- a/lib/src/screens/wallet_unlock/wallet_unlock_arguments.dart +++ b/lib/src/screens/wallet_unlock/wallet_unlock_arguments.dart @@ -1,13 +1,17 @@ import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cw_core/wallet_type.dart'; +typedef AuthPasswordHandler = Future Function(String); + class WalletUnlockArguments { - WalletUnlockArguments({ - required this.callback, - this.walletName, - this.walletType}); + WalletUnlockArguments( + {required this.callback, + this.walletName, + this.walletType, + this.authPasswordHandler}); final OnAuthenticationFinished callback; + final AuthPasswordHandler? authPasswordHandler; final String? walletName; final WalletType? walletType; -} \ No newline at end of file +} diff --git a/lib/src/screens/wallet_unlock/wallet_unlock_page.dart b/lib/src/screens/wallet_unlock/wallet_unlock_page.dart index f7e1968cf..42f5464c7 100644 --- a/lib/src/screens/wallet_unlock/wallet_unlock_page.dart +++ b/lib/src/screens/wallet_unlock/wallet_unlock_page.dart @@ -2,10 +2,10 @@ import 'package:another_flushbar/flushbar.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; +import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_arguments.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; -import 'package:cake_wallet/view_model/wallet_unlock_verifiable_view_model.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/view_model/wallet_unlock_view_model.dart'; @@ -17,10 +17,12 @@ class WalletUnlockPage extends StatefulWidget { WalletUnlockPage( this.walletUnlockViewModel, this.onAuthenticationFinished, + this.authPasswordHandler, {required this.closable}); final WalletUnlockViewModel walletUnlockViewModel; final OnAuthenticationFinished onAuthenticationFinished; + final AuthPasswordHandler? authPasswordHandler; final bool closable; @override @@ -204,7 +206,20 @@ class WalletUnlockPageState extends AuthPageState { child: Observer( builder: (_) => LoadingPrimaryButton( - onPressed: () => widget.walletUnlockViewModel.unlock(), + onPressed: () async { + if (widget.authPasswordHandler != null) { + try { + await widget.authPasswordHandler!(widget + .walletUnlockViewModel.password); + widget.walletUnlockViewModel.success(); + } catch (e) { + widget.walletUnlockViewModel.failure(e); + } + return; + } + + widget.walletUnlockViewModel.unlock(); + }, text: S.of(context).unlock, color: Colors.green, textColor: Colors.white, @@ -213,4 +228,4 @@ class WalletUnlockPageState extends AuthPageState { ])) )); } -} \ No newline at end of file +} diff --git a/lib/view_model/wallet_list/wallet_edit_view_model.dart b/lib/view_model/wallet_list/wallet_edit_view_model.dart index 0582c3f87..806d76022 100644 --- a/lib/view_model/wallet_list/wallet_edit_view_model.dart +++ b/lib/view_model/wallet_list/wallet_edit_view_model.dart @@ -32,11 +32,12 @@ abstract class WalletEditViewModelBase with Store { final WalletLoadingService _walletLoadingService; @action - Future changeName(WalletListItem walletItem) async { + Future changeName(WalletListItem walletItem, {String? password}) async { state = WalletEditRenamePending(); await _walletLoadingService.renameWallet( - walletItem.type, walletItem.name, newName); - _walletListViewModel.updateList(); + walletItem.type, walletItem.name, newName, + password: password); + resetState(); } @action @@ -45,11 +46,11 @@ abstract class WalletEditViewModelBase with Store { final walletService = getIt.get(param1: wallet.type); await walletService.remove(wallet.name); resetState(); - _walletListViewModel.updateList(); } @action void resetState() { + _walletListViewModel.updateList(); state = WalletEditViewModelInitialState(); } } diff --git a/lib/view_model/wallet_unlock_loadable_view_model.dart b/lib/view_model/wallet_unlock_loadable_view_model.dart index e8d328ade..e1e5d5238 100644 --- a/lib/view_model/wallet_unlock_loadable_view_model.dart +++ b/lib/view_model/wallet_unlock_loadable_view_model.dart @@ -7,16 +7,15 @@ import 'package:cake_wallet/view_model/wallet_unlock_view_model.dart'; part 'wallet_unlock_loadable_view_model.g.dart'; -class WalletUnlockLoadableViewModel = WalletUnlockLoadableViewModelBase with _$WalletUnlockLoadableViewModel; +class WalletUnlockLoadableViewModel = WalletUnlockLoadableViewModelBase + with _$WalletUnlockLoadableViewModel; - abstract class WalletUnlockLoadableViewModelBase extends WalletUnlockViewModel with Store { - WalletUnlockLoadableViewModelBase( - this._appStore, - this._walletLoadingService, { - required this.walletName, - required this.walletType}) - : password = '', - state = InitialExecutionState(); +abstract class WalletUnlockLoadableViewModelBase extends WalletUnlockViewModel + with Store { + WalletUnlockLoadableViewModelBase(this._appStore, this._walletLoadingService, + {required this.walletName, required this.walletType}) + : password = '', + state = InitialExecutionState(); final String walletName; @@ -43,14 +42,24 @@ class WalletUnlockLoadableViewModel = WalletUnlockLoadableViewModelBase with _$W Future unlock() async { try { state = InitialExecutionState(); - final wallet = await _walletLoadingService.load( - walletType, - walletName, - password: password); + final wallet = await _walletLoadingService.load(walletType, walletName, + password: password); _appStore.changeCurrentWallet(wallet); - state = ExecutedSuccessfullyState(); - } catch(e) { - state = FailureState(e.toString()); + success(); + } catch (e) { + failure(e.toString()); } } + + @override + @action + void success() { + state = ExecutedSuccessfullyState(); + } + + @override + @action + void failure(e) { + state = FailureState(e.toString()); + } } diff --git a/lib/view_model/wallet_unlock_verifiable_view_model.dart b/lib/view_model/wallet_unlock_verifiable_view_model.dart index ebfec0ff6..11fe3b674 100644 --- a/lib/view_model/wallet_unlock_verifiable_view_model.dart +++ b/lib/view_model/wallet_unlock_verifiable_view_model.dart @@ -7,15 +7,15 @@ import 'package:cake_wallet/view_model/wallet_unlock_view_model.dart'; part 'wallet_unlock_verifiable_view_model.g.dart'; -class WalletUnlockVerifiableViewModel = WalletUnlockVerifiableViewModelBase with _$WalletUnlockVerifiableViewModel; +class WalletUnlockVerifiableViewModel = WalletUnlockVerifiableViewModelBase + with _$WalletUnlockVerifiableViewModel; -abstract class WalletUnlockVerifiableViewModelBase extends WalletUnlockViewModel with Store { - WalletUnlockVerifiableViewModelBase( - this.appStore, { - required this.walletName, - required this.walletType}) - : password = '', - state = InitialExecutionState(); +abstract class WalletUnlockVerifiableViewModelBase extends WalletUnlockViewModel + with Store { + WalletUnlockVerifiableViewModelBase(this.appStore, + {required this.walletName, required this.walletType}) + : password = '', + state = InitialExecutionState(); final String walletName; @@ -38,12 +38,24 @@ abstract class WalletUnlockVerifiableViewModelBase extends WalletUnlockViewModel @override @action Future unlock() async { - try { - state = appStore.wallet!.password == password - ? ExecutedSuccessfullyState() - : FailureState(S.current.invalid_password) ; - } catch(e) { - state = FailureState('${S.current.invalid_password}\n${e.toString()}'); - } + try { + state = appStore.wallet!.password == password + ? ExecutedSuccessfullyState() + : FailureState(S.current.invalid_password); + } catch (e) { + failure('${S.current.invalid_password}\n${e.toString()}'); + } + } + + @override + @action + void success() { + state = ExecutedSuccessfullyState(); + } + + @override + @action + void failure(e) { + state = FailureState(e.toString()); } } diff --git a/lib/view_model/wallet_unlock_view_model.dart b/lib/view_model/wallet_unlock_view_model.dart index aff3a89d0..f0131c61f 100644 --- a/lib/view_model/wallet_unlock_view_model.dart +++ b/lib/view_model/wallet_unlock_view_model.dart @@ -6,4 +6,6 @@ abstract class WalletUnlockViewModel { void setPassword(String password); ExecutionState get state; Future unlock(); -} \ No newline at end of file + void success(); + void failure(dynamic e); +}