Browse Source

BackupState.DISABLED has been removed. Now when the value is UNKNOWN, the app need to invoke `EncryptionService.doesBackupExistOnServer()` to check if a Backup exists.

pull/1832/head
Benoit Marty 10 months ago
parent
commit
d352f14665
  1. 17
      features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenter.kt
  2. 1
      features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootState.kt
  3. 7
      features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootStateProvider.kt
  4. 28
      features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt
  5. 3
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/BackupState.kt
  6. 2
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt
  7. 1
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapper.kt
  8. 6
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt
  9. 4
      libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt

17
features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenter.kt

@ -17,13 +17,18 @@
package io.element.android.features.securebackup.impl.root package io.element.android.features.securebackup.impl.root
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import io.element.android.features.securebackup.impl.loggerTagRoot import io.element.android.features.securebackup.impl.loggerTagRoot
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
import io.element.android.libraries.matrix.api.encryption.BackupState
import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.EncryptionService
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -44,8 +49,20 @@ class SecureBackupRootPresenter @Inject constructor(
Timber.tag(loggerTagRoot.value).d("backupState: $backupState") Timber.tag(loggerTagRoot.value).d("backupState: $backupState")
Timber.tag(loggerTagRoot.value).d("recoveryState: $recoveryState") Timber.tag(loggerTagRoot.value).d("recoveryState: $recoveryState")
var doesBackupExistOnServer: Boolean? by remember { mutableStateOf(null) }
LaunchedEffect(backupState) {
doesBackupExistOnServer = if (backupState == BackupState.UNKNOWN) {
encryptionService.doesBackupExistOnServer().getOrNull() == true
} else {
// The value will not be used when the backupState is not UNKNOWN.
false
}
}
return SecureBackupRootState( return SecureBackupRootState(
backupState = backupState, backupState = backupState,
doesBackupExistOnServer = doesBackupExistOnServer,
recoveryState = recoveryState, recoveryState = recoveryState,
appName = buildMeta.applicationName, appName = buildMeta.applicationName,
snackbarMessage = snackbarMessage, snackbarMessage = snackbarMessage,

1
features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootState.kt

@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.api.encryption.RecoveryState
data class SecureBackupRootState( data class SecureBackupRootState(
val backupState: BackupState, val backupState: BackupState,
val doesBackupExistOnServer: Boolean?,
val recoveryState: RecoveryState, val recoveryState: RecoveryState,
val appName: String, val appName: String,
val snackbarMessage: SnackbarMessage?, val snackbarMessage: SnackbarMessage?,

7
features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootStateProvider.kt

@ -24,9 +24,10 @@ import io.element.android.libraries.matrix.api.encryption.RecoveryState
open class SecureBackupRootStateProvider : PreviewParameterProvider<SecureBackupRootState> { open class SecureBackupRootStateProvider : PreviewParameterProvider<SecureBackupRootState> {
override val values: Sequence<SecureBackupRootState> override val values: Sequence<SecureBackupRootState>
get() = sequenceOf( get() = sequenceOf(
aSecureBackupRootState(backupState = BackupState.UNKNOWN), aSecureBackupRootState(backupState = BackupState.UNKNOWN, doesBackupExistOnServer = null),
aSecureBackupRootState(backupState = BackupState.UNKNOWN, doesBackupExistOnServer = true),
aSecureBackupRootState(backupState = BackupState.UNKNOWN, doesBackupExistOnServer = false),
aSecureBackupRootState(backupState = BackupState.ENABLED), aSecureBackupRootState(backupState = BackupState.ENABLED),
aSecureBackupRootState(backupState = BackupState.DISABLED),
aSecureBackupRootState(recoveryState = RecoveryState.UNKNOWN), aSecureBackupRootState(recoveryState = RecoveryState.UNKNOWN),
aSecureBackupRootState(recoveryState = RecoveryState.ENABLED), aSecureBackupRootState(recoveryState = RecoveryState.ENABLED),
aSecureBackupRootState(recoveryState = RecoveryState.DISABLED), aSecureBackupRootState(recoveryState = RecoveryState.DISABLED),
@ -37,10 +38,12 @@ open class SecureBackupRootStateProvider : PreviewParameterProvider<SecureBackup
fun aSecureBackupRootState( fun aSecureBackupRootState(
backupState: BackupState = BackupState.UNKNOWN, backupState: BackupState = BackupState.UNKNOWN,
doesBackupExistOnServer: Boolean? = true,
recoveryState: RecoveryState = RecoveryState.UNKNOWN, recoveryState: RecoveryState = RecoveryState.UNKNOWN,
snackbarMessage: SnackbarMessage? = null, snackbarMessage: SnackbarMessage? = null,
) = SecureBackupRootState( ) = SecureBackupRootState(
backupState = backupState, backupState = backupState,
doesBackupExistOnServer = doesBackupExistOnServer,
recoveryState = recoveryState, recoveryState = recoveryState,
appName = "Element", appName = "Element",
snackbarMessage = snackbarMessage, snackbarMessage = snackbarMessage,

28
features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt

@ -70,13 +70,27 @@ fun SecureBackupRootView(
// Disable / Enable backup // Disable / Enable backup
when (state.backupState) { when (state.backupState) {
BackupState.WAITING_FOR_SYNC, BackupState.WAITING_FOR_SYNC -> Unit
BackupState.UNKNOWN -> Unit BackupState.UNKNOWN -> {
BackupState.DISABLED -> { when (state.doesBackupExistOnServer) {
PreferenceText( true -> {
title = stringResource(id = R.string.screen_chat_backup_key_backup_action_enable), // Should not happen, we will have the state BackupState.ENABLED
onClick = onEnableClicked, PreferenceText(
) title = stringResource(id = R.string.screen_chat_backup_key_backup_action_disable),
tintColor = ElementTheme.colors.textCriticalPrimary,
onClick = onDisableClicked,
)
}
false -> {
PreferenceText(
title = stringResource(id = R.string.screen_chat_backup_key_backup_action_enable),
onClick = onEnableClicked,
)
}
null -> {
AsyncLoading()
}
}
} }
BackupState.CREATING, BackupState.CREATING,
BackupState.ENABLING, BackupState.ENABLING,

3
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/BackupState.kt

@ -31,6 +31,5 @@ enum class BackupState {
RESUMING, RESUMING,
ENABLED, ENABLED,
DOWNLOADING, DOWNLOADING,
DISABLING, DISABLING;
DISABLED;
} }

2
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt

@ -40,6 +40,8 @@ interface EncryptionService {
suspend fun disableRecovery(): Result<Unit> suspend fun disableRecovery(): Result<Unit>
suspend fun doesBackupExistOnServer(): Result<Boolean>
/** /**
* Note: accept bot recoveryKey and passphrase. * Note: accept bot recoveryKey and passphrase.
*/ */

1
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapper.kt

@ -29,7 +29,6 @@ class BackupStateMapper {
RustBackupState.ENABLED -> BackupState.ENABLED RustBackupState.ENABLED -> BackupState.ENABLED
RustBackupState.DOWNLOADING -> BackupState.DOWNLOADING RustBackupState.DOWNLOADING -> BackupState.DOWNLOADING
RustBackupState.DISABLING -> BackupState.DISABLING RustBackupState.DISABLING -> BackupState.DISABLING
RustBackupState.DISABLED -> BackupState.DISABLED
} }
} }
} }

6
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt

@ -130,6 +130,12 @@ internal class RustEncryptionService(
} }
} }
override suspend fun doesBackupExistOnServer(): Result<Boolean> = withContext(dispatchers.io) {
runCatching {
service.backupExistsOnServer()
}
}
override fun waitForBackupUploadSteadyState(): Flow<BackupUploadState> { override fun waitForBackupUploadSteadyState(): Flow<BackupUploadState> {
return callbackFlow { return callbackFlow {
runCatching { runCatching {

4
libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt

@ -52,6 +52,10 @@ class FakeEncryptionService : EncryptionService {
return Result.success(Unit) return Result.success(Unit)
} }
override suspend fun doesBackupExistOnServer(): Result<Boolean> = simulateLongTask {
return Result.success(true)
}
override suspend fun fixRecoveryIssues(recoveryKey: String): Result<Unit> = simulateLongTask { override suspend fun fixRecoveryIssues(recoveryKey: String): Result<Unit> = simulateLongTask {
fixRecoveryIssuesFailure?.let { return Result.failure(it) } fixRecoveryIssuesFailure?.let { return Result.failure(it) }
return Result.success(Unit) return Result.success(Unit)

Loading…
Cancel
Save