diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt
index 24499263f3..2c1b96df0f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt
@@ -693,11 +693,14 @@ object BackupRepository {
val header = frameReader.getHeader()
if (header == null) {
Log.e(TAG, "[import] Backup is missing header!")
+ SignalStore.backup.hasInvalidBackupVersion = false
return ImportResult.Failure
} else if (header.version > VERSION) {
Log.e(TAG, "[import] Backup version is newer than we understand: ${header.version}")
+ SignalStore.backup.hasInvalidBackupVersion = true
return ImportResult.Failure
}
+ SignalStore.backup.hasInvalidBackupVersion = false
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.
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/BackupRestoreJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/BackupRestoreJob.kt
index 1f60bb4416..d31f9480b9 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/BackupRestoreJob.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/BackupRestoreJob.kt
@@ -12,6 +12,7 @@ import org.signal.libsignal.zkgroup.profiles.ProfileKey
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.backup.RestoreState
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.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobmanager.Job
@@ -103,7 +104,10 @@ class BackupRestoreJob private constructor(parameters: Parameters) : BaseJob(par
val self = Recipient.self()
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
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/BackupValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/BackupValues.kt
index 89c1a49e6b..58d26ab470 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/BackupValues.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/BackupValues.kt
@@ -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_SPACE_REMAINING = "backup.failed.space.remaining"
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"
@@ -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
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
diff --git a/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/RemoteRestoreActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/RemoteRestoreActivity.kt
index 39b0222403..212660a849 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/RemoteRestoreActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/RemoteRestoreActivity.kt
@@ -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.MessageBackupsTypeFeatureRow
import org.thoughtcrime.securesms.conversation.v2.registerForLifecycle
+import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.profiles.edit.CreateProfileActivity
import org.thoughtcrime.securesms.registrationv3.ui.shared.RegistrationScreen
import org.thoughtcrime.securesms.util.DateUtils
+import org.thoughtcrime.securesms.util.PlayStoreUtil
import org.thoughtcrime.securesms.util.viewModel
import java.util.Locale
@@ -111,7 +113,10 @@ class RemoteRestoreActivity : BaseActivity() {
finish()
},
- onErrorDialogDismiss = { viewModel.clearError() }
+ onErrorDialogDismiss = { viewModel.clearError() },
+ onUpdateSignal = {
+ PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(this)
+ }
)
}
}
@@ -145,7 +150,8 @@ private fun RestoreFromBackupContent(
state: RemoteRestoreViewModel.ScreenState,
onRestoreBackupClick: () -> Unit = {},
onCancelClick: () -> Unit = {},
- onErrorDialogDismiss: () -> Unit = {}
+ onErrorDialogDismiss: () -> Unit = {},
+ onUpdateSignal: () -> Unit = {}
) {
when (state.loadState) {
RemoteRestoreViewModel.ScreenState.LoadState.LOADING -> {
@@ -159,7 +165,8 @@ private fun RestoreFromBackupContent(
state = state,
onRestoreBackupClick = onRestoreBackupClick,
onCancelClick = onCancelClick,
- onErrorDialogDismiss = onErrorDialogDismiss
+ onErrorDialogDismiss = onErrorDialogDismiss,
+ onUpdateSignal = onUpdateSignal
)
}
@@ -178,7 +185,8 @@ private fun BackupAvailableContent(
state: RemoteRestoreViewModel.ScreenState,
onRestoreBackupClick: () -> Unit,
onCancelClick: () -> Unit,
- onErrorDialogDismiss: () -> Unit
+ onErrorDialogDismiss: () -> Unit,
+ onUpdateSignal: () -> Unit
) {
val subtitle = if (state.backupSize.bytes > 0) {
stringResource(
@@ -244,7 +252,13 @@ private fun BackupAvailableContent(
RemoteRestoreViewModel.ImportState.None -> Unit
RemoteRestoreViewModel.ImportState.InProgress -> RestoreProgressDialog(state.restoreProgress)
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()
}
}
+
+@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()
+ }
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2c69a8cb4f..91bc4560b3 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1411,6 +1411,14 @@
Couldn\'t finish transfer
An error occurred and your account couldn’t be transferred. Try again by choosing your transfer method.
+
+ Couldn\'t restore this backup
+
+ This version of Signal can\'t restore your backup. Update to the latest version and try again.
+
+ Update Signal
+
+ Not now
Notify me for Mentions