Try to fix some issues with roomList and timeline...
This commit is contained in:
parent
089e1da4b7
commit
bf57b54fee
10 changed files with 107 additions and 78 deletions
|
|
@ -67,6 +67,7 @@ class MessagesViewModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleInit() {
|
private fun handleInit() {
|
||||||
|
timeline.initialize()
|
||||||
room.syncUpdateFlow()
|
room.syncUpdateFlow()
|
||||||
.onEach {
|
.onEach {
|
||||||
val avatarData =
|
val avatarData =
|
||||||
|
|
@ -97,5 +98,6 @@ class MessagesViewModel(
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
|
timeline.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,4 +6,5 @@ data class CoroutineDispatchers(
|
||||||
val io: CoroutineDispatcher,
|
val io: CoroutineDispatcher,
|
||||||
val computation: CoroutineDispatcher,
|
val computation: CoroutineDispatcher,
|
||||||
val main: CoroutineDispatcher,
|
val main: CoroutineDispatcher,
|
||||||
|
val diffUpdateDispatcher: CoroutineDispatcher,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,15 @@ import io.element.android.x.matrix.session.SessionStore
|
||||||
import io.element.android.x.matrix.util.logError
|
import io.element.android.x.matrix.util.logError
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.asCoroutineDispatcher
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.matrix.rustcomponents.sdk.AuthenticationService
|
import org.matrix.rustcomponents.sdk.AuthenticationService
|
||||||
import org.matrix.rustcomponents.sdk.Client
|
import org.matrix.rustcomponents.sdk.Client
|
||||||
import org.matrix.rustcomponents.sdk.ClientBuilder
|
import org.matrix.rustcomponents.sdk.ClientBuilder
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
class Matrix(
|
class Matrix(
|
||||||
private val coroutineScope: CoroutineScope,
|
private val coroutineScope: CoroutineScope,
|
||||||
|
|
@ -22,7 +23,8 @@ class Matrix(
|
||||||
private val coroutineDispatchers = CoroutineDispatchers(
|
private val coroutineDispatchers = CoroutineDispatchers(
|
||||||
io = Dispatchers.IO,
|
io = Dispatchers.IO,
|
||||||
computation = Dispatchers.Default,
|
computation = Dispatchers.Default,
|
||||||
main = Dispatchers.Main
|
main = Dispatchers.Main,
|
||||||
|
diffUpdateDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
|
||||||
)
|
)
|
||||||
private val baseFolder = File(context.filesDir, "matrix")
|
private val baseFolder = File(context.filesDir, "matrix")
|
||||||
private val sessionStore = SessionStore(context)
|
private val sessionStore = SessionStore(context)
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ class MatrixClient internal constructor(
|
||||||
.addView(slidingSyncView)
|
.addView(slidingSyncView)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
private val slidingSyncObserverProxy = SlidingSyncObserverProxy(coroutineScope)
|
private val slidingSyncObserverProxy = SlidingSyncObserverProxy(coroutineScope, dispatchers)
|
||||||
private val roomSummaryDataSource: RustRoomSummaryDataSource =
|
private val roomSummaryDataSource: RustRoomSummaryDataSource =
|
||||||
RustRoomSummaryDataSource(
|
RustRoomSummaryDataSource(
|
||||||
slidingSyncObserverProxy.updateSummaryFlow,
|
slidingSyncObserverProxy.updateSummaryFlow,
|
||||||
|
|
@ -81,6 +81,7 @@ class MatrixClient internal constructor(
|
||||||
slidingSyncUpdateFlow = slidingSyncObserverProxy.updateSummaryFlow,
|
slidingSyncUpdateFlow = slidingSyncObserverProxy.updateSummaryFlow,
|
||||||
slidingSyncRoom = slidingSyncRoom,
|
slidingSyncRoom = slidingSyncRoom,
|
||||||
room = room,
|
room = room,
|
||||||
|
coroutineScope = coroutineScope,
|
||||||
coroutineDispatchers = dispatchers
|
coroutineDispatchers = dispatchers
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import io.element.android.x.core.coroutine.CoroutineDispatchers
|
||||||
import io.element.android.x.matrix.core.RoomId
|
import io.element.android.x.matrix.core.RoomId
|
||||||
import io.element.android.x.matrix.core.UserId
|
import io.element.android.x.matrix.core.UserId
|
||||||
import io.element.android.x.matrix.timeline.MatrixTimeline
|
import io.element.android.x.matrix.timeline.MatrixTimeline
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
@ -15,6 +16,7 @@ class MatrixRoom(
|
||||||
private val slidingSyncUpdateFlow: Flow<UpdateSummary>,
|
private val slidingSyncUpdateFlow: Flow<UpdateSummary>,
|
||||||
private val slidingSyncRoom: SlidingSyncRoom,
|
private val slidingSyncRoom: SlidingSyncRoom,
|
||||||
private val room: Room,
|
private val room: Room,
|
||||||
|
private val coroutineScope: CoroutineScope,
|
||||||
private val coroutineDispatchers: CoroutineDispatchers,
|
private val coroutineDispatchers: CoroutineDispatchers,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
@ -28,7 +30,7 @@ class MatrixRoom(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun timeline(): MatrixTimeline {
|
fun timeline(): MatrixTimeline {
|
||||||
return MatrixTimeline(this, room, coroutineDispatchers)
|
return MatrixTimeline(this, room, coroutineScope, coroutineDispatchers)
|
||||||
}
|
}
|
||||||
|
|
||||||
val roomId = RoomId(room.id())
|
val roomId = RoomId(room.id())
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,21 @@
|
||||||
package io.element.android.x.matrix.room
|
package io.element.android.x.matrix.room
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.rustcomponents.sdk.Room
|
import org.matrix.rustcomponents.sdk.Room
|
||||||
import org.matrix.rustcomponents.sdk.TimelineDiff
|
import org.matrix.rustcomponents.sdk.TimelineDiff
|
||||||
import org.matrix.rustcomponents.sdk.TimelineListener
|
import org.matrix.rustcomponents.sdk.TimelineListener
|
||||||
|
|
||||||
|
|
||||||
fun Room.timelineDiff(): Flow<TimelineDiff> = callbackFlow {
|
fun Room.timelineDiff(scope: CoroutineScope): Flow<TimelineDiff> = callbackFlow {
|
||||||
val listener = object : TimelineListener {
|
val listener = object : TimelineListener {
|
||||||
override fun onUpdate(update: TimelineDiff) {
|
override fun onUpdate(update: TimelineDiff) {
|
||||||
trySend(update)
|
scope.launch {
|
||||||
|
send(update)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addTimelineListener(listener)
|
addTimelineListener(listener)
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import org.matrix.rustcomponents.sdk.*
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.Executors
|
|
||||||
|
|
||||||
interface RoomSummaryDataSource {
|
interface RoomSummaryDataSource {
|
||||||
fun roomSummaries(): Flow<List<RoomSummary>>
|
fun roomSummaries(): Flow<List<RoomSummary>>
|
||||||
|
|
@ -23,8 +22,7 @@ internal class RustRoomSummaryDataSource(
|
||||||
private val roomSummaryDetailsFactory: RoomSummaryDetailsFactory = RoomSummaryDetailsFactory()
|
private val roomSummaryDetailsFactory: RoomSummaryDetailsFactory = RoomSummaryDetailsFactory()
|
||||||
) : RoomSummaryDataSource, Closeable {
|
) : RoomSummaryDataSource, Closeable {
|
||||||
|
|
||||||
private val singleDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
|
private val coroutineScope = CoroutineScope(SupervisorJob() + coroutineDispatchers.io)
|
||||||
private val coroutineScope = CoroutineScope(SupervisorJob() + singleDispatcher)
|
|
||||||
|
|
||||||
private val roomSummaries = MutableStateFlow<List<RoomSummary>>(emptyList())
|
private val roomSummaries = MutableStateFlow<List<RoomSummary>>(emptyList())
|
||||||
private val state = MutableStateFlow(SlidingSyncState.COLD)
|
private val state = MutableStateFlow(SlidingSyncState.COLD)
|
||||||
|
|
@ -32,30 +30,31 @@ internal class RustRoomSummaryDataSource(
|
||||||
fun startSync() {
|
fun startSync() {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
updateRoomSummaries {
|
updateRoomSummaries {
|
||||||
clear()
|
|
||||||
addAll(
|
addAll(
|
||||||
slidingSyncView.currentRoomsList().map(::buildSummaryForRoomListEntry)
|
slidingSyncView.currentRoomsList().map(::buildSummaryForRoomListEntry)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
slidingSyncView.roomListDiff()
|
|
||||||
.onEach { diffs ->
|
|
||||||
updateRoomSummaries {
|
|
||||||
applyDiff(diffs)
|
|
||||||
}
|
|
||||||
}.collect()
|
|
||||||
|
|
||||||
slidingSyncView.state()
|
|
||||||
.onEach { slidingSyncState ->
|
|
||||||
Timber.v("New sliding sync state: $slidingSyncState")
|
|
||||||
state.value = slidingSyncState
|
|
||||||
}.collect()
|
|
||||||
|
|
||||||
slidingSyncUpdateFlow
|
|
||||||
.onEach {
|
|
||||||
didReceiveSyncUpdate(it)
|
|
||||||
}.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slidingSyncUpdateFlow
|
||||||
|
.onEach {
|
||||||
|
didReceiveSyncUpdate(it)
|
||||||
|
}.launchIn(coroutineScope)
|
||||||
|
|
||||||
|
slidingSyncView.roomListDiff(coroutineScope)
|
||||||
|
.onEach { diffs ->
|
||||||
|
updateRoomSummaries {
|
||||||
|
applyDiff(diffs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.launchIn(coroutineScope)
|
||||||
|
|
||||||
|
slidingSyncView.state(coroutineScope)
|
||||||
|
.onEach { slidingSyncState ->
|
||||||
|
Timber.v("New sliding sync state: $slidingSyncState")
|
||||||
|
state.value = slidingSyncState
|
||||||
|
}.launchIn(coroutineScope)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stopSync() {
|
fun stopSync() {
|
||||||
|
|
@ -70,7 +69,7 @@ internal class RustRoomSummaryDataSource(
|
||||||
return roomSummaries.sample(50)
|
return roomSummaries.sample(50)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun didReceiveSyncUpdate(summary: UpdateSummary) {
|
private suspend fun didReceiveSyncUpdate(summary: UpdateSummary) {
|
||||||
Timber.v("UpdateRooms with identifiers: ${summary.rooms}")
|
Timber.v("UpdateRooms with identifiers: ${summary.rooms}")
|
||||||
if (state.value != SlidingSyncState.LIVE) {
|
if (state.value != SlidingSyncState.LIVE) {
|
||||||
return
|
return
|
||||||
|
|
@ -141,19 +140,18 @@ internal class RustRoomSummaryDataSource(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateRoomSummaries(block: MutableList<RoomSummary>.() -> Unit) {
|
private suspend fun updateRoomSummaries(block: MutableList<RoomSummary>.() -> Unit) = withContext(coroutineDispatchers.diffUpdateDispatcher){
|
||||||
val mutableRoomSummaries = roomSummaries.value.toMutableList()
|
val mutableRoomSummaries = roomSummaries.value.toMutableList()
|
||||||
block(mutableRoomSummaries)
|
block(mutableRoomSummaries)
|
||||||
roomSummaries.value = mutableRoomSummaries
|
roomSummaries.value = mutableRoomSummaries
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
fun SlidingSyncViewRoomsListDiff.isInvalidation(): Boolean {
|
||||||
|
return when (this) {
|
||||||
fun SlidingSyncViewRoomsListDiff.isInvalidation(): Boolean {
|
is SlidingSyncViewRoomsListDiff.InsertAt -> this.value is RoomListEntry.Invalidated
|
||||||
return when (this) {
|
is SlidingSyncViewRoomsListDiff.UpdateAt -> this.value is RoomListEntry.Invalidated
|
||||||
is SlidingSyncViewRoomsListDiff.InsertAt -> this.value is RoomListEntry.Invalidated
|
is SlidingSyncViewRoomsListDiff.Push -> this.value is RoomListEntry.Invalidated
|
||||||
is SlidingSyncViewRoomsListDiff.UpdateAt -> this.value is RoomListEntry.Invalidated
|
else -> false
|
||||||
is SlidingSyncViewRoomsListDiff.Push -> this.value is RoomListEntry.Invalidated
|
}
|
||||||
else -> false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,21 +1,28 @@
|
||||||
package io.element.android.x.matrix.sync
|
package io.element.android.x.matrix.sync
|
||||||
|
|
||||||
|
import io.element.android.x.core.coroutine.CoroutineDispatchers
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.rustcomponents.sdk.SlidingSyncObserver
|
import org.matrix.rustcomponents.sdk.SlidingSyncObserver
|
||||||
import org.matrix.rustcomponents.sdk.UpdateSummary
|
import org.matrix.rustcomponents.sdk.UpdateSummary
|
||||||
import org.matrix.rustcomponents.sdk.setupTracing
|
|
||||||
|
|
||||||
class SlidingSyncObserverProxy(private val coroutineScope: CoroutineScope) : SlidingSyncObserver {
|
// Sounds like a reasonable buffer size before it suspends emitting new items.
|
||||||
|
private const val BUFFER_SIZE = 64
|
||||||
|
class SlidingSyncObserverProxy(
|
||||||
|
private val coroutineScope: CoroutineScope,
|
||||||
|
private val coroutineDispatchers: CoroutineDispatchers
|
||||||
|
) : SlidingSyncObserver {
|
||||||
|
|
||||||
private val updateSummaryMutableFlow = MutableSharedFlow<UpdateSummary>()
|
private val updateSummaryMutableFlow =
|
||||||
val updateSummaryFlow: Flow<UpdateSummary> = updateSummaryMutableFlow
|
MutableSharedFlow<UpdateSummary>(extraBufferCapacity = BUFFER_SIZE)
|
||||||
|
val updateSummaryFlow: SharedFlow<UpdateSummary> = updateSummaryMutableFlow.asSharedFlow()
|
||||||
|
|
||||||
override fun didReceiveSyncUpdate(summary: UpdateSummary) {
|
override fun didReceiveSyncUpdate(summary: UpdateSummary) {
|
||||||
if (summary.rooms.isEmpty()) return
|
if (summary.rooms.isEmpty()) return
|
||||||
coroutineScope.launch {
|
coroutineScope.launch(coroutineDispatchers.io) {
|
||||||
updateSummaryMutableFlow.emit(summary)
|
updateSummaryMutableFlow.emit(summary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,40 @@
|
||||||
package io.element.android.x.matrix.sync
|
package io.element.android.x.matrix.sync
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import mxCallbackFlow
|
import mxCallbackFlow
|
||||||
import org.matrix.rustcomponents.sdk.*
|
import org.matrix.rustcomponents.sdk.*
|
||||||
|
|
||||||
fun SlidingSyncView.roomListDiff(): Flow<SlidingSyncViewRoomsListDiff> = mxCallbackFlow {
|
fun SlidingSyncView.roomListDiff(scope: CoroutineScope): Flow<SlidingSyncViewRoomsListDiff> =
|
||||||
val observer = object : SlidingSyncViewRoomListObserver {
|
mxCallbackFlow {
|
||||||
override fun didReceiveUpdate(diff: SlidingSyncViewRoomsListDiff) {
|
val observer = object : SlidingSyncViewRoomListObserver {
|
||||||
trySend(diff)
|
override fun didReceiveUpdate(diff: SlidingSyncViewRoomsListDiff) {
|
||||||
|
scope.launch {
|
||||||
|
send(diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
observeRoomList(observer)
|
||||||
}
|
}
|
||||||
observeRoomList(observer)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun SlidingSyncView.state(): Flow<SlidingSyncState> = mxCallbackFlow {
|
fun SlidingSyncView.state(scope: CoroutineScope): Flow<SlidingSyncState> = mxCallbackFlow {
|
||||||
val observer = object : SlidingSyncViewStateObserver {
|
val observer = object : SlidingSyncViewStateObserver {
|
||||||
override fun didReceiveUpdate(newState: SlidingSyncState) {
|
override fun didReceiveUpdate(newState: SlidingSyncState) {
|
||||||
trySend(newState)
|
scope.launch {
|
||||||
|
send(newState)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
observeState(observer)
|
observeState(observer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SlidingSyncView.roomsCount(): Flow<UInt> = mxCallbackFlow {
|
fun SlidingSyncView.roomsCount(scope: CoroutineScope): Flow<UInt> = mxCallbackFlow {
|
||||||
val observer = object : SlidingSyncViewRoomsCountObserver {
|
val observer = object : SlidingSyncViewRoomsCountObserver {
|
||||||
override fun didReceiveUpdate(count: UInt) {
|
override fun didReceiveUpdate(count: UInt) {
|
||||||
trySend(count)
|
scope.launch {
|
||||||
|
send(count)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
observeRoomsCount(observer)
|
observeRoomsCount(observer)
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
package io.element.android.x.matrix.timeline
|
package io.element.android.x.matrix.timeline
|
||||||
|
|
||||||
import io.element.android.x.core.coroutine.CoroutineDispatchers
|
import io.element.android.x.core.coroutine.CoroutineDispatchers
|
||||||
import io.element.android.x.core.data.flow.chunk
|
|
||||||
import io.element.android.x.matrix.core.EventId
|
import io.element.android.x.matrix.core.EventId
|
||||||
import io.element.android.x.matrix.room.MatrixRoom
|
import io.element.android.x.matrix.room.MatrixRoom
|
||||||
import io.element.android.x.matrix.room.timelineDiff
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.sample
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.matrix.rustcomponents.sdk.*
|
import org.matrix.rustcomponents.sdk.*
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
@ -14,8 +16,9 @@ import java.util.*
|
||||||
class MatrixTimeline(
|
class MatrixTimeline(
|
||||||
private val matrixRoom: MatrixRoom,
|
private val matrixRoom: MatrixRoom,
|
||||||
private val room: Room,
|
private val room: Room,
|
||||||
|
private val coroutineScope: CoroutineScope,
|
||||||
private val coroutineDispatchers: CoroutineDispatchers,
|
private val coroutineDispatchers: CoroutineDispatchers,
|
||||||
) {
|
) : TimelineListener {
|
||||||
interface Callback {
|
interface Callback {
|
||||||
fun onUpdatedTimelineItem(eventId: EventId)
|
fun onUpdatedTimelineItem(eventId: EventId)
|
||||||
fun onStartedBackPaginating()
|
fun onStartedBackPaginating()
|
||||||
|
|
@ -30,9 +33,7 @@ class MatrixTimeline(
|
||||||
|
|
||||||
|
|
||||||
fun timelineItems(): Flow<List<MatrixTimelineItem>> {
|
fun timelineItems(): Flow<List<MatrixTimelineItem>> {
|
||||||
return diffFlow().combine(timelineItems) { _, _ ->
|
return timelineItems.sample(50)
|
||||||
timelineItems.value
|
|
||||||
}.sample(50)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val hasMoreToLoad: Boolean
|
val hasMoreToLoad: Boolean
|
||||||
|
|
@ -41,17 +42,6 @@ class MatrixTimeline(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun diffFlow(): Flow<Unit> {
|
|
||||||
return room.timelineDiff()
|
|
||||||
.onEach { timelineDiffs ->
|
|
||||||
//Timber.v("Apply ${timelineDiffs.size} diffs on thread: ${Thread.currentThread()}")
|
|
||||||
updateTimelineItems {
|
|
||||||
applyDiff(timelineDiffs)
|
|
||||||
}
|
|
||||||
}.map { }
|
|
||||||
.flowOn(coroutineDispatchers.computation)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun MutableList<MatrixTimelineItem>.applyDiff(diff: TimelineDiff) {
|
private fun MutableList<MatrixTimelineItem>.applyDiff(diff: TimelineDiff) {
|
||||||
when (diff.change()) {
|
when (diff.change()) {
|
||||||
TimelineChange.PUSH -> {
|
TimelineChange.PUSH -> {
|
||||||
|
|
@ -107,16 +97,21 @@ class MatrixTimeline(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTimelineItems(block: MutableList<MatrixTimelineItem>.() -> Unit) {
|
private suspend fun updateTimelineItems(block: MutableList<MatrixTimelineItem>.() -> Unit) =
|
||||||
val mutableTimelineItems = timelineItems.value.toMutableList()
|
withContext(coroutineDispatchers.diffUpdateDispatcher) {
|
||||||
block(mutableTimelineItems)
|
val mutableTimelineItems = timelineItems.value.toMutableList()
|
||||||
timelineItems.value = mutableTimelineItems
|
block(mutableTimelineItems)
|
||||||
}
|
timelineItems.value = mutableTimelineItems
|
||||||
|
}
|
||||||
|
|
||||||
fun addListener(timelineListener: TimelineListener) {
|
fun addListener(timelineListener: TimelineListener) {
|
||||||
room.addTimelineListener(timelineListener)
|
room.addTimelineListener(timelineListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun initialize() {
|
||||||
|
addListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
fun dispose() {
|
fun dispose() {
|
||||||
room.removeTimeline()
|
room.removeTimeline()
|
||||||
}
|
}
|
||||||
|
|
@ -128,4 +123,12 @@ class MatrixTimeline(
|
||||||
return matrixRoom.sendMessage(message)
|
return matrixRoom.sendMessage(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onUpdate(update: TimelineDiff) {
|
||||||
|
coroutineScope.launch {
|
||||||
|
updateTimelineItems {
|
||||||
|
applyDiff(update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue