dev
dart 120 lines 3.58 KB
Raw
1 import 'dart:io';
2 import 'package:cake_wallet/core/backup_service_v3.dart';
3 import 'package:cake_wallet/core/execution_state.dart';
4 import 'package:cake_wallet/core/secure_storage.dart';
5 import 'package:cake_wallet/entities/default_settings_migration.dart' show generateBackupPassword;
6 import 'package:cake_wallet/entities/secret_store_key.dart';
7 import 'package:cake_wallet/view_model/edit_backup_password_view_model.dart';
8 import 'package:cw_core/root_dir.dart';
9 import 'package:cw_core/utils/print_verbose.dart';
10 import 'package:mobx/mobx.dart';
11 import 'package:intl/intl.dart';
12 import 'package:cake_wallet/wallet_type_utils.dart';
13
14 part 'backup_view_model.g.dart';
15
16 class BackupExportFile {
17 BackupExportFile(this.file, {required this.name});
18
19 final String name;
20 final File file;
21 }
22
23 class BackupViewModel = BackupViewModelBase with _$BackupViewModel;
24
25 abstract class BackupViewModelBase with Store {
26 BackupViewModelBase(this.secureStorage, this.backupService, this.editBackupPasswordViewModel)
27 : isBackupPasswordVisible = false,
28 backupPassword = '',
29 state = InitialExecutionState() {
30 init();
31
32 reaction((_) => editBackupPasswordViewModel.backupPassword, (value) {
33 if (value != backupPassword) {
34 backupPassword = value;
35 }
36 });
37
38 reaction((_) => backupPassword, (value) {
39 if (value != editBackupPasswordViewModel.backupPassword) {
40 editBackupPasswordViewModel.backupPassword = value;
41 }
42 });
43 }
44
45 final SecureStorage secureStorage;
46 final BackupServiceV3 backupService;
47 final EditBackupPasswordViewModel editBackupPasswordViewModel;
48
49 @observable
50 ExecutionState state;
51
52 @observable
53 bool isBackupPasswordVisible;
54
55 @observable
56 String backupPassword;
57
58 @action
59 Future<void> init() async {
60 final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
61 backupPassword = (await secureStorage.read(key: key)) ?? '';
62 if (backupPassword.isEmpty) {
63 generateBackupPassword(secureStorage);
64 }
65 }
66
67 @action
68 Future<BackupExportFile?> exportBackup() async {
69 try {
70 state = IsExecutingState();
71 final backupFile = await backupService.exportBackupFile(backupPassword);
72 state = ExecutedSuccessfullyState();
73 final now = DateTime.now();
74 final formatter = DateFormat('yyyy-MM-dd_Hm');
75 final snakeAppName = approximatedAppName.replaceAll(' ', '_').toLowerCase();
76 final fileName = '${snakeAppName}_backup_${formatter.format(now)}.zip';
77
78 return BackupExportFile(backupFile, name: fileName);
79 } catch (e) {
80 printV(e.toString());
81 state = FailureState(e.toString());
82 return null;
83 }
84 }
85
86 Future<String> saveBackupFileLocally(BackupExportFile backup) async {
87 final appDir = await getAppDir();
88 final path = '${appDir.path}/${backup.name}';
89 if (File(path).existsSync()) {
90 File(path).deleteSync();
91 }
92 await backup.file.copy(path);
93 return path;
94 }
95
96 Future<void> removeBackupFileLocally(BackupExportFile backup) async {
97 final appDir = await getAppDir();
98 final path = '${appDir.path}/${backup.name}';
99 if (File(path).existsSync()) {
100 File(path).deleteSync();
101 }
102 }
103
104 @action
105 void showMasterPassword() => isBackupPasswordVisible = true;
106
107 @action
108 Future<void> saveToDownload(String name, File file) async {
109 if (!Platform.isAndroid) {
110 return;
111 }
112 const downloadDirPath = '/storage/emulated/0/Download'; // For Android
113 final filePath = '$downloadDirPath/${name}';
114 final downloadFile = File(filePath);
115 if (downloadFile.existsSync()) {
116 downloadFile.deleteSync();
117 }
118 await file.copy(filePath);
119 }
120 }