RoomList: try syncing when network is back and inError state

This commit is contained in:
ganfra
2023-06-23 17:07:27 +02:00
parent 1185dbd276
commit bb4f61fe12
6 changed files with 45 additions and 17 deletions

View File

@@ -22,7 +22,9 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import coil.Coil
import com.bumble.appyx.core.composable.Children
import com.bumble.appyx.core.lifecycle.subscribe
@@ -43,6 +45,8 @@ import io.element.android.appnav.loggedin.LoggedInNode
import io.element.android.features.analytics.api.AnalyticsEntryPoint
import io.element.android.features.createroom.api.CreateRoomEntryPoint
import io.element.android.features.invitelist.api.InviteListEntryPoint
import io.element.android.features.networkmonitor.api.NetworkMonitor
import io.element.android.features.networkmonitor.api.NetworkStatus
import io.element.android.features.preferences.api.PreferencesEntryPoint
import io.element.android.features.roomlist.api.RoomListEntryPoint
import io.element.android.features.verifysession.api.VerifySessionEntryPoint
@@ -59,13 +63,17 @@ import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.MAIN_SPACE
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.sync.SyncState
import io.element.android.libraries.matrix.ui.di.MatrixUIBindings
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.appnavstate.api.AppNavigationStateService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
@ContributesNode(AppScope::class)
@@ -81,6 +89,7 @@ class LoggedInFlowNode @AssistedInject constructor(
private val inviteListEntryPoint: InviteListEntryPoint,
private val analyticsService: AnalyticsService,
private val coroutineScope: CoroutineScope,
private val networkMonitor: NetworkMonitor,
snackbarDispatcher: SnackbarDispatcher,
) : BackstackNode<LoggedInFlowNode.NavTarget>(
backstack = BackStack(
@@ -162,6 +171,27 @@ class LoggedInFlowNode @AssistedInject constructor(
loggedInFlowProcessor.stopObserving()
}
)
observeSyncStateAndNetworkStatus()
}
private fun observeSyncStateAndNetworkStatus() {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
combine(
syncService.syncState.debounce(100),
networkMonitor.connectivity
) { syncState, networkStatus ->
syncState == SyncState.InError && networkStatus == NetworkStatus.Online
}
.distinctUntilChanged()
.collect { restartSync ->
if (restartSync) {
syncService.startSync()
}
}
}
}
}
sealed interface NavTarget : Parcelable {

View File

@@ -37,6 +37,7 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.stateIn
import timber.log.Timber
import javax.inject.Inject
@@ -81,6 +82,7 @@ class NetworkMonitorImpl @Inject constructor(
connectivityManager.unregisterNetworkCallback(callback)
}
}
.distinctUntilChanged()
.debounce(300)
.stateIn(appCoroutineScope, SharingStarted.WhileSubscribed(), connectivityManager.activeNetworkStatus())

View File

@@ -30,7 +30,7 @@ interface SyncService {
fun stopSync()
/**
*
* Flow of [SyncState]. Will be updated as soon as the current [SyncState] changes.
*/
fun syncState(): StateFlow<SyncState>
val syncState: StateFlow<SyncState>
}

View File

@@ -114,7 +114,7 @@ class RustMatrixClient constructor(
init {
client.setDelegate(clientDelegate)
syncService.syncState()
syncService.syncState
.onEach { syncState ->
if (syncState == SyncState.Syncing) {
onSlidingSyncUpdate()

View File

@@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.impl.room.roomListStateFlow
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
@@ -46,13 +47,10 @@ class RustSyncService(
}
}
override fun syncState(): StateFlow<SyncState> {
return roomListService
override val syncState: StateFlow<SyncState> =
roomListService
.roomListStateFlow()
.map(RoomListState::toSyncState)
.onEach { syncState ->
Timber.d("OnSyncState updated = $syncState")
}
.stateIn(sessionCoroutineScope, SharingStarted.Eagerly, SyncState.Idle)
}
.distinctUntilChanged()
.stateIn(sessionCoroutineScope, SharingStarted.WhileSubscribed(), SyncState.Idle)
}

View File

@@ -23,21 +23,19 @@ import kotlinx.coroutines.flow.StateFlow
class FakeSyncService : SyncService {
private val syncState = MutableStateFlow(SyncState.Idle)
private val syncStateFlow = MutableStateFlow(SyncState.Idle)
fun simulateError() {
syncState.value = SyncState.InError
syncStateFlow.value = SyncState.InError
}
override fun startSync() {
syncState.value = SyncState.Syncing
syncStateFlow.value = SyncState.Syncing
}
override fun stopSync() {
syncState.value = SyncState.Terminated
syncStateFlow.value = SyncState.Terminated
}
override fun syncState(): StateFlow<SyncState> {
return syncState
}
override val syncState: StateFlow<SyncState> = syncStateFlow
}