@@ -27,7 +27,6 @@ import androidx.compose.runtime.mutableStateOf
2727import androidx.compose.runtime.setValue
2828import androidx.lifecycle.ViewModel
2929import androidx.lifecycle.viewModelScope
30- import com.wire.android.BuildConfig
3130import com.wire.android.appLogger
3231import com.wire.android.datastore.UserDataStore
3332import com.wire.android.feature.analytics.AnonymousAnalyticsManagerImpl
@@ -38,15 +37,18 @@ import com.wire.android.util.dispatchers.DispatcherProvider
3837import com.wire.kalium.logic.data.asset.KaliumFileSystem
3938import com.wire.kalium.logic.feature.auth.ValidatePasswordResult
4039import com.wire.kalium.logic.feature.auth.ValidatePasswordUseCase
40+ import com.wire.kalium.logic.feature.backup.BackupFileFormat
4141import com.wire.kalium.logic.feature.backup.CreateBackupResult
4242import com.wire.kalium.logic.feature.backup.CreateBackupUseCase
43+ import com.wire.kalium.logic.feature.backup.CreateMPBackupUseCase
4344import com.wire.kalium.logic.feature.backup.RestoreBackupResult
4445import com.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.BackupIOFailure
4546import com.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.DecryptionFailure
4647import com.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.IncompatibleBackup
4748import com.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.InvalidPassword
4849import com.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.InvalidUserId
4950import com.wire.kalium.logic.feature.backup.RestoreBackupUseCase
51+ import com.wire.kalium.logic.feature.backup.RestoreMPBackupUseCase
5052import com.wire.kalium.logic.feature.backup.VerifyBackupResult
5153import com.wire.kalium.logic.feature.backup.VerifyBackupUseCase
5254import com.wire.kalium.util.DateTimeUtil
@@ -60,16 +62,18 @@ import javax.inject.Inject
6062
6163@Suppress(" LongParameterList" , " TooManyFunctions" )
6264@HiltViewModel
63- class BackupAndRestoreViewModel
64- @Inject constructor (
65+ class BackupAndRestoreViewModel @Inject constructor(
6566 private val importBackup : RestoreBackupUseCase ,
67+ private val importMpBackup : RestoreMPBackupUseCase ,
6668 private val createBackupFile : CreateBackupUseCase ,
69+ private val createMpBackupFile : CreateMPBackupUseCase ,
6770 private val verifyBackup : VerifyBackupUseCase ,
6871 private val validatePassword : ValidatePasswordUseCase ,
6972 private val kaliumFileSystem : KaliumFileSystem ,
7073 private val fileManager : FileManager ,
7174 private val userDataStore : UserDataStore ,
72- private val dispatcher: DispatcherProvider
75+ private val dispatcher : DispatcherProvider ,
76+ private val mpBackupSettings : MPBackupSettings ,
7377) : ViewModel() {
7478
7579 val createBackupPasswordState: TextFieldState = TextFieldState ()
@@ -111,13 +115,20 @@ class BackupAndRestoreViewModel
111115 updateCreationProgress(PROGRESS_50 )
112116 delay(SMALL_DELAY )
113117
114- when (val result = createBackupFile(createBackupPasswordState.text.toString())) {
118+ val password = createBackupPasswordState.text.toString()
119+
120+ val result = if (mpBackupSettings is MPBackupSettings .Enabled ) {
121+ createMpBackupFile(password)
122+ } else {
123+ createBackupFile(password)
124+ }
125+
126+ when (result) {
115127 is CreateBackupResult .Success -> {
116128 state = state.copy(backupCreationProgress = BackupCreationProgress .Finished (result.backupFileName))
117129 latestCreatedBackup = BackupAndRestoreState .CreatedBackup (
118130 result.backupFilePath,
119131 result.backupFileName,
120- result.backupFileSize,
121132 createBackupPasswordState.text.isNotEmpty()
122133 )
123134 createBackupPasswordState.clearText()
@@ -170,27 +181,25 @@ class BackupAndRestoreViewModel
170181 fun chooseBackupFileToRestore (uri : Uri ) = viewModelScope.launch {
171182 latestImportedBackupTempPath = kaliumFileSystem.tempFilePath(TEMP_IMPORTED_BACKUP_FILE_NAME )
172183 fileManager.copyToPath(uri, latestImportedBackupTempPath)
173- checkIfBackupEncrypted (latestImportedBackupTempPath)
184+ verifyBackupFile (latestImportedBackupTempPath)
174185 }
175186
176187 private fun showPasswordDialog () {
177188 state = state.copy(restoreFileValidation = RestoreFileValidation .PasswordRequired )
178189 }
179190
180- private suspend fun checkIfBackupEncrypted (importedBackupPath : Path ) = withContext(dispatcher.main()) {
191+ private suspend fun verifyBackupFile (importedBackupPath : Path ) = withContext(dispatcher.main()) {
181192 when (val result = verifyBackup(importedBackupPath)) {
182193 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 )
194203 }
195204 }
196205
@@ -199,6 +208,15 @@ class BackupAndRestoreViewModel
199208 val errorMessage = when (result) {
200209 is VerifyBackupResult .Failure .Generic -> result.error.toString()
201210 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+ }
202220 }
203221
204222 AnonymousAnalyticsManagerImpl .sendEvent(event = AnalyticsEvent .BackupRestoreFailed )
@@ -207,30 +225,6 @@ class BackupAndRestoreViewModel
207225 }
208226 }
209227
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-
234228 fun restorePasswordProtectedBackup () = viewModelScope.launch(dispatcher.main()) {
235229 state = state.copy(
236230 backupRestoreProgress = BackupRestoreProgress .InProgress (PROGRESS_50 ),
@@ -240,21 +234,8 @@ class BackupAndRestoreViewModel
240234 val fileValidationState = state.restoreFileValidation
241235 if (fileValidationState is RestoreFileValidation .PasswordRequired ) {
242236 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- }
252237
253- is RestoreBackupResult .Failure -> {
254- mapBackupRestoreFailure(result.failure)
255- AnonymousAnalyticsManagerImpl .sendEvent(event = AnalyticsEvent .BackupRestoreFailed )
256- }
257- }
238+ restoreBackup(latestImportedBackupTempPath, restoreBackupPasswordState.text.toString())
258239 } else {
259240 state = state.copy(backupRestoreProgress = BackupRestoreProgress .Failed )
260241 AnonymousAnalyticsManagerImpl .sendEvent(event = AnalyticsEvent .BackupRestoreFailed )
@@ -317,6 +298,30 @@ class BackupAndRestoreViewModel
317298 }
318299 }
319300
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+
320325 private suspend fun updateCreationProgress (progress : Float ) = withContext(dispatcher.main()) {
321326 state = state.copy(backupCreationProgress = BackupCreationProgress .InProgress (progress))
322327 }
0 commit comments