Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc4b39f4

Browse files
feat: cross platform backup (#WPB-10579) (#4006)
Co-authored-by: Vitor Hugo Schwaab <vitor@schwaab.dev>
1 parent16c8252 commitc4b39f4

File tree

11 files changed

+161
-85
lines changed

11 files changed

+161
-85
lines changed

‎app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,16 @@ class UseCaseModule {
362362
):ObserveSecurityClassificationLabelUseCase=
363363
coreLogic.getSessionScope(currentAccount).observeSecurityClassificationLabel
364364

365+
@ViewModelScoped
366+
@Provides
367+
funprovideCreateMpBackupUseCase(@KaliumCoreLogiccoreLogic:CoreLogic, @CurrentAccountcurrentAccount:UserId)=
368+
coreLogic.getSessionScope(currentAccount).multiPlatformBackup.create
369+
370+
@ViewModelScoped
371+
@Provides
372+
funprovideRestoreMpBackupUseCase(@KaliumCoreLogiccoreLogic:CoreLogic, @CurrentAccountcurrentAccount:UserId)=
373+
coreLogic.getSessionScope(currentAccount).multiPlatformBackup.restore
374+
365375
@ViewModelScoped
366376
@Provides
367377
funprovideUpdateApiVersionsScheduler(@KaliumCoreLogiccoreLogic:CoreLogic)=

‎app/src/main/kotlin/com/wire/android/di/accountScoped/BackupModule.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
*/
1818
packagecom.wire.android.di.accountScoped
1919

20+
importcom.wire.android.BuildConfig
2021
importcom.wire.android.di.CurrentAccount
2122
importcom.wire.android.di.KaliumCoreLogic
23+
importcom.wire.android.ui.home.settings.backup.MPBackupSettings
2224
importcom.wire.kalium.logic.CoreLogic
2325
importcom.wire.kalium.logic.data.user.UserId
2426
importcom.wire.kalium.logic.feature.backup.BackupScope
@@ -53,6 +55,13 @@ class BackupModule {
5355
funprovideRestoreBackupUseCase(backupScope:BackupScope)=
5456
backupScope.restore
5557

58+
@Provides
59+
funprovideMpBackupSettings()=if (BuildConfig.ENABLE_CROSSPLATFORM_BACKUP) {
60+
MPBackupSettings.Enabled
61+
}else {
62+
MPBackupSettings.Disabled
63+
}
64+
5665
@OptIn(DelicateKaliumApi::class)
5766
@ViewModelScoped
5867
@Provides

‎app/src/main/kotlin/com/wire/android/ui/debug/ExportObfuscatedCopyViewModel.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ class ExportObfuscatedCopyViewModelImpl @OptIn(DelicateKaliumApi::class) @Inject
8383
latestCreatedBackup=BackupAndRestoreState.CreatedBackup(
8484
result.backupFilePath,
8585
result.backupFileName,
86-
result.backupFileSize,
8786
false
8887
)
8988
}

‎app/src/main/kotlin/com/wire/android/ui/home/settings/backup/BackupAndRestoreState.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
packagecom.wire.android.ui.home.settings.backup
2020

2121
importcom.wire.kalium.logic.feature.auth.ValidatePasswordResult
22+
importcom.wire.kalium.logic.feature.backup.BackupFileFormat
2223
importokio.Path
2324

2425
data classBackupAndRestoreState(
@@ -27,10 +28,11 @@ data class BackupAndRestoreState(
2728
valrestorePasswordValidation:PasswordValidation,
2829
valbackupCreationProgress:BackupCreationProgress,
2930
vallastBackupData:Long?,
30-
valpasswordValidation:ValidatePasswordResult
31+
valpasswordValidation:ValidatePasswordResult,
32+
valbackupFileFormat:BackupFileFormat,
3133
) {
3234

33-
data classCreatedBackup(valpath:Path,valassetName:String,valassetSize:Long,valisEncrypted:Boolean)
35+
data classCreatedBackup(valpath:Path,valassetName:String,valisEncrypted:Boolean)
3436

3537
companionobject {
3638
valINITIAL_STATE=BackupAndRestoreState(
@@ -39,7 +41,8 @@ data class BackupAndRestoreState(
3941
backupCreationProgress=BackupCreationProgress.InProgress(),
4042
restorePasswordValidation=PasswordValidation.NotVerified,
4143
passwordValidation=ValidatePasswordResult.Valid,
42-
lastBackupData=null
44+
lastBackupData=null,
45+
backupFileFormat=BackupFileFormat.ANDROID,
4346
)
4447
}
4548
}

‎app/src/main/kotlin/com/wire/android/ui/home/settings/backup/BackupAndRestoreViewModel.kt

Lines changed: 62 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import androidx.compose.runtime.mutableStateOf
2727
importandroidx.compose.runtime.setValue
2828
importandroidx.lifecycle.ViewModel
2929
importandroidx.lifecycle.viewModelScope
30-
importcom.wire.android.BuildConfig
3130
importcom.wire.android.appLogger
3231
importcom.wire.android.datastore.UserDataStore
3332
importcom.wire.android.feature.analytics.AnonymousAnalyticsManagerImpl
@@ -38,15 +37,18 @@ import com.wire.android.util.dispatchers.DispatcherProvider
3837
importcom.wire.kalium.logic.data.asset.KaliumFileSystem
3938
importcom.wire.kalium.logic.feature.auth.ValidatePasswordResult
4039
importcom.wire.kalium.logic.feature.auth.ValidatePasswordUseCase
40+
importcom.wire.kalium.logic.feature.backup.BackupFileFormat
4141
importcom.wire.kalium.logic.feature.backup.CreateBackupResult
4242
importcom.wire.kalium.logic.feature.backup.CreateBackupUseCase
43+
importcom.wire.kalium.logic.feature.backup.CreateMPBackupUseCase
4344
importcom.wire.kalium.logic.feature.backup.RestoreBackupResult
4445
importcom.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.BackupIOFailure
4546
importcom.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.DecryptionFailure
4647
importcom.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.IncompatibleBackup
4748
importcom.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.InvalidPassword
4849
importcom.wire.kalium.logic.feature.backup.RestoreBackupResult.BackupRestoreFailure.InvalidUserId
4950
importcom.wire.kalium.logic.feature.backup.RestoreBackupUseCase
51+
importcom.wire.kalium.logic.feature.backup.RestoreMPBackupUseCase
5052
importcom.wire.kalium.logic.feature.backup.VerifyBackupResult
5153
importcom.wire.kalium.logic.feature.backup.VerifyBackupUseCase
5254
importcom.wire.kalium.util.DateTimeUtil
@@ -60,16 +62,18 @@ import javax.inject.Inject
6062

6163
@Suppress("LongParameterList","TooManyFunctions")
6264
@HiltViewModel
63-
classBackupAndRestoreViewModel
64-
@Injectconstructor(
65+
classBackupAndRestoreViewModel @Inject constructor(
6566
privatevalimportBackup:RestoreBackupUseCase,
67+
privatevalimportMpBackup:RestoreMPBackupUseCase,
6668
privatevalcreateBackupFile:CreateBackupUseCase,
69+
privatevalcreateMpBackupFile:CreateMPBackupUseCase,
6770
privatevalverifyBackup:VerifyBackupUseCase,
6871
privatevalvalidatePassword:ValidatePasswordUseCase,
6972
privatevalkaliumFileSystem:KaliumFileSystem,
7073
privatevalfileManager:FileManager,
7174
privatevaluserDataStore:UserDataStore,
72-
privateval dispatcher:DispatcherProvider
75+
privatevaldispatcher:DispatcherProvider,
76+
privatevalmpBackupSettings: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 (mpBackupSettingsisMPBackupSettings.Enabled) {
121+
createMpBackupFile(password)
122+
}else {
123+
createBackupFile(password)
124+
}
125+
126+
when (result) {
115127
isCreateBackupResult.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
funchooseBackupFileToRestore(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
privatefunshowPasswordDialog() {
177188
state= state.copy(restoreFileValidation=RestoreFileValidation.PasswordRequired)
178189
}
179190

180-
privatesuspendfuncheckIfBackupEncrypted(importedBackupPath:Path)= withContext(dispatcher.main()) {
191+
privatesuspendfunverifyBackupFile(importedBackupPath:Path)= withContext(dispatcher.main()) {
181192
when (val result= verifyBackup(importedBackupPath)) {
182193
isVerifyBackupResult.Success-> {
183-
when (result) {
184-
isVerifyBackupResult.Success.Encrypted-> showPasswordDialog()
185-
isVerifyBackupResult.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
isVerifyBackupResult.Failure.Generic-> result.error.toString()
201210
VerifyBackupResult.Failure.InvalidBackupFile->"No valid files found in the backup"
211+
isVerifyBackupResult.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-
privatesuspendfunimportDatabase(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-
isRestoreBackupResult.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
funrestorePasswordProtectedBackup()= 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 (fileValidationStateisRestoreFileValidation.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-
isRestoreBackupResult.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+
privatefunrestoreBackup(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+
isRestoreBackupResult.Failure-> {
319+
mapBackupRestoreFailure(result.failure)
320+
AnonymousAnalyticsManagerImpl.sendEvent(event=AnalyticsEvent.BackupRestoreFailed)
321+
}
322+
}
323+
}
324+
320325
privatesuspendfunupdateCreationProgress(progress:Float)= withContext(dispatcher.main()) {
321326
state= state.copy(backupCreationProgress=BackupCreationProgress.InProgress(progress))
322327
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Wire
3+
* Copyright (C) 2025 Wire Swiss GmbH
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see http://www.gnu.org/licenses/.
17+
*/
18+
packagecom.wire.android.ui.home.settings.backup
19+
20+
sealedinterfaceMPBackupSettings {
21+
data objectDisabled :MPBackupSettings
22+
data objectEnabled :MPBackupSettings
23+
}

‎app/src/main/res/values/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1343,7 +1343,7 @@ In group conversations, the group admin can overwrite this setting.</string>
13431343
<stringname="backup_label_conversation_restored">Conversations have been restored</string>
13441344
<stringname="backup_label_loading_conversations">Loading conversations</string>
13451345
<stringname="backup_dialog_restore_backup_title">Restore from backup </string>
1346-
<stringname="backup_dialog_restore_backup_message">Thebackup contents will replace the conversation history on this device. You canonlyrestore history froma backup of the same platform.</string>
1346+
<stringname="backup_dialog_restore_backup_message">Theexisting history on this device remains and will be completed by the new backup. You can restore history fromall your devices and different platforms but not from another account.</string>
13471347
<stringname="backup_dialog_choose_backup_file_option">Choose Backup File</string>
13481348
<stringname="backup_label_enter_password">Enter password</string>
13491349
<stringname="backup_dialog_restore_backup_password_message">This backup is password protected.</string>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp