Spaces : expose new SpaceServiceFilter
This commit is contained in:
@@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.api.spaces.LeaveSpaceHandle
|
||||
import io.element.android.libraries.matrix.api.spaces.SpaceRoom
|
||||
import io.element.android.libraries.matrix.api.spaces.SpaceRoomList
|
||||
import io.element.android.libraries.matrix.api.spaces.SpaceService
|
||||
import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter
|
||||
import io.element.android.libraries.matrix.impl.util.cancelAndDestroy
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
@@ -31,9 +32,11 @@ import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.rustcomponents.sdk.SpaceFilterUpdate
|
||||
import org.matrix.rustcomponents.sdk.SpaceListUpdate
|
||||
import org.matrix.rustcomponents.sdk.SpaceServiceInterface
|
||||
import org.matrix.rustcomponents.sdk.SpaceServiceJoinedSpacesListener
|
||||
import org.matrix.rustcomponents.sdk.SpaceServiceSpaceFiltersListener
|
||||
import timber.log.Timber
|
||||
import org.matrix.rustcomponents.sdk.SpaceService as ClientSpaceService
|
||||
|
||||
@@ -45,6 +48,8 @@ class RustSpaceService(
|
||||
private val analyticsService: AnalyticsService,
|
||||
) : SpaceService {
|
||||
private val spaceRoomMapper = SpaceRoomMapper()
|
||||
private val spaceFilterMapper = SpaceServiceFilterMapper(spaceRoomMapper)
|
||||
|
||||
override val topLevelSpacesFlow = MutableSharedFlow<List<SpaceRoom>>(replay = 1, extraBufferCapacity = 1)
|
||||
private val spaceListUpdateProcessor = SpaceListUpdateProcessor(
|
||||
spaceRoomsFlow = topLevelSpacesFlow,
|
||||
@@ -52,6 +57,12 @@ class RustSpaceService(
|
||||
analyticsService = analyticsService,
|
||||
)
|
||||
|
||||
override val spaceFiltersFlow = MutableSharedFlow<List<SpaceServiceFilter>>(replay = 1, extraBufferCapacity = 1)
|
||||
private val spaceFilterUpdateProcessor = SpaceServiceFilterUpdateProcessor(
|
||||
spaceFiltersFlow = spaceFiltersFlow,
|
||||
mapper = spaceFilterMapper,
|
||||
)
|
||||
|
||||
override suspend fun joinedParents(spaceId: RoomId): Result<List<SpaceRoom>> = withContext(sessionDispatcher) {
|
||||
runCatchingExceptions {
|
||||
innerSpaceService
|
||||
@@ -115,6 +126,13 @@ class RustSpaceService(
|
||||
spaceListUpdateProcessor.postUpdates(updates)
|
||||
}
|
||||
.launchIn(sessionCoroutineScope)
|
||||
|
||||
innerSpaceService
|
||||
.spaceFilterListUpdate()
|
||||
.onEach { updates ->
|
||||
spaceFilterUpdateProcessor.postUpdates(updates)
|
||||
}
|
||||
.launchIn(sessionCoroutineScope)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,3 +152,20 @@ internal fun SpaceServiceInterface.spaceListUpdate(): Flow<List<SpaceListUpdate>
|
||||
}.catch {
|
||||
Timber.d(it, "spaceDiffFlow() failed")
|
||||
}.buffer(Channel.UNLIMITED)
|
||||
|
||||
internal fun SpaceServiceInterface.spaceFilterListUpdate(): Flow<List<SpaceFilterUpdate>> =
|
||||
callbackFlow {
|
||||
val listener = object : SpaceServiceSpaceFiltersListener {
|
||||
override fun onUpdate(filterUpdates: List<SpaceFilterUpdate>) {
|
||||
trySendBlocking(filterUpdates)
|
||||
}
|
||||
}
|
||||
Timber.d("Open spaceFilterDiffFlow for SpaceServiceInterface ${this@spaceFilterListUpdate}")
|
||||
val taskHandle = subscribeToSpaceFilters(listener)
|
||||
awaitClose {
|
||||
Timber.d("Close spaceFilterDiffFlow for SpaceServiceInterface ${this@spaceFilterListUpdate}")
|
||||
taskHandle.cancelAndDestroy()
|
||||
}
|
||||
}.catch {
|
||||
Timber.d(it, "spaceFilterListUpdate() failed")
|
||||
}.buffer(Channel.UNLIMITED)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* 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 io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter
|
||||
import org.matrix.rustcomponents.sdk.SpaceFilter as RustSpaceFilter
|
||||
|
||||
class SpaceServiceFilterMapper(
|
||||
private val spaceRoomMapper: SpaceRoomMapper,
|
||||
) {
|
||||
fun map(spaceFilter: RustSpaceFilter): SpaceServiceFilter {
|
||||
return SpaceServiceFilter(
|
||||
spaceRoom = spaceRoomMapper.map(spaceFilter.spaceRoom),
|
||||
level = spaceFilter.level.toInt(),
|
||||
descendants = spaceFilter.descendants.map { RoomId(it) },
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* 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 io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import org.matrix.rustcomponents.sdk.SpaceFilterUpdate
|
||||
import timber.log.Timber
|
||||
|
||||
internal class SpaceServiceFilterUpdateProcessor(
|
||||
private val spaceFiltersFlow: MutableSharedFlow<List<SpaceServiceFilter>>,
|
||||
private val mapper: SpaceServiceFilterMapper,
|
||||
) {
|
||||
private val mutex = Mutex()
|
||||
|
||||
suspend fun postUpdates(updates: List<SpaceFilterUpdate>) {
|
||||
Timber.v("Update space filters from postUpdates (with ${updates.size} items) on ${Thread.currentThread()}")
|
||||
updateSpaceFilters {
|
||||
updates.forEach { update -> applyUpdate(update) }
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateSpaceFilters(block: MutableList<SpaceServiceFilter>.() -> Unit) =
|
||||
mutex.withLock {
|
||||
val spaceFilters = if (spaceFiltersFlow.replayCache.isNotEmpty()) {
|
||||
spaceFiltersFlow.first().toMutableList()
|
||||
} else {
|
||||
mutableListOf()
|
||||
}
|
||||
block(spaceFilters)
|
||||
spaceFiltersFlow.emit(spaceFilters)
|
||||
}
|
||||
|
||||
private fun MutableList<SpaceServiceFilter>.applyUpdate(update: SpaceFilterUpdate) {
|
||||
when (update) {
|
||||
is SpaceFilterUpdate.Append -> {
|
||||
val newFilters = update.values.map(mapper::map)
|
||||
addAll(newFilters)
|
||||
}
|
||||
SpaceFilterUpdate.Clear -> clear()
|
||||
is SpaceFilterUpdate.Insert -> {
|
||||
val newFilter = mapper.map(update.value)
|
||||
add(update.index.toInt(), newFilter)
|
||||
}
|
||||
SpaceFilterUpdate.PopBack -> {
|
||||
removeAt(lastIndex)
|
||||
}
|
||||
SpaceFilterUpdate.PopFront -> {
|
||||
removeAt(0)
|
||||
}
|
||||
is SpaceFilterUpdate.PushBack -> {
|
||||
val newFilter = mapper.map(update.value)
|
||||
add(newFilter)
|
||||
}
|
||||
is SpaceFilterUpdate.PushFront -> {
|
||||
val newFilter = mapper.map(update.value)
|
||||
add(0, newFilter)
|
||||
}
|
||||
is SpaceFilterUpdate.Remove -> {
|
||||
removeAt(update.index.toInt())
|
||||
}
|
||||
is SpaceFilterUpdate.Reset -> {
|
||||
clear()
|
||||
val newFilters = update.values.map(mapper::map)
|
||||
addAll(newFilters)
|
||||
}
|
||||
is SpaceFilterUpdate.Set -> {
|
||||
val newFilter = mapper.map(update.value)
|
||||
this[update.index.toInt()] = newFilter
|
||||
}
|
||||
is SpaceFilterUpdate.Truncate -> {
|
||||
subList(update.length.toInt(), size).clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user