Add UI for mismatched backup versions.
This commit is contained in:
parent
ec4fdfa7d3
commit
a0cb12be8c
5 changed files with 60 additions and 6 deletions
|
@ -693,11 +693,14 @@ object BackupRepository {
|
||||||
val header = frameReader.getHeader()
|
val header = frameReader.getHeader()
|
||||||
if (header == null) {
|
if (header == null) {
|
||||||
Log.e(TAG, "[import] Backup is missing header!")
|
Log.e(TAG, "[import] Backup is missing header!")
|
||||||
|
SignalStore.backup.hasInvalidBackupVersion = false
|
||||||
return ImportResult.Failure
|
return ImportResult.Failure
|
||||||
} else if (header.version > VERSION) {
|
} else if (header.version > VERSION) {
|
||||||
Log.e(TAG, "[import] Backup version is newer than we understand: ${header.version}")
|
Log.e(TAG, "[import] Backup version is newer than we understand: ${header.version}")
|
||||||
|
SignalStore.backup.hasInvalidBackupVersion = true
|
||||||
return ImportResult.Failure
|
return ImportResult.Failure
|
||||||
}
|
}
|
||||||
|
SignalStore.backup.hasInvalidBackupVersion = false
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Removing all the data from the various tables is *very* expensive (i.e. can take *several* minutes) if we don't do some pre-work.
|
// Removing all the data from the various tables is *very* expensive (i.e. can take *several* minutes) if we don't do some pre-work.
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.signal.libsignal.zkgroup.profiles.ProfileKey
|
||||||
import org.thoughtcrime.securesms.R
|
import org.thoughtcrime.securesms.R
|
||||||
import org.thoughtcrime.securesms.backup.RestoreState
|
import org.thoughtcrime.securesms.backup.RestoreState
|
||||||
import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
||||||
|
import org.thoughtcrime.securesms.backup.v2.ImportResult
|
||||||
import org.thoughtcrime.securesms.backup.v2.RestoreV2Event
|
import org.thoughtcrime.securesms.backup.v2.RestoreV2Event
|
||||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||||
import org.thoughtcrime.securesms.jobmanager.Job
|
import org.thoughtcrime.securesms.jobmanager.Job
|
||||||
|
@ -103,7 +104,10 @@ class BackupRestoreJob private constructor(parameters: Parameters) : BaseJob(par
|
||||||
|
|
||||||
val self = Recipient.self()
|
val self = Recipient.self()
|
||||||
val selfData = BackupRepository.SelfData(self.aci.get(), self.pni.get(), self.e164.get(), ProfileKey(self.profileKey))
|
val selfData = BackupRepository.SelfData(self.aci.get(), self.pni.get(), self.e164.get(), ProfileKey(self.profileKey))
|
||||||
BackupRepository.import(length = tempBackupFile.length(), inputStreamFactory = tempBackupFile::inputStream, selfData = selfData, backupKey = SignalStore.backup.messageBackupKey, cancellationSignal = { isCanceled })
|
val result = BackupRepository.import(length = tempBackupFile.length(), inputStreamFactory = tempBackupFile::inputStream, selfData = selfData, backupKey = SignalStore.backup.messageBackupKey, cancellationSignal = { isCanceled })
|
||||||
|
if (result == ImportResult.Failure) {
|
||||||
|
throw IOException("Failed to import backup")
|
||||||
|
}
|
||||||
|
|
||||||
SignalStore.backup.restoreState = RestoreState.RESTORING_MEDIA
|
SignalStore.backup.restoreState = RestoreState.RESTORING_MEDIA
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||||
private const val KEY_BACKUP_FAIL_SHEET_SNOOZE_TIME = "backup.failed.sheet.snooze"
|
private const val KEY_BACKUP_FAIL_SHEET_SNOOZE_TIME = "backup.failed.sheet.snooze"
|
||||||
private const val KEY_BACKUP_FAIL_SPACE_REMAINING = "backup.failed.space.remaining"
|
private const val KEY_BACKUP_FAIL_SPACE_REMAINING = "backup.failed.space.remaining"
|
||||||
private const val KEY_BACKUP_ALREADY_REDEEMED = "backup.already.redeemed"
|
private const val KEY_BACKUP_ALREADY_REDEEMED = "backup.already.redeemed"
|
||||||
|
private const val KEY_INVALID_BACKUP_VERSION = "backup.invalid.version"
|
||||||
|
|
||||||
private const val KEY_USER_MANUALLY_SKIPPED_MEDIA_RESTORE = "backup.user.manually.skipped.media.restore"
|
private const val KEY_USER_MANUALLY_SKIPPED_MEDIA_RESTORE = "backup.user.manually.skipped.media.restore"
|
||||||
|
|
||||||
|
@ -217,6 +218,7 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||||
val nextBackupFailureSheetSnoozeTime: Duration get() = getLong(KEY_BACKUP_FAIL_SHEET_SNOOZE_TIME, getNextBackupFailureSheetSnoozeTime(lastBackupTime.milliseconds).inWholeMilliseconds).milliseconds
|
val nextBackupFailureSheetSnoozeTime: Duration get() = getLong(KEY_BACKUP_FAIL_SHEET_SNOOZE_TIME, getNextBackupFailureSheetSnoozeTime(lastBackupTime.milliseconds).inWholeMilliseconds).milliseconds
|
||||||
|
|
||||||
var hasBackupAlreadyRedeemedError: Boolean by booleanValue(KEY_BACKUP_ALREADY_REDEEMED, false)
|
var hasBackupAlreadyRedeemedError: Boolean by booleanValue(KEY_BACKUP_ALREADY_REDEEMED, false)
|
||||||
|
var hasInvalidBackupVersion: Boolean by booleanValue(KEY_INVALID_BACKUP_VERSION, false)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Denotes how many bytes are still available on the disk for writing. Used to display
|
* Denotes how many bytes are still available on the disk for writing. Used to display
|
||||||
|
|
|
@ -55,9 +55,11 @@ import org.thoughtcrime.securesms.backup.v2.RestoreV2Event
|
||||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsTypeFeature
|
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsTypeFeature
|
||||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsTypeFeatureRow
|
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsTypeFeatureRow
|
||||||
import org.thoughtcrime.securesms.conversation.v2.registerForLifecycle
|
import org.thoughtcrime.securesms.conversation.v2.registerForLifecycle
|
||||||
|
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||||
import org.thoughtcrime.securesms.profiles.edit.CreateProfileActivity
|
import org.thoughtcrime.securesms.profiles.edit.CreateProfileActivity
|
||||||
import org.thoughtcrime.securesms.registrationv3.ui.shared.RegistrationScreen
|
import org.thoughtcrime.securesms.registrationv3.ui.shared.RegistrationScreen
|
||||||
import org.thoughtcrime.securesms.util.DateUtils
|
import org.thoughtcrime.securesms.util.DateUtils
|
||||||
|
import org.thoughtcrime.securesms.util.PlayStoreUtil
|
||||||
import org.thoughtcrime.securesms.util.viewModel
|
import org.thoughtcrime.securesms.util.viewModel
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
|
@ -111,7 +113,10 @@ class RemoteRestoreActivity : BaseActivity() {
|
||||||
|
|
||||||
finish()
|
finish()
|
||||||
},
|
},
|
||||||
onErrorDialogDismiss = { viewModel.clearError() }
|
onErrorDialogDismiss = { viewModel.clearError() },
|
||||||
|
onUpdateSignal = {
|
||||||
|
PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(this)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,7 +150,8 @@ private fun RestoreFromBackupContent(
|
||||||
state: RemoteRestoreViewModel.ScreenState,
|
state: RemoteRestoreViewModel.ScreenState,
|
||||||
onRestoreBackupClick: () -> Unit = {},
|
onRestoreBackupClick: () -> Unit = {},
|
||||||
onCancelClick: () -> Unit = {},
|
onCancelClick: () -> Unit = {},
|
||||||
onErrorDialogDismiss: () -> Unit = {}
|
onErrorDialogDismiss: () -> Unit = {},
|
||||||
|
onUpdateSignal: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
when (state.loadState) {
|
when (state.loadState) {
|
||||||
RemoteRestoreViewModel.ScreenState.LoadState.LOADING -> {
|
RemoteRestoreViewModel.ScreenState.LoadState.LOADING -> {
|
||||||
|
@ -159,7 +165,8 @@ private fun RestoreFromBackupContent(
|
||||||
state = state,
|
state = state,
|
||||||
onRestoreBackupClick = onRestoreBackupClick,
|
onRestoreBackupClick = onRestoreBackupClick,
|
||||||
onCancelClick = onCancelClick,
|
onCancelClick = onCancelClick,
|
||||||
onErrorDialogDismiss = onErrorDialogDismiss
|
onErrorDialogDismiss = onErrorDialogDismiss,
|
||||||
|
onUpdateSignal = onUpdateSignal
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +185,8 @@ private fun BackupAvailableContent(
|
||||||
state: RemoteRestoreViewModel.ScreenState,
|
state: RemoteRestoreViewModel.ScreenState,
|
||||||
onRestoreBackupClick: () -> Unit,
|
onRestoreBackupClick: () -> Unit,
|
||||||
onCancelClick: () -> Unit,
|
onCancelClick: () -> Unit,
|
||||||
onErrorDialogDismiss: () -> Unit
|
onErrorDialogDismiss: () -> Unit,
|
||||||
|
onUpdateSignal: () -> Unit
|
||||||
) {
|
) {
|
||||||
val subtitle = if (state.backupSize.bytes > 0) {
|
val subtitle = if (state.backupSize.bytes > 0) {
|
||||||
stringResource(
|
stringResource(
|
||||||
|
@ -244,7 +252,13 @@ private fun BackupAvailableContent(
|
||||||
RemoteRestoreViewModel.ImportState.None -> Unit
|
RemoteRestoreViewModel.ImportState.None -> Unit
|
||||||
RemoteRestoreViewModel.ImportState.InProgress -> RestoreProgressDialog(state.restoreProgress)
|
RemoteRestoreViewModel.ImportState.InProgress -> RestoreProgressDialog(state.restoreProgress)
|
||||||
is RemoteRestoreViewModel.ImportState.Restored -> Unit
|
is RemoteRestoreViewModel.ImportState.Restored -> Unit
|
||||||
RemoteRestoreViewModel.ImportState.Failed -> RestoreFailedDialog(onDismiss = onErrorDialogDismiss)
|
RemoteRestoreViewModel.ImportState.Failed -> {
|
||||||
|
if (SignalStore.backup.hasInvalidBackupVersion) {
|
||||||
|
InvalidBackupVersionDialog(onUpdateSignal = onUpdateSignal, onDismiss = onErrorDialogDismiss)
|
||||||
|
} else {
|
||||||
|
RestoreFailedDialog(onDismiss = onErrorDialogDismiss)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,3 +423,26 @@ private fun RestoreFailedDialogPreview() {
|
||||||
RestoreFailedDialog()
|
RestoreFailedDialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun InvalidBackupVersionDialog(
|
||||||
|
onUpdateSignal: () -> Unit = {},
|
||||||
|
onDismiss: () -> Unit = {}
|
||||||
|
) {
|
||||||
|
Dialogs.SimpleAlertDialog(
|
||||||
|
title = stringResource(R.string.RemoteRestoreActivity__couldnt_restore),
|
||||||
|
body = stringResource(R.string.RemoteRestoreActivity__update_latest),
|
||||||
|
confirm = stringResource(R.string.RemoteRestoreActivity__update_signal),
|
||||||
|
onConfirm = onUpdateSignal,
|
||||||
|
dismiss = stringResource(R.string.RemoteRestoreActivity__not_now),
|
||||||
|
onDismiss = onDismiss
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SignalPreview
|
||||||
|
@Composable
|
||||||
|
private fun InvalidBackupVersionDialogPreview() {
|
||||||
|
Previews.Preview {
|
||||||
|
InvalidBackupVersionDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1411,6 +1411,14 @@
|
||||||
<string name="RemoteRestoreActivity__couldnt_transfer">Couldn\'t finish transfer</string>
|
<string name="RemoteRestoreActivity__couldnt_transfer">Couldn\'t finish transfer</string>
|
||||||
<!-- Dialog message displayed when remote restore failed -->
|
<!-- Dialog message displayed when remote restore failed -->
|
||||||
<string name="RemoteRestoreActivity__error_occurred">An error occurred and your account couldn’t be transferred. Try again by choosing your transfer method.</string>
|
<string name="RemoteRestoreActivity__error_occurred">An error occurred and your account couldn’t be transferred. Try again by choosing your transfer method.</string>
|
||||||
|
<!-- Dialog title displayed when remote restore failed because of an outdated backup version. -->
|
||||||
|
<string name="RemoteRestoreActivity__couldnt_restore">Couldn\'t restore this backup</string>
|
||||||
|
<!-- Dialog message explaining that an update to Signal is required to restore the backup. -->
|
||||||
|
<string name="RemoteRestoreActivity__update_latest">This version of Signal can\'t restore your backup. Update to the latest version and try again.</string>
|
||||||
|
<!-- Text on button that when pressed will redirect them to update Signal -->
|
||||||
|
<string name="RemoteRestoreActivity__update_signal">Update Signal</string>
|
||||||
|
<!-- Text label button to dismiss the dialog -->
|
||||||
|
<string name="RemoteRestoreActivity__not_now">Not now</string>
|
||||||
|
|
||||||
<!-- GroupMentionSettingDialog -->
|
<!-- GroupMentionSettingDialog -->
|
||||||
<string name="GroupMentionSettingDialog_notify_me_for_mentions">Notify me for Mentions</string>
|
<string name="GroupMentionSettingDialog_notify_me_for_mentions">Notify me for Mentions</string>
|
||||||
|
|
Loading…
Add table
Reference in a new issue