feature (space) : add space cache and navigation to sub space/room
This commit is contained in:
parent
b45a4c3b2c
commit
d4d2aa1707
20 changed files with 278 additions and 101 deletions
|
|
@ -8,10 +8,12 @@
|
|||
package io.element.android.libraries.matrix.impl.spaces
|
||||
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.spaces.SpaceRoom
|
||||
import io.element.android.libraries.matrix.api.spaces.SpaceRoomList
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
|
|
@ -21,16 +23,27 @@ import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState
|
|||
import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList
|
||||
|
||||
class RustSpaceRoomList(
|
||||
private val roomId: RoomId,
|
||||
private val innerProvider: suspend () -> InnerSpaceRoomList,
|
||||
sessionCoroutineScope: CoroutineScope,
|
||||
spaceRoomMapper: SpaceRoomMapper,
|
||||
private val spaceRoomCache: SpaceRoomCache,
|
||||
) : SpaceRoomList {
|
||||
|
||||
private val inner = CompletableDeferred<InnerSpaceRoomList>()
|
||||
|
||||
override fun currentSpaceFlow(): Flow<SpaceRoom?> {
|
||||
return spaceRoomCache.getSpaceRoomFlow(roomId)
|
||||
}
|
||||
|
||||
override val spaceRoomsFlow = MutableSharedFlow<List<SpaceRoom>>(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
|
||||
override val paginationStatusFlow: MutableStateFlow<SpaceRoomList.PaginationStatus> =
|
||||
MutableStateFlow(SpaceRoomList.PaginationStatus.Idle(hasMoreToLoad = false))
|
||||
private val spaceListUpdateProcessor = SpaceListUpdateProcessor(spaceRoomsFlow, spaceRoomMapper)
|
||||
private val spaceListUpdateProcessor = SpaceListUpdateProcessor(
|
||||
spaceRoomsFlow = spaceRoomsFlow,
|
||||
mapper = spaceRoomMapper,
|
||||
spaceRoomCache = spaceRoomCache
|
||||
)
|
||||
|
||||
init {
|
||||
sessionCoroutineScope.launch {
|
||||
|
|
|
|||
|
|
@ -39,8 +39,13 @@ class RustSpaceService(
|
|||
private val sessionDispatcher: CoroutineDispatcher,
|
||||
) : SpaceService {
|
||||
private val spaceRoomMapper = SpaceRoomMapper()
|
||||
private val spaceRoomCache = SpaceRoomCache()
|
||||
override val spaceRoomsFlow = MutableSharedFlow<List<SpaceRoom>>(replay = 1, extraBufferCapacity = 1)
|
||||
private val spaceListUpdateProcessor = SpaceListUpdateProcessor(spaceRoomsFlow, spaceRoomMapper)
|
||||
private val spaceListUpdateProcessor = SpaceListUpdateProcessor(
|
||||
spaceRoomsFlow = spaceRoomsFlow,
|
||||
mapper = spaceRoomMapper,
|
||||
spaceRoomCache = spaceRoomCache
|
||||
)
|
||||
|
||||
override suspend fun joinedSpaces(): Result<List<SpaceRoom>> = withContext(sessionDispatcher) {
|
||||
runCatchingExceptions {
|
||||
|
|
@ -53,9 +58,11 @@ class RustSpaceService(
|
|||
|
||||
override fun spaceRoomList(id: RoomId): SpaceRoomList {
|
||||
return RustSpaceRoomList(
|
||||
roomId = id,
|
||||
innerProvider = { innerSpaceService.spaceRoomList(id.value) },
|
||||
sessionCoroutineScope = sessionCoroutineScope,
|
||||
spaceRoomMapper = spaceRoomMapper
|
||||
spaceRoomMapper = spaceRoomMapper,
|
||||
spaceRoomCache = spaceRoomCache,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import timber.log.Timber
|
|||
internal class SpaceListUpdateProcessor(
|
||||
private val spaceRoomsFlow: MutableSharedFlow<List<SpaceRoom>>,
|
||||
private val mapper: SpaceRoomMapper,
|
||||
private val spaceRoomCache: SpaceRoomCache,
|
||||
) {
|
||||
private val mutex = Mutex()
|
||||
|
||||
|
|
@ -36,7 +37,8 @@ internal class SpaceListUpdateProcessor(
|
|||
mutableListOf()
|
||||
}
|
||||
block(spaceRooms)
|
||||
spaceRoomsFlow.tryEmit(spaceRooms)
|
||||
spaceRoomCache.update(spaceRooms)
|
||||
spaceRoomsFlow.emit(spaceRooms)
|
||||
}
|
||||
|
||||
private fun MutableList<SpaceRoom>.applyUpdate(update: SpaceListUpdate) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.spaces
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.spaces.SpaceRoom
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
|
||||
/**
|
||||
* An in memory cache of space rooms.
|
||||
* Only caches Rooms with roomType [io.element.android.libraries.matrix.api.room.RoomType.Space].
|
||||
*/
|
||||
class SpaceRoomCache() {
|
||||
private val inMemoryCache = MutableStateFlow<MutableMap<RoomId, SpaceRoom>>(LinkedHashMap())
|
||||
private val mutex = Mutex()
|
||||
|
||||
fun getSpaceRoomFlow(roomId: RoomId): Flow<SpaceRoom?> {
|
||||
return inMemoryCache.map { it[roomId] }
|
||||
}
|
||||
|
||||
suspend fun update(spaceRooms: List<SpaceRoom>) = mutex.withLock {
|
||||
inMemoryCache.update { cache ->
|
||||
spaceRooms
|
||||
.filter { it.isSpace }
|
||||
.forEach { spaceRoom ->
|
||||
cache.put(spaceRoom.roomId, spaceRoom)
|
||||
}
|
||||
cache
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue