RoomList: change a bit the api of RoomSummaryDataSource

This commit is contained in:
ganfra 2023-06-22 12:34:07 +02:00
parent 6446f2f6a7
commit 8ce65b4429
12 changed files with 78 additions and 92 deletions

View file

@ -49,8 +49,8 @@ class InviteListPresenter @Inject constructor(
@Composable @Composable
override fun present(): InviteListState { override fun present(): InviteListState {
val invites by client val invites by client
.invitesDataSource .roomSummaryDataSource
.roomSummaries() .inviteList()
.collectAsState() .collectAsState()
var seenInvites by remember { mutableStateOf<Set<RoomId>>(emptySet()) } var seenInvites by remember { mutableStateOf<Set<RoomId>>(emptySet()) }

View file

@ -43,8 +43,8 @@ class DefaultInviteStateDataSource @Inject constructor(
@Composable @Composable
override fun inviteState(): InvitesState { override fun inviteState(): InvitesState {
val invites by client val invites by client
.invitesDataSource .roomSummaryDataSource
.roomSummaries() .inviteList()
.collectAsState() .collectAsState()
val seenInvites by seenInvitesStore val seenInvites by seenInvitesStore

View file

@ -77,7 +77,7 @@ class RoomListPresenter @Inject constructor(
var filter by rememberSaveable { mutableStateOf("") } var filter by rememberSaveable { mutableStateOf("") }
val roomSummaries by client val roomSummaries by client
.roomSummaryDataSource .roomSummaryDataSource
.roomSummaries() .roomList()
.collectAsState() .collectAsState()
val networkConnectionStatus by networkMonitor.connectivity.collectAsState(initial = networkMonitor.currentConnectivityStatus) val networkConnectionStatus by networkMonitor.connectivity.collectAsState(initial = networkMonitor.currentConnectivityStatus)
@ -177,7 +177,7 @@ class RoomListPresenter @Inject constructor(
// Safe to give bigger size than room list // Safe to give bigger size than room list
val extendedRangeEnd = range.last + midExtendedRangeSize val extendedRangeEnd = range.last + midExtendedRangeSize
val extendedRange = IntRange(extendedRangeStart, extendedRangeEnd) val extendedRange = IntRange(extendedRangeStart, extendedRangeEnd)
client.roomSummaryDataSource.setSlidingSyncRange(extendedRange) client.roomSummaryDataSource.updateRoomListVisibleRange(extendedRange)
} }
private suspend fun mapRoomSummaries( private suspend fun mapRoomSummaries(

View file

@ -35,7 +35,6 @@ import java.io.Closeable
interface MatrixClient : Closeable { interface MatrixClient : Closeable {
val sessionId: SessionId val sessionId: SessionId
val roomSummaryDataSource: RoomSummaryDataSource val roomSummaryDataSource: RoomSummaryDataSource
val invitesDataSource: RoomSummaryDataSource
val mediaLoader: MatrixMediaLoader val mediaLoader: MatrixMediaLoader
fun getRoom(roomId: RoomId): MatrixRoom? fun getRoom(roomId: RoomId): MatrixRoom?
fun findDM(userId: UserId): MatrixRoom? fun findDM(userId: UserId): MatrixRoom?

View file

@ -28,6 +28,7 @@ interface RoomSummaryDataSource {
} }
fun loadingState(): StateFlow<LoadingState> fun loadingState(): StateFlow<LoadingState>
fun roomSummaries(): StateFlow<List<RoomSummary>> fun roomList(): StateFlow<List<RoomSummary>>
fun setSlidingSyncRange(range: IntRange) fun inviteList(): StateFlow<List<RoomSummary>>
fun updateRoomListVisibleRange(range: IntRange)
} }

View file

@ -93,28 +93,18 @@ class RustMatrixClient constructor(
} }
} }
private val roomList = client.roomList() private val roomListService = client.roomList()
private val rustRoomSummaryDataSource: RustRoomSummaryDataSource = private val rustRoomSummaryDataSource: RustRoomSummaryDataSource =
RustRoomSummaryDataSource( RustRoomSummaryDataSource(
roomList, roomListService = roomListService,
sessionCoroutineScope, sessionCoroutineScope = sessionCoroutineScope,
dispatchers, coroutineDispatchers = dispatchers,
) )
override val roomSummaryDataSource: RoomSummaryDataSource override val roomSummaryDataSource: RoomSummaryDataSource
get() = rustRoomSummaryDataSource get() = rustRoomSummaryDataSource
private val rustInvitesDataSource: RustRoomSummaryDataSource =
RustRoomSummaryDataSource(
roomList,
sessionCoroutineScope,
dispatchers,
)
override val invitesDataSource: RoomSummaryDataSource
get() = rustInvitesDataSource
private val rustMediaLoader = RustMediaLoader(baseCacheDirectory, dispatchers, client) private val rustMediaLoader = RustMediaLoader(baseCacheDirectory, dispatchers, client)
override val mediaLoader: MatrixMediaLoader override val mediaLoader: MatrixMediaLoader
get() = rustMediaLoader get() = rustMediaLoader
@ -123,17 +113,16 @@ class RustMatrixClient constructor(
init { init {
client.setDelegate(clientDelegate) client.setDelegate(clientDelegate)
rustRoomSummaryDataSource.subscribeIfNeeded() rustRoomSummaryDataSource.init()
roomList.stateFlow() roomListService.stateFlow()
.onEach { .onEach {
Timber.v("onRoomList state change: $it") Timber.v("onRoomList state change: $it")
} }
.launchIn(sessionCoroutineScope) .launchIn(sessionCoroutineScope)
//rustInvitesDataSource.init()
} }
override fun getRoom(roomId: RoomId): MatrixRoom? { override fun getRoom(roomId: RoomId): MatrixRoom? {
val roomListItem = roomList.roomOrNull(roomId.value) ?: return null val roomListItem = roomListService.roomOrNull(roomId.value) ?: return null
val fullRoom = roomListItem.fullRoom() val fullRoom = roomListItem.fullRoom()
return RustMatrixRoom( return RustMatrixRoom(
sessionId = sessionId, sessionId = sessionId,
@ -185,7 +174,7 @@ class RustMatrixClient constructor(
// Wait to receive the room back from the sync // Wait to receive the room back from the sync
withTimeout(30_000L) { withTimeout(30_000L) {
roomSummaryDataSource.roomSummaries() roomSummaryDataSource.roomList()
.filter { roomSummaries -> .filter { roomSummaries ->
roomSummaries.map { it.identifier() }.contains(roomId.value) roomSummaries.map { it.identifier() }.contains(roomId.value)
}.first() }.first()
@ -226,14 +215,14 @@ class RustMatrixClient constructor(
override fun notificationService(): NotificationService = notificationService override fun notificationService(): NotificationService = notificationService
override fun startSync() { override fun startSync() {
if (!roomList.isSyncing()) { if (!roomListService.isSyncing()) {
roomList.sync() roomListService.sync()
} }
} }
override fun stopSync() { override fun stopSync() {
if (roomList.isSyncing()) { if (roomListService.isSyncing()) {
roomList.stopSync() roomListService.stopSync()
} }
} }
@ -242,7 +231,7 @@ class RustMatrixClient constructor(
sessionCoroutineScope.cancel() sessionCoroutineScope.cancel()
client.setDelegate(null) client.setDelegate(null)
verificationService.destroy() verificationService.destroy()
roomList.destroy() roomListService.destroy()
client.destroy() client.destroy()
} }

View file

@ -7,6 +7,7 @@ import org.matrix.rustcomponents.sdk.RoomList
import org.matrix.rustcomponents.sdk.RoomListEntriesListener import org.matrix.rustcomponents.sdk.RoomListEntriesListener
import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
import org.matrix.rustcomponents.sdk.RoomListEntry import org.matrix.rustcomponents.sdk.RoomListEntry
import org.matrix.rustcomponents.sdk.RoomListInterface
import org.matrix.rustcomponents.sdk.RoomListItem import org.matrix.rustcomponents.sdk.RoomListItem
import org.matrix.rustcomponents.sdk.RoomListState import org.matrix.rustcomponents.sdk.RoomListState
import org.matrix.rustcomponents.sdk.RoomListStateListener import org.matrix.rustcomponents.sdk.RoomListStateListener
@ -14,7 +15,7 @@ import org.matrix.rustcomponents.sdk.SlidingSyncListLoadingState
import org.matrix.rustcomponents.sdk.SlidingSyncListStateObserver import org.matrix.rustcomponents.sdk.SlidingSyncListStateObserver
import timber.log.Timber import timber.log.Timber
fun RoomList.stateFlow(): Flow<RoomListState> = fun RoomListInterface.stateFlow(): Flow<RoomListState> =
mxCallbackFlow { mxCallbackFlow {
val listener = object : RoomListStateListener { val listener = object : RoomListStateListener {
override fun onUpdate(state: RoomListState) { override fun onUpdate(state: RoomListState) {
@ -24,7 +25,7 @@ fun RoomList.stateFlow(): Flow<RoomListState> =
state(listener) state(listener)
} }
fun RoomList.loadingStateFlow(): Flow<SlidingSyncListLoadingState> = fun RoomListInterface.loadingStateFlow(): Flow<SlidingSyncListLoadingState> =
mxCallbackFlow { mxCallbackFlow {
val listener = object : SlidingSyncListStateObserver { val listener = object : SlidingSyncListStateObserver {
override fun didReceiveUpdate(newState: SlidingSyncListLoadingState) { override fun didReceiveUpdate(newState: SlidingSyncListLoadingState) {
@ -36,7 +37,7 @@ fun RoomList.loadingStateFlow(): Flow<SlidingSyncListLoadingState> =
result.entriesLoadingStateStream result.entriesLoadingStateStream
} }
fun RoomList.roomListEntriesUpdateFlow(onInitialList: suspend (List<RoomListEntry>) -> Unit): Flow<RoomListEntriesUpdate> = fun RoomListInterface.roomListEntriesUpdateFlow(onInitialList: suspend (List<RoomListEntry>) -> Unit): Flow<RoomListEntriesUpdate> =
mxCallbackFlow { mxCallbackFlow {
val listener = object : RoomListEntriesListener { val listener = object : RoomListEntriesListener {
override fun onUpdate(roomEntriesUpdate: RoomListEntriesUpdate) { override fun onUpdate(roomEntriesUpdate: RoomListEntriesUpdate) {
@ -48,7 +49,7 @@ fun RoomList.roomListEntriesUpdateFlow(onInitialList: suspend (List<RoomListEntr
result.entriesStream result.entriesStream
} }
fun RoomList.roomOrNull(roomId: String): RoomListItem? { fun RoomListInterface.roomOrNull(roomId: String): RoomListItem? {
return try { return try {
room(roomId) room(roomId)
} catch (failure: Throwable) { } catch (failure: Throwable) {

View file

@ -81,7 +81,7 @@ class RustMatrixRoom(
RustMatrixTimeline( RustMatrixTimeline(
matrixRoom = this, matrixRoom = this,
innerRoom = innerRoom, innerRoom = innerRoom,
coroutineScope = roomCoroutineScope, roomCoroutineScope = roomCoroutineScope,
coroutineDispatchers = coroutineDispatchers coroutineDispatchers = coroutineDispatchers
) )
} }

View file

@ -22,108 +22,111 @@ import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.getAndUpdate
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.matrix.rustcomponents.sdk.RoomList
import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
import org.matrix.rustcomponents.sdk.RoomListEntry import org.matrix.rustcomponents.sdk.RoomListEntry
import org.matrix.rustcomponents.sdk.RoomListException
import org.matrix.rustcomponents.sdk.RoomListInput import org.matrix.rustcomponents.sdk.RoomListInput
import org.matrix.rustcomponents.sdk.RoomListInterface
import org.matrix.rustcomponents.sdk.RoomListRange import org.matrix.rustcomponents.sdk.RoomListRange
import timber.log.Timber import timber.log.Timber
import java.util.UUID import java.util.UUID
internal class RustRoomSummaryDataSource( internal class RustRoomSummaryDataSource(
private val roomList: RoomList, private val roomListService: RoomListInterface,
private val sessionCoroutineScope: CoroutineScope, private val sessionCoroutineScope: CoroutineScope,
private val coroutineDispatchers: CoroutineDispatchers, private val coroutineDispatchers: CoroutineDispatchers,
private val roomSummaryDetailsFactory: RoomSummaryDetailsFactory = RoomSummaryDetailsFactory(), private val roomSummaryDetailsFactory: RoomSummaryDetailsFactory = RoomSummaryDetailsFactory(),
) : RoomSummaryDataSource { ) : RoomSummaryDataSource {
private val roomSummaries = MutableStateFlow<List<RoomSummary>>(emptyList()) private val roomList = MutableStateFlow<List<RoomSummary>>(emptyList())
private val inviteList = MutableStateFlow<List<RoomSummary>>(emptyList())
private val loadingState = MutableStateFlow(RoomSummaryDataSource.LoadingState.NotLoaded) private val loadingState = MutableStateFlow(RoomSummaryDataSource.LoadingState.NotLoaded)
fun subscribeIfNeeded() { fun init() {
sessionCoroutineScope.launch { sessionCoroutineScope.launch(coroutineDispatchers.computation) {
roomList.roomListEntriesUpdateFlow { roomListEntries -> roomListService.roomListEntriesUpdateFlow { roomListEntries ->
val summaries = roomListEntries.map(::buildSummaryForRoomListEntry) roomList.value = roomListEntries.map(::buildSummaryForRoomListEntry)
updateRoomSummaries { }.onEach { update ->
addAll(summaries) roomList.getAndUpdate {
} it.applyUpdate(update)
}.onEach {
updateRoomSummaries {
applyUpdate(it)
} }
}.launchIn(this) }.launchIn(this)
} }
} }
override fun roomSummaries(): StateFlow<List<RoomSummary>> { override fun roomList(): StateFlow<List<RoomSummary>> {
return roomSummaries return roomList
}
override fun inviteList(): StateFlow<List<RoomSummary>> {
return inviteList
} }
override fun loadingState(): StateFlow<RoomSummaryDataSource.LoadingState> { override fun loadingState(): StateFlow<RoomSummaryDataSource.LoadingState> {
return loadingState return loadingState
} }
override fun setSlidingSyncRange(range: IntRange) { override fun updateRoomListVisibleRange(range: IntRange) {
Timber.v("setVisibleRange=$range") Timber.v("setVisibleRange=$range")
sessionCoroutineScope.launch { sessionCoroutineScope.launch {
val ranges = listOf(RoomListRange(range.first.toUInt(), range.last.toUInt())) try {
roomList.applyInput( val ranges = listOf(RoomListRange(range.first.toUInt(), range.last.toUInt()))
RoomListInput.Viewport(ranges) roomListService.applyInput(
) RoomListInput.Viewport(ranges)
)
} catch (exception: RoomListException) {
Timber.e(exception, "Failed updating visible range")
}
} }
} }
private fun MutableList<RoomSummary>.applyUpdate(update: RoomListEntriesUpdate) { private fun List<RoomSummary>.applyUpdate(update: RoomListEntriesUpdate): List<RoomSummary> {
fun MutableList<RoomSummary>.fillUntil(untilIndex: Int) { val newList = toMutableList()
repeat((size - 1 until untilIndex).count()) {
add(buildEmptyRoomSummary())
}
}
when (update) { when (update) {
is RoomListEntriesUpdate.Append -> { is RoomListEntriesUpdate.Append -> {
val roomSummaries = update.values.map { val roomSummaries = update.values.map {
buildSummaryForRoomListEntry(it) buildSummaryForRoomListEntry(it)
} }
addAll(roomSummaries) newList.addAll(roomSummaries)
} }
is RoomListEntriesUpdate.PushBack -> { is RoomListEntriesUpdate.PushBack -> {
val roomSummary = buildSummaryForRoomListEntry(update.value) val roomSummary = buildSummaryForRoomListEntry(update.value)
add(roomSummary) newList.add(roomSummary)
} }
is RoomListEntriesUpdate.PushFront -> { is RoomListEntriesUpdate.PushFront -> {
val roomSummary = buildSummaryForRoomListEntry(update.value) val roomSummary = buildSummaryForRoomListEntry(update.value)
add(0, roomSummary) newList.add(0, roomSummary)
} }
is RoomListEntriesUpdate.Set -> { is RoomListEntriesUpdate.Set -> {
fillUntil(update.index.toInt())
val roomSummary = buildSummaryForRoomListEntry(update.value) val roomSummary = buildSummaryForRoomListEntry(update.value)
set(update.index.toInt(), roomSummary) newList[update.index.toInt()] = roomSummary
} }
is RoomListEntriesUpdate.Insert -> { is RoomListEntriesUpdate.Insert -> {
val roomSummary = buildSummaryForRoomListEntry(update.value) val roomSummary = buildSummaryForRoomListEntry(update.value)
add(update.index.toInt(), roomSummary) newList.add(update.index.toInt(), roomSummary)
} }
is RoomListEntriesUpdate.Remove -> { is RoomListEntriesUpdate.Remove -> {
removeAt(update.index.toInt()) newList.removeAt(update.index.toInt())
} }
is RoomListEntriesUpdate.Reset -> { is RoomListEntriesUpdate.Reset -> {
clear() newList.clear()
addAll(update.values.map { buildSummaryForRoomListEntry(it) }) newList.addAll(update.values.map { buildSummaryForRoomListEntry(it) })
} }
RoomListEntriesUpdate.PopBack -> { RoomListEntriesUpdate.PopBack -> {
removeFirstOrNull() newList.removeFirstOrNull()
} }
RoomListEntriesUpdate.PopFront -> { RoomListEntriesUpdate.PopFront -> {
removeLastOrNull() newList.removeLastOrNull()
} }
RoomListEntriesUpdate.Clear -> { RoomListEntriesUpdate.Clear -> {
clear() newList.clear()
} }
} }
return newList
} }
private fun buildSummaryForRoomListEntry(entry: RoomListEntry): RoomSummary { private fun buildSummaryForRoomListEntry(entry: RoomListEntry): RoomSummary {
@ -139,7 +142,7 @@ internal class RustRoomSummaryDataSource(
} }
private fun buildRoomSummaryForIdentifier(identifier: String): RoomSummary { private fun buildRoomSummaryForIdentifier(identifier: String): RoomSummary {
val roomListItem = roomList.roomOrNull(identifier) ?: return RoomSummary.Empty(identifier) val roomListItem = roomListService.roomOrNull(identifier) ?: return RoomSummary.Empty(identifier)
return roomListItem.use { return roomListItem.use {
roomListItem.fullRoom().use { fullRoom -> roomListItem.fullRoom().use { fullRoom ->
RoomSummary.Filled( RoomSummary.Filled(
@ -148,11 +151,4 @@ internal class RustRoomSummaryDataSource(
} }
} }
} }
private suspend fun updateRoomSummaries(block: MutableList<RoomSummary>.() -> Unit) =
withContext(coroutineDispatchers.diffUpdateDispatcher) {
val mutableRoomSummaries = roomSummaries.value.toMutableList()
block(mutableRoomSummaries)
roomSummaries.value = mutableRoomSummaries
}
} }

View file

@ -26,7 +26,7 @@ import org.matrix.rustcomponents.sdk.TimelineItem
class MatrixTimelineItemMapper( class MatrixTimelineItemMapper(
private val fetchDetailsForEvent: suspend (EventId) -> Result<Unit>, private val fetchDetailsForEvent: suspend (EventId) -> Result<Unit>,
private val coroutineScope: CoroutineScope, private val roomCoroutineScope: CoroutineScope,
private val virtualTimelineItemMapper: VirtualTimelineItemMapper = VirtualTimelineItemMapper(), private val virtualTimelineItemMapper: VirtualTimelineItemMapper = VirtualTimelineItemMapper(),
private val eventTimelineItemMapper: EventTimelineItemMapper = EventTimelineItemMapper(), private val eventTimelineItemMapper: EventTimelineItemMapper = EventTimelineItemMapper(),
) { ) {
@ -51,7 +51,7 @@ class MatrixTimelineItemMapper(
return MatrixTimelineItem.Other return MatrixTimelineItem.Other
} }
private fun fetchEventDetails(eventId: EventId) = coroutineScope.launch { private fun fetchEventDetails(eventId: EventId) = roomCoroutineScope.launch {
fetchDetailsForEvent(eventId) fetchDetailsForEvent(eventId)
} }
} }

View file

@ -39,7 +39,7 @@ import org.matrix.rustcomponents.sdk.TimelineItem
import timber.log.Timber import timber.log.Timber
class RustMatrixTimeline( class RustMatrixTimeline(
coroutineScope: CoroutineScope, roomCoroutineScope: CoroutineScope,
private val matrixRoom: MatrixRoom, private val matrixRoom: MatrixRoom,
private val innerRoom: Room, private val innerRoom: Room,
private val coroutineDispatchers: CoroutineDispatchers, private val coroutineDispatchers: CoroutineDispatchers,
@ -54,7 +54,7 @@ class RustMatrixTimeline(
private val timelineItemFactory = MatrixTimelineItemMapper( private val timelineItemFactory = MatrixTimelineItemMapper(
fetchDetailsForEvent = this::fetchDetailsForEvent, fetchDetailsForEvent = this::fetchDetailsForEvent,
coroutineScope = coroutineScope, roomCoroutineScope = roomCoroutineScope,
virtualTimelineItemMapper = VirtualTimelineItemMapper(), virtualTimelineItemMapper = VirtualTimelineItemMapper(),
eventTimelineItemMapper = EventTimelineItemMapper( eventTimelineItemMapper = EventTimelineItemMapper(
contentMapper = TimelineEventContentMapper( contentMapper = TimelineEventContentMapper(
@ -66,7 +66,7 @@ class RustMatrixTimeline(
private val timelineDiffProcessor = MatrixTimelineDiffProcessor( private val timelineDiffProcessor = MatrixTimelineDiffProcessor(
paginationState = paginationState, paginationState = paginationState,
timelineItems = timelineItems, timelineItems = timelineItems,
coroutineScope = coroutineScope, coroutineScope = roomCoroutineScope,
diffDispatcher = coroutineDispatchers.diffUpdateDispatcher, diffDispatcher = coroutineDispatchers.diffUpdateDispatcher,
timelineItemFactory = timelineItemFactory, timelineItemFactory = timelineItemFactory,
) )

View file

@ -29,14 +29,14 @@ class FakeRoomSummaryDataSource : RoomSummaryDataSource {
roomSummariesFlow.emit(roomSummaries) roomSummariesFlow.emit(roomSummaries)
} }
override fun roomSummaries(): StateFlow<List<RoomSummary>> { override fun roomList(): StateFlow<List<RoomSummary>> {
return roomSummariesFlow return roomSummariesFlow
} }
var latestSlidingSyncRange: IntRange? = null var latestSlidingSyncRange: IntRange? = null
private set private set
override fun setSlidingSyncRange(range: IntRange) { override fun updateRoomListVisibleRange(range: IntRange) {
latestSlidingSyncRange = range latestSlidingSyncRange = range
} }
} }