Update rust-sdk (from maven)

This commit is contained in:
ganfra
2023-02-24 15:05:20 +01:00
parent 8d4d8e96bd
commit 247f6d2188
12 changed files with 86 additions and 96 deletions

View File

@@ -28,8 +28,6 @@ import io.element.android.features.messages.timeline.factories.TimelineItemsFact
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.core.EventId
import io.element.android.libraries.matrix.room.MatrixRoom
import io.element.android.libraries.matrix.timeline.MatrixTimeline
import io.element.android.libraries.matrix.timeline.MatrixTimelineItem
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
@@ -47,17 +45,6 @@ class TimelinePresenter @Inject constructor(
private val timeline = room.timeline()
private class TimelineCallback(
private val coroutineScope: CoroutineScope,
private val timelineItemsFactory: TimelineItemsFactory,
) : MatrixTimeline.Callback {
override fun onPushedTimelineItem(timelineItem: MatrixTimelineItem) {
coroutineScope.launch {
timelineItemsFactory.pushItem(timelineItem)
}
}
}
@Composable
override fun present(): TimelineState {
val localCoroutineScope = rememberCoroutineScope()
@@ -83,10 +70,8 @@ class TimelinePresenter @Inject constructor(
}
DisposableEffect(Unit) {
timeline.callback = TimelineCallback(localCoroutineScope, timelineItemsFactory)
timeline.initialize()
onDispose {
timeline.callback = null
timeline.dispose()
}
}

View File

@@ -22,7 +22,6 @@ import io.element.android.features.messages.timeline.diff.MatrixTimelineItemsDif
import io.element.android.features.messages.timeline.factories.event.TimelineItemEventFactory
import io.element.android.features.messages.timeline.factories.virtual.TimelineItemVirtualFactory
import io.element.android.features.messages.timeline.model.TimelineItem
import io.element.android.features.messages.timeline.util.invalidateLast
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.timeline.MatrixTimelineItem
import kotlinx.coroutines.flow.MutableStateFlow
@@ -61,18 +60,6 @@ class TimelineItemsFactory @Inject constructor(
}
}
suspend fun pushItem(
timelineItem: MatrixTimelineItem,
) = withContext(dispatchers.computation) {
lock.withLock {
// Makes sure to invalidate last as we need to recompute some data (like groupPosition)
timelineItemsCache.invalidateLast()
timelineItemsCache.add(null)
matrixTimelineItems = matrixTimelineItems + timelineItem
buildAndEmitTimelineItemStates(matrixTimelineItems)
}
}
private suspend fun buildAndEmitTimelineItemStates(timelineItems: List<MatrixTimelineItem>) {
val newTimelineItemStates = ArrayList<TimelineItem>()
for (index in timelineItemsCache.indices.reversed()) {

View File

@@ -117,6 +117,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" }
molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" }
timber = "com.jakewharton.timber:timber:5.0.1"
matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.2"
# Di
inject = "javax.inject:javax.inject:1"

View File

@@ -31,7 +31,8 @@ anvil {
}
dependencies {
api(projects.libraries.rustsdk)
//api(projects.libraries.rustsdk)
api(libs.matrix.sdk)
implementation(projects.libraries.di)
implementation(libs.dagger)
implementation(projects.libraries.core)

View File

@@ -38,7 +38,7 @@ import org.matrix.rustcomponents.sdk.RequiredState
import org.matrix.rustcomponents.sdk.SlidingSyncMode
import org.matrix.rustcomponents.sdk.SlidingSyncRequestListFilters
import org.matrix.rustcomponents.sdk.SlidingSyncViewBuilder
import org.matrix.rustcomponents.sdk.StoppableSpawn
import org.matrix.rustcomponents.sdk.TaskHandle
import timber.log.Timber
import java.io.File
import java.util.concurrent.atomic.AtomicBoolean
@@ -114,7 +114,7 @@ class RustMatrixClient constructor(
dispatchers,
::onRestartSync
)
private var slidingSyncObserverToken: StoppableSpawn? = null
private var slidingSyncObserverToken: TaskHandle? = null
private val mediaResolver = RustMediaResolver(this)
private val isSyncing = AtomicBoolean(false)

View File

@@ -37,7 +37,6 @@ import org.matrix.rustcomponents.sdk.SlidingSyncViewRoomsListDiff
import org.matrix.rustcomponents.sdk.UpdateSummary
import timber.log.Timber
import java.io.Closeable
import java.util.Collections
import java.util.UUID
interface RoomSummaryDataSource {
@@ -128,30 +127,40 @@ internal class RustRoomSummaryDataSource(
}
Timber.v("ApplyDiff: $diff for list with size: $size")
when (diff) {
is SlidingSyncViewRoomsListDiff.Push -> {
is SlidingSyncViewRoomsListDiff.Append -> {
val roomSummaries = diff.values.map {
buildSummaryForRoomListEntry(it)
}
addAll(roomSummaries)
}
is SlidingSyncViewRoomsListDiff.PushBack -> {
val roomSummary = buildSummaryForRoomListEntry(diff.value)
add(roomSummary)
}
is SlidingSyncViewRoomsListDiff.UpdateAt -> {
is SlidingSyncViewRoomsListDiff.PushFront -> {
val roomSummary = buildSummaryForRoomListEntry(diff.value)
add(0, roomSummary)
}
is SlidingSyncViewRoomsListDiff.Set -> {
fillUntil(diff.index.toInt())
val roomSummary = buildSummaryForRoomListEntry(diff.value)
set(diff.index.toInt(), roomSummary)
}
is SlidingSyncViewRoomsListDiff.InsertAt -> {
is SlidingSyncViewRoomsListDiff.Insert -> {
val roomSummary = buildSummaryForRoomListEntry(diff.value)
add(diff.index.toInt(), roomSummary)
}
is SlidingSyncViewRoomsListDiff.Move -> {
Collections.swap(this, diff.oldIndex.toInt(), diff.newIndex.toInt())
}
is SlidingSyncViewRoomsListDiff.RemoveAt -> {
is SlidingSyncViewRoomsListDiff.Remove -> {
removeAt(diff.index.toInt())
}
is SlidingSyncViewRoomsListDiff.Replace -> {
is SlidingSyncViewRoomsListDiff.Reset -> {
clear()
addAll(diff.values.map { buildSummaryForRoomListEntry(it) })
}
SlidingSyncViewRoomsListDiff.Pop -> {
SlidingSyncViewRoomsListDiff.PopBack -> {
removeFirstOrNull()
}
SlidingSyncViewRoomsListDiff.PopFront -> {
removeLastOrNull()
}
SlidingSyncViewRoomsListDiff.Clear -> {
@@ -185,13 +194,4 @@ internal class RustRoomSummaryDataSource(
block(mutableRoomSummaries)
roomSummaries.value = mutableRoomSummaries
}
fun SlidingSyncViewRoomsListDiff.isInvalidation(): Boolean {
return when (this) {
is SlidingSyncViewRoomsListDiff.InsertAt -> this.value is RoomListEntry.Invalidated
is SlidingSyncViewRoomsListDiff.UpdateAt -> this.value is RoomListEntry.Invalidated
is SlidingSyncViewRoomsListDiff.Push -> this.value is RoomListEntry.Invalidated
else -> false
}
}
}

View File

@@ -21,16 +21,9 @@ import kotlinx.coroutines.flow.Flow
import org.matrix.rustcomponents.sdk.TimelineListener
interface MatrixTimeline {
var callback: Callback?
interface Callback {
fun onUpdatedTimelineItem(timelineItem: MatrixTimelineItem) = Unit
fun onPushedTimelineItem(timelineItem: MatrixTimelineItem) = Unit
}
fun timelineItems(): Flow<List<MatrixTimelineItem>>
suspend fun paginateBackwards(requestSize: Int, untilNumberOfItems: Int): Result<Unit>
fun addListener(timelineListener: TimelineListener)
fun initialize()
fun dispose()

View File

@@ -19,7 +19,7 @@ package io.element.android.libraries.matrix.timeline
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.core.EventId
import io.element.android.libraries.matrix.room.RustMatrixRoom
import io.element.android.libraries.matrix.util.StoppableSpawnBag
import io.element.android.libraries.matrix.util.TaskHandleBag
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
@@ -32,9 +32,9 @@ import org.matrix.rustcomponents.sdk.Room
import org.matrix.rustcomponents.sdk.SlidingSyncRoom
import org.matrix.rustcomponents.sdk.TimelineChange
import org.matrix.rustcomponents.sdk.TimelineDiff
import org.matrix.rustcomponents.sdk.TimelineItem
import org.matrix.rustcomponents.sdk.TimelineListener
import timber.log.Timber
import java.util.Collections
class RustMatrixTimeline(
private val matrixRoom: RustMatrixRoom,
@@ -54,12 +54,10 @@ class RustMatrixTimeline(
}
}
override var callback: MatrixTimeline.Callback? = null
private val timelineItems: MutableStateFlow<List<MatrixTimelineItem>> =
MutableStateFlow(emptyList())
private val listenerTokens = StoppableSpawnBag()
private val listenerTokens = TaskHandleBag()
@OptIn(FlowPreview::class)
override fun timelineItems(): Flow<List<MatrixTimelineItem>> {
@@ -68,37 +66,42 @@ class RustMatrixTimeline(
private fun MutableList<MatrixTimelineItem>.applyDiff(diff: TimelineDiff) {
when (diff.change()) {
TimelineChange.PUSH -> {
val item = diff.push()?.asMatrixTimelineItem() ?: return
callback?.onPushedTimelineItem(item)
TimelineChange.APPEND -> {
val items = diff.append()?.map { it.asMatrixTimelineItem() } ?: return
addAll(items)
}
TimelineChange.PUSH_BACK -> {
val item = diff.pushBack()?.asMatrixTimelineItem() ?: return
add(item)
}
TimelineChange.UPDATE_AT -> {
val updateAtData = diff.updateAt() ?: return
TimelineChange.PUSH_FRONT -> {
val item = diff.pushFront()?.asMatrixTimelineItem() ?: return
add(0, item)
}
TimelineChange.SET -> {
val updateAtData = diff.set() ?: return
val item = updateAtData.item.asMatrixTimelineItem()
callback?.onUpdatedTimelineItem(item)
set(updateAtData.index.toInt(), item)
}
TimelineChange.INSERT_AT -> {
val insertAtData = diff.insertAt() ?: return
TimelineChange.INSERT -> {
val insertAtData = diff.insert() ?: 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
TimelineChange.REMOVE -> {
val removeAtData = diff.remove() ?: return
removeAt(removeAtData.toInt())
}
TimelineChange.REPLACE -> {
TimelineChange.RESET -> {
clear()
val items = diff.replace()?.map { it.asMatrixTimelineItem() } ?: return
val items = diff.reset()?.map { it.asMatrixTimelineItem() } ?: return
addAll(items)
}
TimelineChange.POP -> {
removeLast()
TimelineChange.POP_FRONT -> {
removeFirstOrNull()
}
TimelineChange.POP_BACK -> {
removeLastOrNull()
}
TimelineChange.CLEAR -> {
clear()
@@ -128,8 +131,12 @@ class RustMatrixTimeline(
timelineItems.value = mutableTimelineItems
}
override fun addListener(timelineListener: TimelineListener) {
listenerTokens += slidingSyncRoom.subscribeAndAddTimelineListener(timelineListener, null)
private suspend fun addListener(timelineListener: TimelineListener): Result<List<TimelineItem>> = withContext(coroutineDispatchers.computation) {
runCatching {
val result = slidingSyncRoom.subscribeAndAddTimelineListener(timelineListener, null)
listenerTokens += result.taskHandle
result.items
}
}
override fun initialize() {
@@ -142,7 +149,17 @@ class RustMatrixTimeline(
Timber.v("Success fetching members for room ${slidingSyncRoom.roomId()}")
}
}
addListener(innerTimelineListener)
coroutineScope.launch {
val result = addListener(innerTimelineListener)
result
.onSuccess { timelineItems ->
val matrixTimelineItems = timelineItems.map { it.asMatrixTimelineItem() }
updateTimelineItems { addAll(matrixTimelineItems) }
}
.onFailure {
Timber.e("Failed adding timeline listener on room with identifier: ${slidingSyncRoom.roomId()})")
}
}
}
override fun dispose() {

View File

@@ -19,12 +19,13 @@ package io.element.android.libraries.matrix.util
import kotlinx.coroutines.channels.ProducerScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.callbackFlow
import org.matrix.rustcomponents.sdk.StoppableSpawn
import org.matrix.rustcomponents.sdk.TaskHandle
internal fun <T> mxCallbackFlow(block: suspend ProducerScope<T>.() -> StoppableSpawn) =
internal fun <T> mxCallbackFlow(block: suspend ProducerScope<T>.() -> TaskHandle) =
callbackFlow {
val token: StoppableSpawn = block(this)
val token: TaskHandle = block(this)
awaitClose {
token.cancel()
token.destroy()
}
}

View File

@@ -16,14 +16,14 @@
package io.element.android.libraries.matrix.util
import org.matrix.rustcomponents.sdk.StoppableSpawn
import org.matrix.rustcomponents.sdk.TaskHandle
import java.util.concurrent.CopyOnWriteArraySet
class StoppableSpawnBag(private val tokens: MutableSet<StoppableSpawn> = CopyOnWriteArraySet()) : Set<StoppableSpawn> by tokens {
class TaskHandleBag(private val tokens: MutableSet<TaskHandle> = CopyOnWriteArraySet()) : Set<TaskHandle> by tokens {
operator fun plusAssign(stoppableSpawn: StoppableSpawn?) {
if (stoppableSpawn == null) return
tokens += stoppableSpawn
operator fun plusAssign(taskHandle: TaskHandle?) {
if (taskHandle == null) return
tokens += taskHandle
}
fun dispose() {

View File

@@ -51,6 +51,7 @@ dependencies {
implementation(projects.libraries.designsystem)
implementation(projects.libraries.architecture)
implementation(projects.libraries.core)
implementation(projects.libraries.dateformatter)
implementation(projects.features.roomlist)
implementation(projects.features.login)
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.2.2")

View File

@@ -18,17 +18,24 @@ package io.element.android.samples.minimal
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import io.element.android.features.roomlist.LastMessageFormatter
import io.element.android.features.roomlist.RoomListPresenter
import io.element.android.features.roomlist.RoomListView
import io.element.android.libraries.dateformatter.impl.DefaultLastMessageFormatter
import io.element.android.libraries.matrix.MatrixClient
import io.element.android.libraries.matrix.core.RoomId
import kotlinx.coroutines.launch
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import java.util.Locale
class RoomListScreen(private val matrixClient: MatrixClient) {
private val clock = Clock.System
private val locale = Locale.getDefault()
private val timeZone = TimeZone.currentSystemDefault()
private val presenter = RoomListPresenter(matrixClient, DefaultLastMessageFormatter(clock, locale, timeZone))
@Composable
fun Content(modifier: Modifier = Modifier) {
fun onRoomClicked(roomId: RoomId) {
@@ -43,9 +50,6 @@ class RoomListScreen(private val matrixClient: MatrixClient) {
}
}
val presenter = remember {
RoomListPresenter(matrixClient, LastMessageFormatter())
}
val state = presenter.present()
RoomListView(
state = state,