From 38aa0ad1cff0b50b8b705574627d4c1077cb042a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Nov 2023 09:44:50 +0000 Subject: [PATCH 1/6] Update dependency org.matrix.rustcomponents:sdk-android to v0.1.68 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b43b4e7072..4f33b98fe0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -144,7 +144,7 @@ jsoup = "org.jsoup:jsoup:1.16.2" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:1.3.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.67" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.68" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From 3c79390e45cebcc8d09000941a5f9f03b20e30ce Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 17 Nov 2023 17:31:22 +0100 Subject: [PATCH 2/6] 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) From d33002aa7fcf7b69155cad7bca9083f1c0c393f3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 20 Nov 2023 10:00:21 +0100 Subject: [PATCH 3/6] SecureBackup: improve error flow when backup state cannot be retrieved, and add tests. --- .../impl/root/SecureBackupRootEvents.kt | 21 +++++++ .../impl/root/SecureBackupRootPresenter.kt | 32 +++++++--- .../impl/root/SecureBackupRootState.kt | 4 +- .../root/SecureBackupRootStateProvider.kt | 11 ++-- .../impl/root/SecureBackupRootView.kt | 63 +++++++++++++++---- .../root/SecureBackupRootPresenterTest.kt | 35 ++++++++++- .../test/encryption/FakeEncryptionService.kt | 7 ++- 7 files changed, 147 insertions(+), 26 deletions(-) create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootEvents.kt diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootEvents.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootEvents.kt new file mode 100644 index 0000000000..0b2859b250 --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootEvents.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.securebackup.impl.root + +sealed interface SecureBackupRootEvents { + data object RetryKeyBackupState : SecureBackupRootEvents +} 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 4ed898ff9a..9036200ac9 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 @@ -18,18 +18,23 @@ package io.element.android.features.securebackup.impl.root import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState 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 androidx.compose.runtime.rememberCoroutineScope import io.element.android.features.securebackup.impl.loggerTagRoot +import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.architecture.runCatchingUpdatingState 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 kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @@ -41,6 +46,7 @@ class SecureBackupRootPresenter @Inject constructor( @Composable override fun present(): SecureBackupRootState { + val localCoroutineScope = rememberCoroutineScope() val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState() val backupState by encryptionService.backupStateStateFlow.collectAsState() @@ -49,23 +55,33 @@ 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) } + val doesBackupExistOnServerAction: MutableState> = remember { mutableStateOf(Async.Uninitialized) } 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 + if (backupState == BackupState.UNKNOWN) { + getKeyBackupStatus(doesBackupExistOnServerAction) + } + } + + fun handleEvents(event: SecureBackupRootEvents) { + when (event) { + SecureBackupRootEvents.RetryKeyBackupState -> localCoroutineScope.getKeyBackupStatus(doesBackupExistOnServerAction) } } return SecureBackupRootState( backupState = backupState, - doesBackupExistOnServer = doesBackupExistOnServer, + doesBackupExistOnServer = doesBackupExistOnServerAction.value, recoveryState = recoveryState, appName = buildMeta.applicationName, snackbarMessage = snackbarMessage, + eventSink = ::handleEvents, ) } + + private fun CoroutineScope.getKeyBackupStatus(action: MutableState>) = launch { + suspend { + encryptionService.doesBackupExistOnServer().getOrThrow() + }.runCatchingUpdatingState(action) + } } 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 a6dadf83c9..e2c6c1154c 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 @@ -16,14 +16,16 @@ package io.element.android.features.securebackup.impl.root +import io.element.android.libraries.architecture.Async import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.RecoveryState data class SecureBackupRootState( val backupState: BackupState, - val doesBackupExistOnServer: Boolean?, + val doesBackupExistOnServer: Async, val recoveryState: RecoveryState, val appName: String, val snackbarMessage: SnackbarMessage?, + val eventSink: (SecureBackupRootEvents) -> Unit, ) 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 efe59f23b3..ae8b2aa63b 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 @@ -17,6 +17,7 @@ package io.element.android.features.securebackup.impl.root import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.architecture.Async import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.RecoveryState @@ -24,9 +25,10 @@ import io.element.android.libraries.matrix.api.encryption.RecoveryState open class SecureBackupRootStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( - aSecureBackupRootState(backupState = BackupState.UNKNOWN, doesBackupExistOnServer = null), - aSecureBackupRootState(backupState = BackupState.UNKNOWN, doesBackupExistOnServer = true), - aSecureBackupRootState(backupState = BackupState.UNKNOWN, doesBackupExistOnServer = false), + aSecureBackupRootState(backupState = BackupState.UNKNOWN, doesBackupExistOnServer = Async.Uninitialized), + aSecureBackupRootState(backupState = BackupState.UNKNOWN, doesBackupExistOnServer = Async.Success(true)), + aSecureBackupRootState(backupState = BackupState.UNKNOWN, doesBackupExistOnServer = Async.Success(false)), + aSecureBackupRootState(backupState = BackupState.UNKNOWN, doesBackupExistOnServer = Async.Failure(Exception("An error"))), aSecureBackupRootState(backupState = BackupState.ENABLED), aSecureBackupRootState(recoveryState = RecoveryState.UNKNOWN), aSecureBackupRootState(recoveryState = RecoveryState.ENABLED), @@ -38,7 +40,7 @@ open class SecureBackupRootStateProvider : PreviewParameterProvider = Async.Uninitialized, recoveryState: RecoveryState = RecoveryState.UNKNOWN, snackbarMessage: SnackbarMessage? = null, ) = SecureBackupRootState( @@ -47,4 +49,5 @@ fun aSecureBackupRootState( recoveryState = recoveryState, appName = "Element", snackbarMessage = snackbarMessage, + eventSink = {}, ) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt index 8cee413c7e..e4ea588df0 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt @@ -16,18 +16,27 @@ package io.element.android.features.securebackup.impl.root +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.features.securebackup.impl.R +import io.element.android.libraries.architecture.Async import io.element.android.libraries.designsystem.components.async.AsyncLoading +import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.components.preferences.PreferenceDivider import io.element.android.libraries.designsystem.components.preferences.PreferencePage import io.element.android.libraries.designsystem.components.preferences.PreferenceText import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart +import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator +import io.element.android.libraries.designsystem.theme.components.ListItem +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.matrix.api.encryption.BackupState @@ -73,23 +82,55 @@ fun SecureBackupRootView( 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, - ) + is Async.Success -> when (state.doesBackupExistOnServer.data) { + 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, + ) + } } - false -> { + is Async.Loading, + Async.Uninitialized -> { + ListItem(headlineContent = { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + ) { + CircularProgressIndicator() + } + }) + } + is Async.Failure -> { + ListItem( + headlineContent = { + Text( + text = stringResource(id = CommonStrings.error_unknown), + ) + }, + trailingContent = ListItemContent.Custom { + TextButton( + text = stringResource( + id = CommonStrings.action_retry + ), + onClick = { state.eventSink.invoke(SecureBackupRootEvents.RetryKeyBackupState) } + ) + } + ) + PreferenceText( title = stringResource(id = R.string.screen_chat_backup_key_backup_action_enable), onClick = onEnableClicked, ) } - null -> { - AsyncLoading() - } } } BackupState.CREATING, diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenterTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenterTest.kt index 93031b6d2a..ba20439e79 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenterTest.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenterTest.kt @@ -20,12 +20,16 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.architecture.Async import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher 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.RecoveryState +import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.awaitLastSequentialItem import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -40,9 +44,38 @@ class SecureBackupRootPresenterTest { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - val initialState = awaitItem() + val initialState = awaitLastSequentialItem() assertThat(initialState.backupState).isEqualTo(BackupState.UNKNOWN) + assertThat(initialState.doesBackupExistOnServer.dataOrNull()).isTrue() + assertThat(initialState.recoveryState).isEqualTo(RecoveryState.UNKNOWN) assertThat(initialState.appName).isEqualTo("Element") + assertThat(initialState.snackbarMessage).isNull() + } + } + + @Test + fun `present - Unknown state`() = runTest { + val encryptionService = FakeEncryptionService() + val presenter = createSecureBackupRootPresenter( + encryptionService = encryptionService, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + encryptionService.givenDoesBackupExistOnServerResult(Result.failure(AN_EXCEPTION)) + assertThat(initialState.backupState).isEqualTo(BackupState.UNKNOWN) + assertThat(initialState.doesBackupExistOnServer).isEqualTo(Async.Uninitialized) + val loadingState1 = awaitItem() + assertThat(loadingState1.doesBackupExistOnServer).isInstanceOf(Async.Loading::class.java) + val errorState = awaitItem() + assertThat(errorState.doesBackupExistOnServer).isEqualTo(Async.Failure(AN_EXCEPTION)) + encryptionService.givenDoesBackupExistOnServerResult(Result.success(false)) + errorState.eventSink.invoke(SecureBackupRootEvents.RetryKeyBackupState) + val loadingState2 = awaitItem() + assertThat(loadingState2.doesBackupExistOnServer).isInstanceOf(Async.Loading::class.java) + val finalState = awaitItem() + assertThat(finalState.doesBackupExistOnServer.dataOrNull()).isFalse() } } 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 4d7cbf5c09..9f10f4ba35 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 @@ -34,6 +34,7 @@ class FakeEncryptionService : EncryptionService { private var waitForBackupUploadSteadyStateFlow: Flow = flowOf() private var fixRecoveryIssuesFailure: Exception? = null + private var doesBackupExistOnServerResult: Result = Result.success(true) override suspend fun enableBackups(): Result = simulateLongTask { return Result.success(Unit) @@ -52,8 +53,12 @@ class FakeEncryptionService : EncryptionService { return Result.success(Unit) } + fun givenDoesBackupExistOnServerResult(result: Result) { + doesBackupExistOnServerResult = result + } + override suspend fun doesBackupExistOnServer(): Result = simulateLongTask { - return Result.success(true) + return doesBackupExistOnServerResult } override suspend fun fixRecoveryIssues(recoveryKey: String): Result = simulateLongTask { From 3de856e98e829e88efe91c6d9a872fd16657a23f Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 20 Nov 2023 09:08:16 +0000 Subject: [PATCH 4/6] Update screenshots --- ...ll_SecureBackupRootView-Day-3_3_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ll_SecureBackupRootView-Day-3_3_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...ll_SecureBackupRootView-Day-3_3_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...ll_SecureBackupRootView-Day-3_3_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...ll_SecureBackupRootView-Day-3_3_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...ll_SecureBackupRootView-Day-3_3_null_7,NEXUS_5,1.0,en].png | 3 +++ ...ll_SecureBackupRootView-Day-3_3_null_8,NEXUS_5,1.0,en].png | 3 +++ ..._SecureBackupRootView-Night-3_4_null_0,NEXUS_5,1.0,en].png | 4 ++-- ..._SecureBackupRootView-Night-3_4_null_3,NEXUS_5,1.0,en].png | 4 ++-- ..._SecureBackupRootView-Night-3_4_null_4,NEXUS_5,1.0,en].png | 4 ++-- ..._SecureBackupRootView-Night-3_4_null_5,NEXUS_5,1.0,en].png | 4 ++-- ..._SecureBackupRootView-Night-3_4_null_6,NEXUS_5,1.0,en].png | 4 ++-- ..._SecureBackupRootView-Night-3_4_null_7,NEXUS_5,1.0,en].png | 3 +++ ..._SecureBackupRootView-Night-3_4_null_8,NEXUS_5,1.0,en].png | 3 +++ 14 files changed, 32 insertions(+), 20 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_7,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_8,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_7,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_8,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_0,NEXUS_5,1.0,en].png index d5ae1fe7c3..a6ce94832e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1aef9057653b917425621448d0ef62975b02b6cae0e572758a2749ac9cc71189 -size 39364 +oid sha256:fafe906b308c604f4ef98dab36b55b84fd235598aea738913301940bf4222a93 +size 41473 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_3,NEXUS_5,1.0,en].png index d5ae1fe7c3..c6db44bf6f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1aef9057653b917425621448d0ef62975b02b6cae0e572758a2749ac9cc71189 -size 39364 +oid sha256:7f395fed6dfabb7f26a10f851e0fca7ea475722e1def7159f36d05cc9e47e09a +size 47990 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_4,NEXUS_5,1.0,en].png index 471a6b98c6..0abdbfd76d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b159c6b39ad05b3d0dc10ae0da1826bcaae45c94e0150b09c2cf6ddf2353d305 -size 24831 +oid sha256:92ce51c885eb9c5efb80b747ef107e185114401d235bfd261ec06a1bb9f53f85 +size 42518 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_5,NEXUS_5,1.0,en].png index d5ae1fe7c3..a6ce94832e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1aef9057653b917425621448d0ef62975b02b6cae0e572758a2749ac9cc71189 -size 39364 +oid sha256:fafe906b308c604f4ef98dab36b55b84fd235598aea738913301940bf4222a93 +size 41473 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_6,NEXUS_5,1.0,en].png index f75b484e1f..8e822c7ef2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb83490002e584be9f268eadc014345740d0026c929e79f2bb4c407fdf2ba926 -size 29777 +oid sha256:3747da81312e3f34da13e6bd530301550c7307856cc7a31aa009be2d60002ecc +size 26338 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_7,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..a6ce94832e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_7,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fafe906b308c604f4ef98dab36b55b84fd235598aea738913301940bf4222a93 +size 41473 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_8,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..557ce7e1ce --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Day-3_3_null_8,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:083440e0fa8699c8fd370bb13351d04c01fa2c78c273f8e2b07bff0b09e4f2f1 +size 31938 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_0,NEXUS_5,1.0,en].png index 35f90db1d9..be5ffbb21e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:870c36e4f7a64e258af75e22845d05dd8c8217d6dc65826b6405537bed9bc848 -size 37439 +oid sha256:94869b0aaccbbc1e82fb96de5f71fa7e9a59ba36317213c0f9a6bb4f9448e2b1 +size 39451 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_3,NEXUS_5,1.0,en].png index 35f90db1d9..cbfa69161d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:870c36e4f7a64e258af75e22845d05dd8c8217d6dc65826b6405537bed9bc848 -size 37439 +oid sha256:0a8411a6c7df7bdc79a526755745fd2b2fed1c32676acd9c9b1135b2391e5abe +size 45326 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_4,NEXUS_5,1.0,en].png index a8dd202ac2..3a7029466e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:837be69c85fb1a7f08ac0780ca34a56fa5d4d1f2134b4255efc68a78b33cab65 -size 23591 +oid sha256:19965ae446d383e69f8f05dc3e3cb1d3956a9962c472d9246b765ae467ef8d56 +size 40318 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_5,NEXUS_5,1.0,en].png index 35f90db1d9..be5ffbb21e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:870c36e4f7a64e258af75e22845d05dd8c8217d6dc65826b6405537bed9bc848 -size 37439 +oid sha256:94869b0aaccbbc1e82fb96de5f71fa7e9a59ba36317213c0f9a6bb4f9448e2b1 +size 39451 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_6,NEXUS_5,1.0,en].png index ffc413c52d..4673753cdc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eda4aab1ded791ad60e417818ad49070c1c53b9c1353da6dd843fae0934459a5 -size 28387 +oid sha256:14cb5e199172c0b325175e913708fb88111d479af06c1ac2c380a8cd68a80021 +size 25090 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_7,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..be5ffbb21e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_7,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94869b0aaccbbc1e82fb96de5f71fa7e9a59ba36317213c0f9a6bb4f9448e2b1 +size 39451 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_8,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..f9da40e05d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.securebackup.impl.root_SecureBackupRootView_null_SecureBackupRootView-Night-3_4_null_8,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:59912e13e6cfec021b7c12d689029f159a0b69e91905323f710d47124e67a7ea +size 30051 From ed23fdbc104b080cdb9d1471b7d8c36bbc42e650 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 20 Nov 2023 10:36:29 +0100 Subject: [PATCH 5/6] Remove wrong comment. --- .../features/securebackup/impl/root/SecureBackupRootView.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt index e4ea588df0..3a27ae553e 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt @@ -84,7 +84,6 @@ fun SecureBackupRootView( when (state.doesBackupExistOnServer) { is Async.Success -> when (state.doesBackupExistOnServer.data) { 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, From 7369d25a924c82160999915bf171b9dbcc865f06 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 20 Nov 2023 11:27:25 +0100 Subject: [PATCH 6/6] Fix test on CI. --- .../securebackup/impl/root/SecureBackupRootPresenterTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenterTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenterTest.kt index ba20439e79..6b88e20748 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenterTest.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootPresenterTest.kt @@ -29,7 +29,6 @@ import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.tests.testutils.WarmUpRule -import io.element.android.tests.testutils.awaitLastSequentialItem import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -44,7 +43,8 @@ class SecureBackupRootPresenterTest { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - val initialState = awaitLastSequentialItem() + skipItems(2) + val initialState = awaitItem() assertThat(initialState.backupState).isEqualTo(BackupState.UNKNOWN) assertThat(initialState.doesBackupExistOnServer.dataOrNull()).isTrue() assertThat(initialState.recoveryState).isEqualTo(RecoveryState.UNKNOWN)