@@ -27,7 +27,6 @@ import androidx.compose.runtime.mutableStateOf
27
27
import androidx.compose.runtime.setValue
28
28
import androidx.lifecycle.ViewModel
29
29
import androidx.lifecycle.viewModelScope
30
- import com.wire.android.BuildConfig
31
30
import com.wire.android.appLogger
32
31
import com.wire.android.datastore.UserDataStore
33
32
import com.wire.android.feature.analytics.AnonymousAnalyticsManagerImpl
@@ -38,15 +37,18 @@ import com.wire.android.util.dispatchers.DispatcherProvider
38
37
import com.wire.kalium.logic.data.asset.KaliumFileSystem
39
38
import com.wire.kalium.logic.feature.auth.ValidatePasswordResult
40
39
import com.wire.kalium.logic.feature.auth.ValidatePasswordUseCase
40
+ import com.wire.kalium.logic.feature.backup.BackupFileFormat
41
41
import com.wire.kalium.logic.feature.backup.CreateBackupResult
42
42
import com.wire.kalium.logic.feature.backup.CreateBackupUseCase
43
+ import com.wire.kalium.logic.feature.backup.CreateMPBackupUseCase
43
44
import com.wire.kalium.logic.feature.backup.RestoreBackupResult
44
45
import com.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.BackupIOFailure
45
46
import com.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.DecryptionFailure
46
47
import com.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.IncompatibleBackup
47
48
import com.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.InvalidPassword
48
49
import com.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.InvalidUserId
49
50
import com.wire.kalium.logic.feature.backup.RestoreBackupUseCase
51
+ import com.wire.kalium.logic.feature.backup.RestoreMPBackupUseCase
50
52
import com.wire.kalium.logic.feature.backup.VerifyBackupResult
51
53
import com.wire.kalium.logic.feature.backup.VerifyBackupUseCase
52
54
import com.wire.kalium.util.DateTimeUtil
@@ -60,16 +62,18 @@ import javax.inject.Inject
60
62
61
63
@Suppress(" LongParameterList" ," TooManyFunctions" )
62
64
@HiltViewModel
63
- class BackupAndRestoreViewModel
64
- @Injectconstructor (
65
+ class BackupAndRestoreViewModel @Inject constructor(
65
66
private val importBackup : RestoreBackupUseCase ,
67
+ private val importMpBackup : RestoreMPBackupUseCase ,
66
68
private val createBackupFile : CreateBackupUseCase ,
69
+ private val createMpBackupFile : CreateMPBackupUseCase ,
67
70
private val verifyBackup : VerifyBackupUseCase ,
68
71
private val validatePassword : ValidatePasswordUseCase ,
69
72
private val kaliumFileSystem : KaliumFileSystem ,
70
73
private val fileManager : FileManager ,
71
74
private val userDataStore : UserDataStore ,
72
- private val dispatcher: DispatcherProvider
75
+ private val dispatcher : DispatcherProvider ,
76
+ private val mpBackupSettings : MPBackupSettings ,
73
77
) : ViewModel() {
74
78
75
79
val createBackupPasswordState: TextFieldState = TextFieldState ()
@@ -111,13 +115,20 @@ class BackupAndRestoreViewModel
111
115
updateCreationProgress(PROGRESS_50 )
112
116
delay(SMALL_DELAY )
113
117
114
- when (val result= createBackupFile(createBackupPasswordState.text.toString())) {
118
+ val password= createBackupPasswordState.text.toString()
119
+
120
+ val result= if (mpBackupSettingsis MPBackupSettings .Enabled ) {
121
+ createMpBackupFile(password)
122
+ }else {
123
+ createBackupFile(password)
124
+ }
125
+
126
+ when (result) {
115
127
is CreateBackupResult .Success -> {
116
128
state= state.copy(backupCreationProgress= BackupCreationProgress .Finished (result.backupFileName))
117
129
latestCreatedBackup= BackupAndRestoreState .CreatedBackup (
118
130
result.backupFilePath,
119
131
result.backupFileName,
120
- result.backupFileSize,
121
132
createBackupPasswordState.text.isNotEmpty()
122
133
)
123
134
createBackupPasswordState.clearText()
@@ -170,27 +181,25 @@ class BackupAndRestoreViewModel
170
181
fun chooseBackupFileToRestore (uri : Uri )= viewModelScope.launch {
171
182
latestImportedBackupTempPath= kaliumFileSystem.tempFilePath(TEMP_IMPORTED_BACKUP_FILE_NAME )
172
183
fileManager.copyToPath(uri, latestImportedBackupTempPath)
173
- checkIfBackupEncrypted (latestImportedBackupTempPath)
184
+ verifyBackupFile (latestImportedBackupTempPath)
174
185
}
175
186
176
187
private fun showPasswordDialog () {
177
188
state= state.copy(restoreFileValidation= RestoreFileValidation .PasswordRequired )
178
189
}
179
190
180
- private suspend fun checkIfBackupEncrypted (importedBackupPath : Path )= withContext(dispatcher.main()) {
191
+ private suspend fun verifyBackupFile (importedBackupPath : Path )= withContext(dispatcher.main()) {
181
192
when (val result= verifyBackup(importedBackupPath)) {
182
193
is VerifyBackupResult .Success -> {
183
- when (result) {
184
- is VerifyBackupResult .Success .Encrypted -> showPasswordDialog()
185
- is VerifyBackupResult .Success .NotEncrypted -> importDatabase(importedBackupPath)
186
- VerifyBackupResult .Success .Web -> {
187
- if (BuildConfig .DEVELOPER_FEATURES_ENABLED ) {
188
- importDatabase(importedBackupPath)
189
- }else {
190
- state= state.copy(restoreFileValidation= RestoreFileValidation .IncompatibleBackup )
191
- AnonymousAnalyticsManagerImpl .sendEvent(event= AnalyticsEvent .BackupRestoreFailed )
192
- }
193
- }
194
+ state= state.copy(backupFileFormat= result.format)
195
+ if (result.isEncrypted) {
196
+ showPasswordDialog()
197
+ }else {
198
+ state= state.copy(
199
+ restoreFileValidation= RestoreFileValidation .ValidNonEncryptedBackup ,
200
+ backupRestoreProgress= BackupRestoreProgress .InProgress (PROGRESS_75 )
201
+ )
202
+ restoreBackup(importedBackupPath,null )
194
203
}
195
204
}
196
205
@@ -199,6 +208,15 @@ class BackupAndRestoreViewModel
199
208
val errorMessage= when (result) {
200
209
is VerifyBackupResult .Failure .Generic -> result.error.toString()
201
210
VerifyBackupResult .Failure .InvalidBackupFile -> " No valid files found in the backup"
211
+ is VerifyBackupResult .Failure .UnsupportedVersion -> " Unsupported backup version:${result.version} "
212
+ VerifyBackupResult .Failure .InvalidUserId -> {
213
+ state= state.copy(
214
+ backupRestoreProgress= BackupRestoreProgress .Failed ,
215
+ restoreFileValidation= RestoreFileValidation .WrongBackup ,
216
+ restorePasswordValidation= PasswordValidation .Valid
217
+ )
218
+ " Invalid user ID"
219
+ }
202
220
}
203
221
204
222
AnonymousAnalyticsManagerImpl .sendEvent(event= AnalyticsEvent .BackupRestoreFailed )
@@ -207,30 +225,6 @@ class BackupAndRestoreViewModel
207
225
}
208
226
}
209
227
210
- private suspend fun importDatabase (importedBackupPath : Path ) {
211
- state= state.copy(
212
- restoreFileValidation= RestoreFileValidation .ValidNonEncryptedBackup ,
213
- backupRestoreProgress= BackupRestoreProgress .InProgress (PROGRESS_75 )
214
- )
215
- when (val result= importBackup(importedBackupPath,null )) {
216
- RestoreBackupResult .Success -> {
217
- updateCreationProgress(PROGRESS_75 )
218
- delay(SMALL_DELAY )
219
- state= state.copy(backupRestoreProgress= BackupRestoreProgress .Finished )
220
- AnonymousAnalyticsManagerImpl .sendEvent(event= AnalyticsEvent .BackupRestoreSucceeded )
221
- }
222
-
223
- is RestoreBackupResult .Failure -> {
224
- appLogger.e(" Error when restoring the backup db file caused by:${result.failure.cause} " )
225
- state= state.copy(
226
- restoreFileValidation= RestoreFileValidation .IncompatibleBackup ,
227
- backupRestoreProgress= BackupRestoreProgress .Failed
228
- )
229
- AnonymousAnalyticsManagerImpl .sendEvent(event= AnalyticsEvent .BackupRestoreFailed )
230
- }
231
- }
232
- }
233
-
234
228
fun restorePasswordProtectedBackup ()= viewModelScope.launch(dispatcher.main()) {
235
229
state= state.copy(
236
230
backupRestoreProgress= BackupRestoreProgress .InProgress (PROGRESS_50 ),
@@ -240,21 +234,8 @@ class BackupAndRestoreViewModel
240
234
val fileValidationState= state.restoreFileValidation
241
235
if (fileValidationStateis RestoreFileValidation .PasswordRequired ) {
242
236
state= state.copy(restorePasswordValidation= PasswordValidation .Entered )
243
- when (val result= importBackup(latestImportedBackupTempPath, restoreBackupPasswordState.text.toString())) {
244
- RestoreBackupResult .Success -> {
245
- state= state.copy(
246
- backupRestoreProgress= BackupRestoreProgress .Finished ,
247
- restorePasswordValidation= PasswordValidation .Valid
248
- )
249
- restoreBackupPasswordState.clearText()
250
- AnonymousAnalyticsManagerImpl .sendEvent(event= AnalyticsEvent .BackupRestoreSucceeded )
251
- }
252
237
253
- is RestoreBackupResult .Failure -> {
254
- mapBackupRestoreFailure(result.failure)
255
- AnonymousAnalyticsManagerImpl .sendEvent(event= AnalyticsEvent .BackupRestoreFailed )
256
- }
257
- }
238
+ restoreBackup(latestImportedBackupTempPath, restoreBackupPasswordState.text.toString())
258
239
}else {
259
240
state= state.copy(backupRestoreProgress= BackupRestoreProgress .Failed )
260
241
AnonymousAnalyticsManagerImpl .sendEvent(event= AnalyticsEvent .BackupRestoreFailed )
@@ -317,6 +298,30 @@ class BackupAndRestoreViewModel
317
298
}
318
299
}
319
300
301
+ private fun restoreBackup (backupFilePath : Path ,password : String? )= viewModelScope.launch {
302
+ val result= when (state.backupFileFormat) {
303
+ BackupFileFormat .ANDROID -> importBackup(backupFilePath, password)
304
+ BackupFileFormat .MULTIPLATFORM -> importMpBackup(backupFilePath, password)
305
+ }
306
+ when (result) {
307
+ RestoreBackupResult .Success -> {
308
+ updateCreationProgress(PROGRESS_75 )
309
+ delay(SMALL_DELAY )
310
+ state= state.copy(
311
+ backupRestoreProgress= BackupRestoreProgress .Finished ,
312
+ restorePasswordValidation= PasswordValidation .Valid
313
+ )
314
+ restoreBackupPasswordState.clearText()
315
+ AnonymousAnalyticsManagerImpl .sendEvent(event= AnalyticsEvent .BackupRestoreSucceeded )
316
+ }
317
+
318
+ is RestoreBackupResult .Failure -> {
319
+ mapBackupRestoreFailure(result.failure)
320
+ AnonymousAnalyticsManagerImpl .sendEvent(event= AnalyticsEvent .BackupRestoreFailed )
321
+ }
322
+ }
323
+ }
324
+
320
325
private suspend fun updateCreationProgress (progress : Float )= withContext(dispatcher.main()) {
321
326
state= state.copy(backupCreationProgress= BackupCreationProgress .InProgress (progress))
322
327
}