Alert user to file system errors during backup restore.
This commit is contained in:
parent
73142cea39
commit
71979b34db
4 changed files with 48 additions and 5 deletions
|
@ -20,6 +20,7 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
|
|||
import org.thoughtcrime.securesms.notifications.NotificationChannels
|
||||
import org.thoughtcrime.securesms.service.LocalBackupListener
|
||||
import org.thoughtcrime.securesms.util.BackupUtil
|
||||
import org.thoughtcrime.securesms.util.BackupUtil.BackupInfo
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
|
@ -28,8 +29,13 @@ import java.io.IOException
|
|||
object RestoreRepository {
|
||||
private val TAG = Log.tag(RestoreRepository.javaClass)
|
||||
|
||||
suspend fun getLocalBackupFromUri(context: Context, uri: Uri): BackupUtil.BackupInfo? = withContext(Dispatchers.IO) {
|
||||
BackupUtil.getBackupInfoFromSingleUri(context, uri)
|
||||
suspend fun getLocalBackupFromUri(context: Context, uri: Uri): BackupInfoResult = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
return@withContext BackupInfoResult(backupInfo = BackupUtil.getBackupInfoFromSingleUri(context, uri), failureCause = null, failure = false)
|
||||
} catch (ex: BackupUtil.BackupFileException) {
|
||||
Log.w(TAG, "Encountered error while trying to read backup!", ex)
|
||||
return@withContext BackupInfoResult(backupInfo = null, failureCause = ex, failure = true)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun restoreBackupAsynchronously(context: Context, backupFileUri: Uri, passphrase: String): BackupImportResult = withContext(Dispatchers.IO) {
|
||||
|
@ -88,4 +94,6 @@ object RestoreRepository {
|
|||
FAILURE_FOREIGN_KEY,
|
||||
FAILURE_UNKNOWN
|
||||
}
|
||||
|
||||
data class BackupInfoResult(val backupInfo: BackupInfo?, val failureCause: BackupUtil.BackupFileException?, val failure: Boolean)
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
|
@ -29,6 +30,7 @@ import org.thoughtcrime.securesms.registration.fragments.RestoreBackupFragment.P
|
|||
import org.thoughtcrime.securesms.restore.RestoreActivity
|
||||
import org.thoughtcrime.securesms.restore.RestoreRepository
|
||||
import org.thoughtcrime.securesms.restore.RestoreViewModel
|
||||
import org.thoughtcrime.securesms.util.BackupUtil
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.thoughtcrime.securesms.util.ViewModelFactory
|
||||
|
@ -74,6 +76,13 @@ class RestoreLocalBackupFragment : LoggingFragment(R.layout.fragment_restore_loc
|
|||
return
|
||||
}
|
||||
|
||||
restoreLocalBackupViewModel.backupReadError.observe(viewLifecycleOwner) { fileState ->
|
||||
fileState?.let {
|
||||
restoreLocalBackupViewModel.clearBackupFileStateError()
|
||||
handleBackupFileStateError(it)
|
||||
}
|
||||
}
|
||||
|
||||
restoreLocalBackupViewModel.uiState.observe(viewLifecycleOwner) { fragmentState ->
|
||||
fragmentState.backupInfo?.let {
|
||||
presentBackupFileInfo(backupSize = it.size, backupTimestamp = it.timestamp)
|
||||
|
@ -126,6 +135,18 @@ class RestoreLocalBackupFragment : LoggingFragment(R.layout.fragment_restore_loc
|
|||
restoreLocalBackupViewModel.onBackupProgressUpdate(event)
|
||||
}
|
||||
|
||||
private fun handleBackupFileStateError(fileState: BackupUtil.BackupFileState) {
|
||||
@StringRes
|
||||
val errorResId: Int = when (fileState) {
|
||||
BackupUtil.BackupFileState.READABLE -> throw AssertionError("Unexpected error state.")
|
||||
BackupUtil.BackupFileState.NOT_FOUND -> R.string.RestoreBackupFragment__backup_not_found
|
||||
BackupUtil.BackupFileState.NOT_READABLE -> R.string.RestoreBackupFragment__backup_has_a_bad_extension
|
||||
BackupUtil.BackupFileState.UNSUPPORTED_FILE_EXTENSION -> R.string.RestoreBackupFragment__backup_could_not_be_read
|
||||
}
|
||||
|
||||
Toast.makeText(requireContext(), errorResId, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
private fun handleBackupImportError(importResult: RestoreRepository.BackupImportResult) {
|
||||
when (importResult) {
|
||||
RestoreRepository.BackupImportResult.FAILURE_VERSION_DOWNGRADE -> Toast.makeText(requireContext(), R.string.RegistrationActivity_backup_failure_downgrade, Toast.LENGTH_LONG).show()
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.restore.restorelocalbackup
|
|||
|
||||
import android.net.Uri
|
||||
import org.thoughtcrime.securesms.restore.RestoreRepository
|
||||
import org.thoughtcrime.securesms.util.BackupUtil
|
||||
import org.thoughtcrime.securesms.util.BackupUtil.BackupInfo
|
||||
|
||||
/**
|
||||
|
@ -15,6 +16,7 @@ import org.thoughtcrime.securesms.util.BackupUtil.BackupInfo
|
|||
data class RestoreLocalBackupState(
|
||||
val uri: Uri,
|
||||
val backupInfo: BackupInfo? = null,
|
||||
val backupFileStateError: BackupUtil.BackupFileState? = null,
|
||||
val backupPassphrase: String = "",
|
||||
val restoreInProgress: Boolean = false,
|
||||
val backupVerifyingInProgress: Boolean = false,
|
||||
|
|
|
@ -25,21 +25,29 @@ class RestoreLocalBackupViewModel(fileBackupUri: Uri) : ViewModel() {
|
|||
private val store = MutableStateFlow(RestoreLocalBackupState(fileBackupUri))
|
||||
val uiState = store.asLiveData()
|
||||
|
||||
val backupReadError = store.map { it.backupFileStateError }.asLiveData()
|
||||
|
||||
val backupComplete = store.map { Pair(it.backupRestoreComplete, it.backupImportResult) }.asLiveData()
|
||||
|
||||
fun prepareRestore(context: Context) {
|
||||
val backupFileUri = store.value.uri
|
||||
viewModelScope.launch {
|
||||
val backupInfo = RestoreRepository.getLocalBackupFromUri(context, backupFileUri)
|
||||
val result: RestoreRepository.BackupInfoResult = RestoreRepository.getLocalBackupFromUri(context, backupFileUri)
|
||||
|
||||
if (backupInfo == null) {
|
||||
if (result.failure && result.failureCause != null) {
|
||||
store.update {
|
||||
it.copy(
|
||||
backupFileStateError = result.failureCause.state
|
||||
)
|
||||
}
|
||||
} else if (result.backupInfo == null) {
|
||||
abort()
|
||||
return@launch
|
||||
}
|
||||
|
||||
store.update {
|
||||
it.copy(
|
||||
backupInfo = backupInfo
|
||||
backupInfo = result.backupInfo
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +109,10 @@ class RestoreLocalBackupViewModel(fileBackupUri: Uri) : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
fun clearBackupFileStateError() {
|
||||
store.update { it.copy(backupFileStateError = null) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(RestoreLocalBackupViewModel::class.java)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue