Refactor room list filtering to use Rust SDK

This commit is contained in:
ganfra
2026-01-28 15:50:34 +01:00
parent 3d75b92ec3
commit 0824a3ab8b
33 changed files with 358 additions and 481 deletions

View File

@@ -8,12 +8,7 @@
package io.element.android.libraries.matrix.api.roomlist
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
/**
* RoomList with dynamic filtering and loading.
@@ -21,12 +16,8 @@ import kotlinx.coroutines.flow.onEach
* It lets load rooms on demand and filter them.
*/
interface DynamicRoomList : RoomList {
val currentFilter: StateFlow<RoomListFilter>
val loadedPages: StateFlow<Int>
val pageSize: Int
val filteredSummaries: SharedFlow<List<RoomSummary>>
/**
* Load more rooms into the list if possible.
*/
@@ -44,28 +35,13 @@ interface DynamicRoomList : RoomList {
suspend fun updateFilter(filter: RoomListFilter)
}
/**
* Offers a way to load all the rooms incrementally.
* It will load more room until all are loaded.
* If total number of rooms increase, it will load more pages if needed.
* The number of rooms is independent of the filter.
*/
fun DynamicRoomList.loadAllIncrementally(coroutineScope: CoroutineScope) {
combine(
loadedPages,
loadingState,
) { loadedPages, loadingState ->
loadedPages to loadingState
suspend fun DynamicRoomList.updateVisibleRange(
visibleRange: IntRange,
paginationThreshold: Int = pageSize * 3
) {
val loadedCount = summaries.replayCache.firstOrNull().orEmpty().count()
val threshold = loadedCount - paginationThreshold
if (visibleRange.last >= threshold) {
loadMore()
}
.onEach { (loadedPages, loadingState) ->
when (loadingState) {
is RoomList.LoadingState.Loaded -> {
if (pageSize * loadedPages < loadingState.numberOfRooms) {
loadMore()
}
}
RoomList.LoadingState.NotLoaded -> Unit
}
}
.launchIn(coroutineScope)
}

View File

@@ -21,6 +21,7 @@ import kotlin.time.Duration
* Can be retrieved from [RoomListService] methods.
*/
interface RoomList {
/**
* The loading state of the room list.
*/

View File

@@ -8,8 +8,6 @@
package io.element.android.libraries.matrix.api.roomlist
import io.element.android.libraries.core.extensions.withoutAccents
sealed interface RoomListFilter {
companion object {
/**
@@ -77,7 +75,5 @@ sealed interface RoomListFilter {
*/
data class NormalizedMatchRoomName(
val pattern: String
) : RoomListFilter {
val normalizedPattern: String = pattern.withoutAccents()
}
) : RoomListFilter
}

View File

@@ -38,13 +38,11 @@ interface RoomListService {
/**
* Creates a room list that can be used to load more rooms and filter them dynamically.
* @param pageSize the number of rooms to load at once.
* @param initialFilter the initial filter to apply to the rooms.
* @param source the source of the rooms, either all rooms or invites.
* @param coroutineScope the coroutine scope to use for the room list operations.
*/
fun createRoomList(
pageSize: Int,
initialFilter: RoomListFilter,
source: RoomList.Source,
coroutineScope: CoroutineScope,
): DynamicRoomList
@@ -56,10 +54,10 @@ interface RoomListService {
suspend fun subscribeToVisibleRooms(roomIds: List<RoomId>)
/**
* Returns a [DynamicRoomList] object of all rooms we want to display.
* Returns a [RoomList] object with all rooms locally known.
* If you want to get a filtered room list, consider using [createRoomList].
*/
val allRooms: DynamicRoomList
val allRooms: RoomList
/**
* The sync indicator as a flow.