Hide the encryption badge when key storage is set up on the server

The settings badge was shown for every unknown backup state, so a session
whose key backup lives on the server but has not been reported by the SDK
kept a red dot next to Encryption while the Encryption screen itself
showed nothing to do.

Resolve an unknown backup state the way the Encryption screen already
does, by asking whether a backup exists on the server, and only badge the
entry when there is none.
This commit is contained in:
hayaksi1
2026-08-17 03:55:09 +03:00
parent 23b75c3423
commit 7dcd55ee08
2 changed files with 33 additions and 5 deletions
@@ -9,11 +9,14 @@
package io.element.android.libraries.indicator.impl package io.element.android.libraries.indicator.impl
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.indicator.api.IndicatorService import io.element.android.libraries.indicator.api.IndicatorService
@@ -43,12 +46,17 @@ class DefaultIndicatorService(
override fun showSettingChatBackupIndicator(): State<Boolean> { override fun showSettingChatBackupIndicator(): State<Boolean> {
val backupState by encryptionService.backupStateStateFlow.collectAsState() val backupState by encryptionService.backupStateStateFlow.collectAsState()
val recoveryState by encryptionService.recoveryStateStateFlow.collectAsState() val recoveryState by encryptionService.recoveryStateStateFlow.collectAsState()
var doesBackupExistOnServer by remember { mutableStateOf<Boolean?>(null) }
LaunchedEffect(backupState) {
if (backupState == BackupState.UNKNOWN) {
doesBackupExistOnServer = encryptionService.doesBackupExistOnServer().getOrNull()
}
}
return remember { return remember {
derivedStateOf { derivedStateOf {
val showForBackup = backupState in listOf( val showForBackup = backupState == BackupState.UNKNOWN && doesBackupExistOnServer != true
BackupState.UNKNOWN,
)
val showForRecovery = recoveryState in listOf( val showForRecovery = recoveryState in listOf(
RecoveryState.DISABLED, RecoveryState.DISABLED,
RecoveryState.INCOMPLETE, RecoveryState.INCOMPLETE,
@@ -42,8 +42,10 @@ class DefaultIndicatorServiceTest {
} }
@Test @Test
fun `test - showSettingChatBackupIndicator is true when BackupState is UNKNOWN`() = runTest { fun `test - showSettingChatBackupIndicator is true when BackupState is UNKNOWN and no backup exists on the server`() = runTest {
val encryptionService = FakeEncryptionService() val encryptionService = FakeEncryptionService().apply {
givenDoesBackupExistOnServerResult(Result.success(false))
}
val sessionVerificationService = FakeSessionVerificationService() val sessionVerificationService = FakeSessionVerificationService()
val sut = DefaultIndicatorService( val sut = DefaultIndicatorService(
sessionVerificationService = sessionVerificationService, sessionVerificationService = sessionVerificationService,
@@ -61,6 +63,24 @@ class DefaultIndicatorServiceTest {
} }
} }
@Test
fun `test - showSettingChatBackupIndicator is false when BackupState is UNKNOWN but a backup exists on the server`() = runTest {
val encryptionService = FakeEncryptionService().apply {
givenDoesBackupExistOnServerResult(Result.success(true))
}
val sessionVerificationService = FakeSessionVerificationService()
val sut = DefaultIndicatorService(
sessionVerificationService = sessionVerificationService,
encryptionService = encryptionService,
)
moleculeFlow(RecompositionMode.Immediate) {
sut.showSettingChatBackupIndicator().value
}.test {
assertThat(awaitItem()).isTrue()
assertThat(awaitItem()).isFalse()
}
}
@Test @Test
fun `test - showSettingChatBackupIndicator is true when recoveryState is DISABLED`() = runTest { fun `test - showSettingChatBackupIndicator is true when recoveryState is DISABLED`() = runTest {
val encryptionService = FakeEncryptionService() val encryptionService = FakeEncryptionService()