Subscribe to RoomListItems in the visible range (#3169)
* Subscribe to `RoomListItems` in the visible range This ensures the room list items always have updated info.
This commit is contained in:
parent
0be7058416
commit
5944f112fb
16 changed files with 204 additions and 17 deletions
|
|
@ -20,6 +20,7 @@ import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
|||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
||||
sealed interface RoomListEvents {
|
||||
data class UpdateVisibleRange(val range: IntRange) : RoomListEvents
|
||||
data object DismissRequestVerificationPrompt : RoomListEvents
|
||||
data object DismissRecoveryKeyPrompt : RoomListEvents
|
||||
data object ToggleSearchResults : RoomListEvents
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ import io.element.android.services.analyticsproviders.api.trackers.captureIntera
|
|||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.first
|
||||
|
|
@ -78,6 +80,8 @@ import kotlinx.coroutines.flow.takeWhile
|
|||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val EXTENDED_RANGE_SIZE = 40
|
||||
|
||||
class RoomListPresenter @Inject constructor(
|
||||
private val client: MatrixClient,
|
||||
private val networkMonitor: NetworkMonitor,
|
||||
|
|
@ -122,6 +126,9 @@ class RoomListPresenter @Inject constructor(
|
|||
|
||||
fun handleEvents(event: RoomListEvents) {
|
||||
when (event) {
|
||||
is RoomListEvents.UpdateVisibleRange -> coroutineScope.launch {
|
||||
updateVisibleRange(event.range)
|
||||
}
|
||||
RoomListEvents.DismissRequestVerificationPrompt -> securityBannerDismissed = true
|
||||
RoomListEvents.DismissRecoveryKeyPrompt -> securityBannerDismissed = true
|
||||
RoomListEvents.ToggleSearchResults -> searchState.eventSink(RoomListSearchEvents.ToggleSearchVisibility)
|
||||
|
|
@ -283,6 +290,22 @@ class RoomListPresenter @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var currentUpdateVisibleRangeJob: Job? = null
|
||||
private fun CoroutineScope.updateVisibleRange(range: IntRange) {
|
||||
currentUpdateVisibleRangeJob?.cancel()
|
||||
currentUpdateVisibleRangeJob = launch(SupervisorJob()) {
|
||||
if (range.isEmpty()) return@launch
|
||||
val currentRoomList = roomListDataSource.allRooms.first()
|
||||
// Use extended range to 'prefetch' the next rooms info
|
||||
val midExtendedRangeSize = EXTENDED_RANGE_SIZE / 2
|
||||
val extendedRange = range.first until range.last + midExtendedRangeSize
|
||||
val roomIds = extendedRange.mapNotNull { index ->
|
||||
currentRoomList.getOrNull(index)?.roomId
|
||||
}
|
||||
roomListDataSource.subscribeToVisibleRooms(roomIds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
|
|
|||
|
|
@ -30,6 +30,11 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
|
@ -165,6 +170,18 @@ private fun RoomsViewList(
|
|||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val lazyListState = rememberLazyListState()
|
||||
val visibleRange by remember {
|
||||
derivedStateOf {
|
||||
val layoutInfo = lazyListState.layoutInfo
|
||||
val firstItemIndex = layoutInfo.visibleItemsInfo.firstOrNull()?.index ?: 0
|
||||
val size = layoutInfo.visibleItemsInfo.size
|
||||
firstItemIndex until firstItemIndex + size
|
||||
}
|
||||
}
|
||||
val updatedEventSink by rememberUpdatedState(newValue = eventSink)
|
||||
LaunchedEffect(visibleRange) {
|
||||
updatedEventSink(RoomListEvents.UpdateVisibleRange(visibleRange))
|
||||
}
|
||||
LazyColumn(
|
||||
state = lazyListState,
|
||||
modifier = modifier,
|
||||
|
|
@ -177,7 +194,7 @@ private fun RoomsViewList(
|
|||
item {
|
||||
ConfirmRecoveryKeyBanner(
|
||||
onContinueClick = onConfirmRecoveryKeyClick,
|
||||
onDismissClick = { eventSink(RoomListEvents.DismissRecoveryKeyPrompt) }
|
||||
onDismissClick = { updatedEventSink(RoomListEvents.DismissRecoveryKeyPrompt) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
|||
import io.element.android.libraries.androidutils.diff.DiffCacheUpdater
|
||||
import io.element.android.libraries.androidutils.diff.MutableListDiffCache
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
||||
|
|
@ -57,6 +58,10 @@ class RoomListDataSource @Inject constructor(
|
|||
old?.roomId == new?.roomId
|
||||
}
|
||||
|
||||
val allRooms: Flow<ImmutableList<RoomListRoomSummary>> = _allRooms
|
||||
|
||||
val loadingState = roomListService.allRooms.loadingState
|
||||
|
||||
fun launchIn(coroutineScope: CoroutineScope) {
|
||||
roomListService
|
||||
.allRooms
|
||||
|
|
@ -67,9 +72,9 @@ class RoomListDataSource @Inject constructor(
|
|||
.launchIn(coroutineScope)
|
||||
}
|
||||
|
||||
val allRooms: Flow<ImmutableList<RoomListRoomSummary>> = _allRooms
|
||||
|
||||
val loadingState = roomListService.allRooms.loadingState
|
||||
suspend fun subscribeToVisibleRooms(roomIds: List<RoomId>) {
|
||||
roomListService.subscribeToVisibleRooms(roomIds)
|
||||
}
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
private fun observeNotificationSettings() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue