Ensure BackupState and RecoveryState values are set from the SDK only when the first sync is finished.

This commit is contained in:
Benoit Marty 2023-11-08 11:33:02 +01:00
parent bf4ce9f05a
commit 8d3af2a1fc
5 changed files with 60 additions and 5 deletions

View file

@ -70,6 +70,7 @@ fun SecureBackupRootView(
// Disable / Enable backup // Disable / Enable backup
when (state.backupState) { when (state.backupState) {
BackupState.WAITING_FOR_SYNC,
BackupState.UNKNOWN -> Unit BackupState.UNKNOWN -> Unit
BackupState.DISABLED -> { BackupState.DISABLED -> {
PreferenceText( PreferenceText(
@ -97,6 +98,7 @@ fun SecureBackupRootView(
// Setup recovery // Setup recovery
when (state.recoveryState) { when (state.recoveryState) {
RecoveryState.WAITING_FOR_SYNC -> Unit
RecoveryState.UNKNOWN, RecoveryState.UNKNOWN,
RecoveryState.DISABLED -> { RecoveryState.DISABLED -> {
PreferenceText( PreferenceText(

View file

@ -17,6 +17,14 @@
package io.element.android.libraries.matrix.api.encryption package io.element.android.libraries.matrix.api.encryption
enum class BackupState { enum class BackupState {
/**
* Special value, when the SDK is waiting for the first sync to be done.
*/
WAITING_FOR_SYNC,
/**
* Values mapped from the SDK.
*/
UNKNOWN, UNKNOWN,
CREATING, CREATING,
ENABLING, ENABLING,

View file

@ -17,6 +17,14 @@
package io.element.android.libraries.matrix.api.encryption package io.element.android.libraries.matrix.api.encryption
enum class RecoveryState { enum class RecoveryState {
/**
* Special value, when the SDK is waiting for the first sync to be done.
*/
WAITING_FOR_SYNC,
/**
* Values mapped from the SDK.
*/
UNKNOWN, UNKNOWN,
ENABLED, ENABLED,
DISABLED, DISABLED,

View file

@ -121,7 +121,12 @@ class RustMatrixClient constructor(
private val notificationService = RustNotificationService(sessionId, notificationClient, dispatchers, clock) private val notificationService = RustNotificationService(sessionId, notificationClient, dispatchers, clock)
private val notificationSettingsService = RustNotificationSettingsService(notificationSettings, dispatchers) private val notificationSettingsService = RustNotificationSettingsService(notificationSettings, dispatchers)
private val roomSyncSubscriber = RoomSyncSubscriber(innerRoomListService, dispatchers) private val roomSyncSubscriber = RoomSyncSubscriber(innerRoomListService, dispatchers)
private val encryptionService = RustEncryptionService(client, dispatchers).apply { start() } private val encryptionService = RustEncryptionService(
client = client,
syncService = rustSyncService,
sessionCoroutineScope = sessionCoroutineScope,
dispatchers = dispatchers,
).apply { start() }
private val isLoggingOut = AtomicBoolean(false) private val isLoggingOut = AtomicBoolean(false)

View file

@ -22,10 +22,16 @@ import io.element.android.libraries.matrix.api.encryption.BackupUploadState
import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress
import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.RecoveryState import io.element.android.libraries.matrix.api.encryption.RecoveryState
import io.element.android.libraries.matrix.api.sync.SyncState
import io.element.android.libraries.matrix.impl.sync.RustSyncService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.rustcomponents.sdk.BackupStateListener import org.matrix.rustcomponents.sdk.BackupStateListener
import org.matrix.rustcomponents.sdk.BackupSteadyStateListener import org.matrix.rustcomponents.sdk.BackupSteadyStateListener
@ -41,6 +47,8 @@ import org.matrix.rustcomponents.sdk.SteadyStateException as RustSteadyStateExce
internal class RustEncryptionService( internal class RustEncryptionService(
client: Client, client: Client,
syncService: RustSyncService,
sessionCoroutineScope: CoroutineScope,
private val dispatchers: CoroutineDispatchers, private val dispatchers: CoroutineDispatchers,
) : EncryptionService { ) : EncryptionService {
@ -52,20 +60,44 @@ internal class RustEncryptionService(
private val backupUploadStateMapper = BackupUploadStateMapper() private val backupUploadStateMapper = BackupUploadStateMapper()
private val steadyStateExceptionMapper = SteadyStateExceptionMapper() private val steadyStateExceptionMapper = SteadyStateExceptionMapper()
override val backupStateStateFlow: MutableStateFlow<BackupState> = MutableStateFlow(service.backupState().let(backupStateMapper::map)) private val backupStateFlow = MutableStateFlow(service.backupState().let(backupStateMapper::map))
override val recoveryStateStateFlow: MutableStateFlow<RecoveryState> = MutableStateFlow(service.recoveryState().let(recoveryStateMapper::map))
override val backupStateStateFlow = combine(
backupStateFlow,
syncService.syncState,
) { backupState, syncState ->
if (syncState == SyncState.Running) {
backupState
} else {
BackupState.WAITING_FOR_SYNC
}
}.stateIn(sessionCoroutineScope, SharingStarted.Eagerly, BackupState.WAITING_FOR_SYNC)
private val recoveryStateFlow: MutableStateFlow<RecoveryState> = MutableStateFlow(service.recoveryState().let(recoveryStateMapper::map))
override val recoveryStateStateFlow = combine(
recoveryStateFlow,
syncService.syncState,
) { recoveryState, syncState ->
if (syncState == SyncState.Running) {
recoveryState
} else {
RecoveryState.WAITING_FOR_SYNC
}
}.stateIn(sessionCoroutineScope, SharingStarted.Eagerly, RecoveryState.WAITING_FOR_SYNC)
override val enableRecoveryProgressStateFlow: MutableStateFlow<EnableRecoveryProgress> = MutableStateFlow(EnableRecoveryProgress.Unknown) override val enableRecoveryProgressStateFlow: MutableStateFlow<EnableRecoveryProgress> = MutableStateFlow(EnableRecoveryProgress.Unknown)
fun start() { fun start() {
service.backupStateListener(object : BackupStateListener { service.backupStateListener(object : BackupStateListener {
override fun onUpdate(status: RustBackupState) { override fun onUpdate(status: RustBackupState) {
backupStateStateFlow.value = backupStateMapper.map(status) backupStateFlow.value = backupStateMapper.map(status)
} }
}) })
service.recoveryStateListener(object : RecoveryStateListener { service.recoveryStateListener(object : RecoveryStateListener {
override fun onUpdate(status: RustRecoveryState) { override fun onUpdate(status: RustRecoveryState) {
recoveryStateStateFlow.value = recoveryStateMapper.map(status) recoveryStateFlow.value = recoveryStateMapper.map(status)
} }
}) })
} }