Start implementing timeline
This commit is contained in:
parent
ed764c097f
commit
8f3233e450
9 changed files with 289 additions and 23 deletions
|
|
@ -4,9 +4,7 @@ import io.element.android.x.core.data.CoroutineDispatchers
|
|||
import io.element.android.x.matrix.core.UserId
|
||||
import io.element.android.x.matrix.room.MatrixRoom
|
||||
import io.element.android.x.matrix.room.RoomSummaryDataSource
|
||||
import io.element.android.x.matrix.room.RoomSummaryDetailsFactory
|
||||
import io.element.android.x.matrix.room.RustRoomSummaryDataSource
|
||||
import io.element.android.x.matrix.room.message.RoomMessageFactory
|
||||
import io.element.android.x.matrix.session.SessionStore
|
||||
import io.element.android.x.matrix.sync.SlidingSyncObserverProxy
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -58,7 +56,12 @@ class MatrixClient internal constructor(
|
|||
|
||||
private val slidingSyncObserverProxy = SlidingSyncObserverProxy(coroutineScope)
|
||||
private val roomSummaryDataSource: RustRoomSummaryDataSource =
|
||||
RustRoomSummaryDataSource(slidingSyncObserverProxy.updateSummaryFlow, slidingSync, slidingSyncView, dispatchers)
|
||||
RustRoomSummaryDataSource(
|
||||
slidingSyncObserverProxy.updateSummaryFlow,
|
||||
slidingSync,
|
||||
slidingSyncView,
|
||||
dispatchers
|
||||
)
|
||||
private var slidingSyncObserverToken: StoppableSpawn? = null
|
||||
|
||||
init {
|
||||
|
|
@ -71,7 +74,8 @@ class MatrixClient internal constructor(
|
|||
return MatrixRoom(
|
||||
slidingSyncUpdateFlow = slidingSyncObserverProxy.updateSummaryFlow,
|
||||
slidingSyncRoom = slidingSyncRoom,
|
||||
room = room
|
||||
room = room,
|
||||
coroutineDispatchers = dispatchers
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,21 @@
|
|||
package io.element.android.x.matrix.room
|
||||
|
||||
import io.element.android.x.core.data.CoroutineDispatchers
|
||||
import io.element.android.x.matrix.core.RoomId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.SlidingSyncRoom
|
||||
import org.matrix.rustcomponents.sdk.UpdateSummary
|
||||
import io.element.android.x.matrix.timeline.MatrixTimeline
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.rustcomponents.sdk.*
|
||||
|
||||
class MatrixRoom(
|
||||
private val slidingSyncUpdateFlow: Flow<UpdateSummary>,
|
||||
private val slidingSyncRoom: SlidingSyncRoom,
|
||||
private val room: Room,
|
||||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
) {
|
||||
|
||||
private val paginationOutcome = MutableStateFlow(PaginationOutcome(true))
|
||||
fun syncUpdateFlow(): Flow<Unit> {
|
||||
return slidingSyncUpdateFlow
|
||||
.filter {
|
||||
|
|
@ -24,6 +25,14 @@ class MatrixRoom(
|
|||
.onStart { emit(Unit) }
|
||||
}
|
||||
|
||||
fun timeline(): MatrixTimeline {
|
||||
return MatrixTimeline(this)
|
||||
}
|
||||
|
||||
internal fun timelineDiff(): Flow<TimelineDiff> {
|
||||
return room.timelineDiff()
|
||||
}
|
||||
|
||||
val roomId = RoomId(room.id())
|
||||
|
||||
val name: String?
|
||||
|
|
@ -46,5 +55,18 @@ class MatrixRoom(
|
|||
return room.avatarUrl()
|
||||
}
|
||||
|
||||
fun addTimelineListener(timelineListener: TimelineListener) {
|
||||
room.addTimelineListener(timelineListener)
|
||||
}
|
||||
|
||||
suspend fun paginateBackwards(count: Int): Result<Unit> = withContext(coroutineDispatchers.io) {
|
||||
if (!paginationOutcome.value.moreMessages) {
|
||||
return@withContext Result.failure(IllegalStateException("no more message"))
|
||||
}
|
||||
runCatching {
|
||||
paginationOutcome.value = room.paginateBackwards(count.toUShort())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package io.element.android.x.matrix.room
|
||||
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.TimelineDiff
|
||||
import org.matrix.rustcomponents.sdk.TimelineListener
|
||||
|
||||
|
||||
fun Room.timelineDiff(): Flow<TimelineDiff> = callbackFlow {
|
||||
val listener = object : TimelineListener {
|
||||
override fun onUpdate(update: TimelineDiff) {
|
||||
trySend(update)
|
||||
}
|
||||
}
|
||||
addTimelineListener(listener)
|
||||
awaitClose {
|
||||
removeTimeline()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ internal class RustRoomSummaryDataSource(
|
|||
add(roomSummary)
|
||||
}
|
||||
is SlidingSyncViewRoomsListDiff.UpdateAt -> {
|
||||
//fillUntil(diff.index.toInt())
|
||||
fillUntil(diff.index.toInt())
|
||||
val roomSummary = buildSummaryForRoomListEntry(diff.value)
|
||||
set(diff.index.toInt(), roomSummary)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
package io.element.android.x.matrix.timeline
|
||||
|
||||
import io.element.android.x.matrix.core.EventId
|
||||
import io.element.android.x.matrix.room.MatrixRoom
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.matrix.rustcomponents.sdk.TimelineChange
|
||||
import org.matrix.rustcomponents.sdk.TimelineDiff
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
|
||||
class MatrixTimeline(
|
||||
private val room: MatrixRoom,
|
||||
) {
|
||||
|
||||
interface Callback {
|
||||
fun onUpdatedTimelineItem(eventId: EventId)
|
||||
fun onStartedBackPaginating()
|
||||
fun onFinishedBackPaginating()
|
||||
}
|
||||
|
||||
var callback: Callback? = null
|
||||
|
||||
private val timelineItems: MutableStateFlow<List<MatrixTimelineItem>> =
|
||||
MutableStateFlow(emptyList())
|
||||
|
||||
|
||||
fun timelineItems(): Flow<List<MatrixTimelineItem>> {
|
||||
return diffFlow().combine(timelineItems) { _, _ ->
|
||||
timelineItems.value.reversed()
|
||||
}
|
||||
}
|
||||
|
||||
private fun diffFlow(): Flow<Unit> {
|
||||
return room.timelineDiff()
|
||||
.onEach { timelineDiff ->
|
||||
updateTimelineItems {
|
||||
applyDiff(timelineDiff)
|
||||
}
|
||||
}.map { }
|
||||
}
|
||||
|
||||
private fun MutableList<MatrixTimelineItem>.applyDiff(diff: TimelineDiff) {
|
||||
Timber.v("ApplyDiff: ${diff.change()} for list with size: $size")
|
||||
when (diff.change()) {
|
||||
TimelineChange.PUSH -> {
|
||||
val item = diff.push()?.asMatrixTimelineItem() ?: return
|
||||
add(item)
|
||||
}
|
||||
TimelineChange.UPDATE_AT -> {
|
||||
val updateAtData = diff.updateAt() ?: return
|
||||
val item = updateAtData.item.asMatrixTimelineItem()
|
||||
set(updateAtData.index.toInt(), item)
|
||||
}
|
||||
TimelineChange.INSERT_AT -> {
|
||||
val insertAtData = diff.insertAt() ?: return
|
||||
val item = insertAtData.item.asMatrixTimelineItem()
|
||||
add(insertAtData.index.toInt(), item)
|
||||
}
|
||||
TimelineChange.MOVE -> {
|
||||
val moveData = diff.move() ?: return
|
||||
Collections.swap(this, moveData.oldIndex.toInt(), moveData.newIndex.toInt())
|
||||
}
|
||||
TimelineChange.REMOVE_AT -> {
|
||||
val removeAtData = diff.removeAt() ?: return
|
||||
removeAt(removeAtData.toInt())
|
||||
}
|
||||
TimelineChange.REPLACE -> {
|
||||
clear()
|
||||
val items = diff.replace()?.map { it.asMatrixTimelineItem() } ?: return
|
||||
addAll(items)
|
||||
}
|
||||
TimelineChange.POP -> {
|
||||
removeLast()
|
||||
}
|
||||
TimelineChange.CLEAR -> {
|
||||
clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTimelineItems(block: MutableList<MatrixTimelineItem>.() -> Unit) {
|
||||
val mutableTimelineItems = timelineItems.value.toMutableList()
|
||||
block(mutableTimelineItems)
|
||||
timelineItems.value = mutableTimelineItems
|
||||
}
|
||||
|
||||
|
||||
suspend fun processItemAppearance(itemId: String) {
|
||||
|
||||
}
|
||||
|
||||
suspend fun processItemDisappearance(itemId: String) {
|
||||
|
||||
}
|
||||
|
||||
suspend fun paginateBackwards(count: Int): Result<Unit> {
|
||||
return room.paginateBackwards(count)
|
||||
}
|
||||
|
||||
suspend fun sendMessage(message: String): Result<Unit> {
|
||||
return Result.success(Unit)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package io.element.android.x.matrix.timeline
|
||||
|
||||
import org.matrix.rustcomponents.sdk.EventTimelineItem
|
||||
import org.matrix.rustcomponents.sdk.TimelineItem
|
||||
|
||||
sealed interface MatrixTimelineItem {
|
||||
data class Event(val event: EventTimelineItem) : MatrixTimelineItem
|
||||
object Virtual : MatrixTimelineItem
|
||||
object Other : MatrixTimelineItem
|
||||
}
|
||||
|
||||
fun TimelineItem.asMatrixTimelineItem(): MatrixTimelineItem {
|
||||
val asEvent = asEvent()
|
||||
if (asEvent != null) {
|
||||
return MatrixTimelineItem.Event(asEvent)
|
||||
}
|
||||
val asVirtual = asVirtual()
|
||||
if (asVirtual != null) {
|
||||
return MatrixTimelineItem.Virtual
|
||||
}
|
||||
return MatrixTimelineItem.Other
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue