Fixes for backups for monero.com app

M committed Feb 2, 2022 at 14:40 UTC 05c4d26634a780339486a28472dd4eda976d1a17
8 files changed +65 -16
lib/core/backup_service.dart
+40 -2
@@ -14,6 +14,7 @@ import 'package:cake_wallet/entities/preferences_key.dart';
14 import 'package:cake_wallet/entities/secret_store_key.dart';
15 import 'package:cw_core/wallet_info.dart';
16 import 'package:cake_wallet/.secrets.g.dart' as secrets;
17 +import 'package:cake_wallet/wallet_types.g.dart';
18
19 class BackupService {
20 BackupService(this._flutterSecureStorage, this._walletInfoSource,
@@ -29,6 +30,7 @@ class BackupService {
30 final SharedPreferences _sharedPreferences;
31 final Box<WalletInfo> _walletInfoSource;
32 final KeyService _keyService;
33 + List<WalletInfo> _correctWallets;
34
35 Future<void> importBackup(Uint8List data, String password,
36 {String nonce = secrets.backupSalt}) async {
@@ -118,10 +120,35 @@ class BackupService {
120 }
121 });
122
123 + await _verifyWallets();
124 await _importKeychainDump(password, nonce: nonce);
125 await _importPreferencesDump();
126 }
127
128 + Future<void> _verifyWallets() async {
129 + final walletInfoSource = await _reloadHiveWalletInfoBox();
130 + _correctWallets = walletInfoSource
131 + .values
132 + .where((info) => availableWalletTypes.contains(info.type))
133 + .toList();
134 +
135 + if (_correctWallets.isEmpty) {
136 + throw Exception('Correct wallets not detected');
137 + }
138 + }
139 +
140 + Future<Box<WalletInfo>> _reloadHiveWalletInfoBox() async {
141 + final appDir = await getApplicationDocumentsDirectory();
142 + await Hive.close();
143 + Hive.init(appDir.path);
144 +
145 + if (!Hive.isAdapterRegistered(WalletInfo.typeId)) {
146 + Hive.registerAdapter(WalletInfoAdapter());
147 + }
148 +
149 + return await Hive.openBox<WalletInfo>(WalletInfo.boxName);
150 + }
151 +
152 Future<void> _importPreferencesDump() async {
153 final appDir = await getApplicationDocumentsDirectory();
154 final preferencesFile = File('${appDir.path}/~_preferences_dump');
@@ -132,15 +159,26 @@ class BackupService {
159
160 final data =
161 json.decode(preferencesFile.readAsStringSync()) as Map<String, Object>;
162 + String currentWalletName = data[PreferencesKey.currentWalletName] as String;
163 + int currentWalletType = data[PreferencesKey.currentWalletType] as int;
164 +
165 + final isCorrentCurrentWallet = _correctWallets
166 + .any((info) => info.name == currentWalletName &&
167 + info.type.index == currentWalletType);
168 +
169 + if (!isCorrentCurrentWallet) {
170 + currentWalletName = _correctWallets.first.name;
171 + currentWalletType = _correctWallets.first.type.index;
172 + }
173
174 await _sharedPreferences.setString(PreferencesKey.currentWalletName,
137 - data[PreferencesKey.currentWalletName] as String);
175 + currentWalletName);
176 await _sharedPreferences.setInt(PreferencesKey.currentNodeIdKey,
177 data[PreferencesKey.currentNodeIdKey] as int);
178 await _sharedPreferences.setInt(PreferencesKey.currentBalanceDisplayModeKey,
179 data[PreferencesKey.currentBalanceDisplayModeKey] as int);
180 await _sharedPreferences.setInt(PreferencesKey.currentWalletType,
143 - data[PreferencesKey.currentWalletType] as int);
181 + currentWalletType);
182 await _sharedPreferences.setString(PreferencesKey.currentFiatCurrencyKey,
183 data[PreferencesKey.currentFiatCurrencyKey] as String);
184 await _sharedPreferences.setBool(
lib/src/screens/dashboard/wallet_menu.dart
-1
@@ -52,7 +52,6 @@ class WalletMenu {
52 image: Image.asset('assets/images/open_book_menu.png',
53 height: 16, width: 16),
54 handler: () => Navigator.of(context).pushNamed(Routes.addressBook)),
55 - if(!isMoneroOnly)
55 WalletMenuItem(
56 title: S.current.backup,
57 image: Image.asset('assets/images/restore_wallet.png',
lib/src/screens/wallet_list/wallet_list_page.dart
+4 -2
@@ -80,7 +80,7 @@ class WalletListBodyState extends State<WalletListBody> {
80 : Theme.of(context).backgroundColor;
81 final row = GestureDetector(
82 onTap: () async {
83 - if (wallet.isCurrent) {
83 + if (wallet.isCurrent || !wallet.isEnabled) {
84 return;
85 }
86
@@ -132,7 +132,9 @@ class WalletListBodyState extends State<WalletListBody> {
132 crossAxisAlignment:
133 CrossAxisAlignment.center,
134 children: <Widget>[
135 - _imageFor(type: wallet.type),
135 + wallet.isEnabled
136 + ? _imageFor(type: wallet.type)
137 + : nonWalletTypeIcon,
138 SizedBox(width: 10),
139 Text(
140 wallet.name,
lib/src/screens/welcome/welcome_page.dart
+2 -7
@@ -161,13 +161,8 @@ class WelcomePage extends BasePage {
161 padding: EdgeInsets.only(top: 10),
162 child: PrimaryImageButton(
163 onPressed: () {
164 - if (isMoneroOnly) {
165 - Navigator.of(context).pushNamed(Routes.moneroRestoreWalletFromWelcome);
166 - } else {
167 - Navigator.pushNamed(context,
168 - Routes.restoreOptions);
169 - }
170 - },
164 + Navigator.pushNamed(context, Routes.restoreOptions);
165 + },
166 image: restoreWalletImage,
167 text: S
168 .of(context)
lib/view_model/backup_view_model.dart
+4 -2
@@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart';
7 import 'package:flutter_secure_storage/flutter_secure_storage.dart';
8 import 'package:mobx/mobx.dart';
9 import 'package:intl/intl.dart';
10 +import 'package:cake_wallet/wallet_type_utils.dart';
11
12 part 'backup_view_model.g.dart';
13
@@ -58,9 +59,10 @@ abstract class BackupViewModelBase with Store {
59 state = ExecutedSuccessfullyState();
60 final now = DateTime.now();
61 final formatter = DateFormat('yyyy-MM-dd_Hm');
62 + final snakeAppName = approximatedAppName.replaceAll(' ', '_').toLowerCase();
63 + final fileName = '${snakeAppName}_backup_${formatter.format(now)}';
64
62 - return BackupExportFile(backupContent.toList(),
63 - name: 'cake_wallet_backup_${formatter.format(now)}');
65 + return BackupExportFile(backupContent.toList(), name: fileName);
66 } catch (e) {
67 print(e.toString());
68 state = FailureState(e.toString());
lib/view_model/wallet_list/wallet_list_item.dart
+6 -1
@@ -3,10 +3,15 @@ import 'package:cw_core/wallet_type.dart';
3
4 class WalletListItem {
5 const WalletListItem(
6 - {@required this.name, @required this.type, @required this.key, this.isCurrent = false});
6 + {@required this.name,
7 + @required this.type,
8 + @required this.key,
9 + this.isCurrent = false,
10 + this.isEnabled = true});
11
12 final String name;
13 final WalletType type;
14 final bool isCurrent;
15 final dynamic key;
16 + final bool isEnabled;
17 }
lib/view_model/wallet_list/wallet_list_view_model.dart
+3 -1
@@ -8,6 +8,7 @@ import 'package:cw_core/wallet_service.dart';
8 import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
9 import 'package:cw_core/wallet_info.dart';
10 import 'package:cw_core/wallet_type.dart';
11 +import 'package:cake_wallet/wallet_types.g.dart';
12
13 part 'wallet_list_view_model.g.dart';
14
@@ -55,6 +56,7 @@ abstract class WalletListViewModelBase with Store {
56 type: info.type,
57 key: info.key,
58 isCurrent: info.name == _appStore.wallet.name &&
58 - info.type == _appStore.wallet.type)));
59 + info.type == _appStore.wallet.type,
60 + isEnabled: availableWalletTypes.contains(info.type))));
61 }
62 }
lib/wallet_type_utils.dart
+6
@@ -4,4 +4,10 @@ import 'package:cake_wallet/wallet_types.g.dart';
4 bool get isMoneroOnly {
5 return availableWalletTypes.length == 1
6 && availableWalletTypes.first == WalletType.monero;
7 +}
8 +
9 +String get approximatedAppName {
10 + return isMoneroOnly
11 + ? 'Monero.com'
12 + : 'Cake Wallet';
13 }
\ No newline at end of file