diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt index f2af582c25..7683b7278f 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt @@ -19,21 +19,17 @@ package io.element.android.appnav.loggedin import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.derivedStateOf 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.networkmonitor.api.NetworkMonitor import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.push.api.PushService -import kotlinx.coroutines.delay import javax.inject.Inject -private const val DELAY_BEFORE_SHOWING_SYNC_SPINNER_IN_MILLIS = 1500L - class LoggedInPresenter @Inject constructor( private val matrixClient: MatrixClient, private val networkMonitor: NetworkMonitor, @@ -50,19 +46,11 @@ class LoggedInPresenter @Inject constructor( pushService.registerWith(matrixClient, pushProvider, distributor) } - val roomListState by matrixClient.roomListService.state.collectAsState() + val syncIndicator by matrixClient.roomListService.syncIndicator.collectAsState() val networkStatus by networkMonitor.connectivity.collectAsState() - var showSyncSpinner by remember { - mutableStateOf(false) - } - LaunchedEffect(roomListState, networkStatus) { - showSyncSpinner = when { - networkStatus == NetworkStatus.Offline -> false - roomListState == RoomListService.State.Running -> false - else -> { - delay(DELAY_BEFORE_SHOWING_SYNC_SPINNER_IN_MILLIS) - true - } + val showSyncSpinner by remember { + derivedStateOf { + networkStatus == NetworkStatus.Online && syncIndicator == RoomListService.SyncIndicator.Show } } return LoggedInState( diff --git a/changelog.d/1244.misc b/changelog.d/1244.misc new file mode 100644 index 0000000000..ab0bbf5178 --- /dev/null +++ b/changelog.d/1244.misc @@ -0,0 +1 @@ +Use the new SyncIndicator API. diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt index 9ae6c22e7d..de7f1f3918 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt @@ -32,6 +32,11 @@ interface RoomListService { data object Terminated : State() } + sealed class SyncIndicator { + data object Show : SyncIndicator() + data object Hide : SyncIndicator() + } + /** * returns a [RoomList] object of all rooms we want to display. * This will exclude some rooms like the invites, or spaces. @@ -49,6 +54,11 @@ interface RoomListService { */ fun updateAllRoomsVisibleRange(range: IntRange) + /** + * The sync indicator as a flow. + */ + val syncIndicator: StateFlow + /** * The state of the service as a flow. */ diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt index 8d96990a9e..1e599a184d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt @@ -33,6 +33,8 @@ import org.matrix.rustcomponents.sdk.RoomListLoadingStateListener import org.matrix.rustcomponents.sdk.RoomListService import org.matrix.rustcomponents.sdk.RoomListServiceState import org.matrix.rustcomponents.sdk.RoomListServiceStateListener +import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator +import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicatorListener import timber.log.Timber fun RoomList.loadingStateFlow(): Flow = @@ -83,6 +85,18 @@ fun RoomListService.stateFlow(): Flow = } }.buffer(Channel.UNLIMITED) +fun RoomListService.syncIndicator(): Flow = + mxCallbackFlow { + val listener = object : RoomListServiceSyncIndicatorListener { + override fun onUpdate(syncIndicator: RoomListServiceSyncIndicator) { + trySendBlocking(syncIndicator) + } + } + tryOrNull { + syncIndicator(listener) + } + }.buffer(Channel.UNLIMITED) + fun RoomListService.roomOrNull(roomId: String): RoomListItem? { return try { room(roomId) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt index 5dade3b1c7..a2de2be89b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt @@ -38,6 +38,7 @@ import org.matrix.rustcomponents.sdk.RoomListInput import org.matrix.rustcomponents.sdk.RoomListLoadingState import org.matrix.rustcomponents.sdk.RoomListRange import org.matrix.rustcomponents.sdk.RoomListServiceState +import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator import timber.log.Timber import org.matrix.rustcomponents.sdk.RoomListService as InnerRustRoomListService @@ -106,6 +107,15 @@ class RustRoomListService( } } + override val syncIndicator: StateFlow = + innerRoomListService.syncIndicator() + .map { it.toSyncIndicator() } + .onEach { syncIndicator -> + Timber.d("SyncIndicator = $syncIndicator") + } + .distinctUntilChanged() + .stateIn(sessionCoroutineScope, SharingStarted.Eagerly, RoomListService.SyncIndicator.Hide) + override val state: StateFlow = innerRoomListService.stateFlow() .map { it.toRoomListState() } @@ -134,6 +144,13 @@ private fun RoomListServiceState.toRoomListState(): RoomListService.State { } } +private fun RoomListServiceSyncIndicator.toSyncIndicator(): RoomListService.SyncIndicator { + return when (this) { + RoomListServiceSyncIndicator.SHOW -> RoomListService.SyncIndicator.Show + RoomListServiceSyncIndicator.HIDE -> RoomListService.SyncIndicator.Hide + } +} + private fun org.matrix.rustcomponents.sdk.RoomList.observeEntriesWithProcessor(processor: RoomSummaryListProcessor): Flow> { return entriesFlow { roomListEntries -> processor.postEntries(roomListEntries) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt index fa2e347e3b..7e0f3e8891 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt @@ -29,6 +29,7 @@ class FakeRoomListService : RoomListService { private val allRoomsLoadingStateFlow = MutableStateFlow(RoomList.LoadingState.NotLoaded) private val inviteRoomsLoadingStateFlow = MutableStateFlow(RoomList.LoadingState.NotLoaded) private val roomListStateFlow = MutableStateFlow(RoomListService.State.Idle) + private val syncIndicatorStateFlow = MutableStateFlow(RoomListService.SyncIndicator.Hide) suspend fun postAllRooms(roomSummaries: List) { allRoomSummariesFlow.emit(roomSummaries) @@ -72,4 +73,6 @@ class FakeRoomListService : RoomListService { } override val state: StateFlow = roomListStateFlow + + override val syncIndicator: StateFlow = syncIndicatorStateFlow }