From d352f146650c6f9c2ace53ffbdd23891b68261ed Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 17 Nov 2023 17:31:22 +0100 Subject: [PATCH] BackupState.DISABLED has been removed. Now when the value is UNKNOWN, the app need to invoke `EncryptionService.doesBackupExistOnServer()` to check if a Backup exists. --- .../impl/root/SecureBackupRootPresenter.kt | 17 +++++++++++ .../impl/root/SecureBackupRootState.kt | 1 + .../root/SecureBackupRootStateProvider.kt | 7 +++-- .../impl/root/SecureBackupRootView.kt | 28 ++++++++++++++----- .../matrix/api/encryption/BackupState.kt | 3 +- .../api/encryption/EncryptionService.kt | 2 ++ .../impl/encryption/BackupStateMapper.kt | 1 - .../impl/encryption/RustEncryptionService.kt | 6 ++++ .../test/encryption/FakeEncryptionService.kt | 4 +++ 9 files changed, 57 insertions(+), 12 deletions(-) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenter.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenter.kt index 8a8fa6075c..4ed898ff9a 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenter.kt +++ b/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 import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState 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.libraries.architecture.Presenter 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.collectSnackbarMessageAsState +import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.EncryptionService import timber.log.Timber import javax.inject.Inject @@ -44,8 +49,20 @@ class SecureBackupRootPresenter @Inject constructor( Timber.tag(loggerTagRoot.value).d("backupState: $backupState") 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( backupState = backupState, + doesBackupExistOnServer = doesBackupExistOnServer, recoveryState = recoveryState, appName = buildMeta.applicationName, snackbarMessage = snackbarMessage, diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootState.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootState.kt index 1eacd9e81a..a6dadf83c9 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootState.kt +++ b/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( val backupState: BackupState, + val doesBackupExistOnServer: Boolean?, val recoveryState: RecoveryState, val appName: String, val snackbarMessage: SnackbarMessage?, diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootStateProvider.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootStateProvider.kt index ee15a40f50..efe59f23b3 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootStateProvider.kt +++ b/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 { override val values: Sequence 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.DISABLED), aSecureBackupRootState(recoveryState = RecoveryState.UNKNOWN), aSecureBackupRootState(recoveryState = RecoveryState.ENABLED), aSecureBackupRootState(recoveryState = RecoveryState.DISABLED), @@ -37,10 +38,12 @@ open class SecureBackupRootStateProvider : PreviewParameterProvider Unit - BackupState.DISABLED -> { - PreferenceText( - title = stringResource(id = R.string.screen_chat_backup_key_backup_action_enable), - onClick = onEnableClicked, - ) + BackupState.WAITING_FOR_SYNC -> Unit + BackupState.UNKNOWN -> { + when (state.doesBackupExistOnServer) { + true -> { + // Should not happen, we will have the state BackupState.ENABLED + 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.ENABLING, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/BackupState.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/BackupState.kt index 98c45a1c9e..03f650e316 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/BackupState.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/BackupState.kt @@ -31,6 +31,5 @@ enum class BackupState { RESUMING, ENABLED, DOWNLOADING, - DISABLING, - DISABLED; + DISABLING; } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt index 9652c53678..534f5b68e2 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt +++ b/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 + suspend fun doesBackupExistOnServer(): Result + /** * Note: accept bot recoveryKey and passphrase. */ diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapper.kt index dbdd48da6c..ec7bc8e4d9 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapper.kt +++ b/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.DOWNLOADING -> BackupState.DOWNLOADING RustBackupState.DISABLING -> BackupState.DISABLING - RustBackupState.DISABLED -> BackupState.DISABLED } } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt index 11f9842d62..30b8c651a0 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt +++ b/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 = withContext(dispatchers.io) { + runCatching { + service.backupExistsOnServer() + } + } + override fun waitForBackupUploadSteadyState(): Flow { return callbackFlow { runCatching { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt index 825d929c0e..4d7cbf5c09 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt +++ b/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) } + override suspend fun doesBackupExistOnServer(): Result = simulateLongTask { + return Result.success(true) + } + override suspend fun fixRecoveryIssues(recoveryKey: String): Result = simulateLongTask { fixRecoveryIssuesFailure?.let { return Result.failure(it) } return Result.success(Unit)