Add fetchMembers and use it when init timeline (import again rust-sdk with fix on poisoning)

This commit is contained in:
ganfra
2023-02-14 20:13:47 +01:00
parent 2176aa8e5a
commit 9526eac81c
13 changed files with 106 additions and 107 deletions

View File

@@ -83,11 +83,11 @@ import io.element.android.features.messages.timeline.model.virtual.TimelineItemL
import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.utils.PairCombinedPreviewParameter
import io.element.android.libraries.matrix.core.EventId
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
import timber.log.Timber
@Composable
fun TimelineView(
@@ -117,14 +117,6 @@ fun TimelineView(
onLongClick = onMessageLongClicked
)
}
/*
if (state.hasMoreToLoad) {
item {
TimelineLoadingMoreIndicator()
}
}
*/
}
fun onReachedLoadMore() {
@@ -165,12 +157,23 @@ fun TimelineItemRow(
is TimelineItem.Virtual -> TimelineItemVirtualRow(
virtual = timelineItem
)
is TimelineItem.Event -> TimelineItemEventRow(
event = timelineItem,
isHighlighted = isHighlighted,
onClick = { onClick(timelineItem) },
onLongClick = { onLongClick(timelineItem) }
)
is TimelineItem.Event -> {
fun onClick() {
onClick(timelineItem)
}
fun onLongClick() {
onLongClick(timelineItem)
}
TimelineItemEventRow(
event = timelineItem,
isHighlighted = isHighlighted,
onClick = ::onClick,
onLongClick = ::onLongClick
)
}
}
}

View File

@@ -33,7 +33,7 @@ class TimelineItemEventFactory @Inject constructor(
private val contentFactory: TimelineItemContentFactory,
) {
suspend fun create(
fun create(
currentTimelineItem: MatrixTimelineItem.Event,
index: Int,
timelineItems: List<MatrixTimelineItem>,

View File

@@ -29,7 +29,7 @@ class TimelineItemVirtualFactory @Inject constructor(
private val daySeparatorFactory: TimelineItemDaySeparatorFactory,
) {
suspend fun create(
fun create(
currentTimelineItem: MatrixTimelineItem.Virtual,
index: Int,
timelineItems: List<MatrixTimelineItem>,

View File

@@ -24,11 +24,19 @@ import io.element.android.libraries.matrix.core.EventId
@Immutable
sealed interface TimelineItem {
fun identifier(): String = when(this){
is Event -> id
is Virtual -> id
}
@Immutable
data class Virtual(
val id: String,
val model: TimelineItemVirtualModel
) : TimelineItem
@Immutable
data class Event(
val id: String,
val eventId: EventId? = null,

View File

@@ -43,7 +43,7 @@ import timber.log.Timber
import java.io.File
import java.util.concurrent.atomic.AtomicBoolean
internal class RustMatrixClient internal constructor(
class RustMatrixClient constructor(
private val client: Client,
private val sessionStore: SessionStore,
private val coroutineScope: CoroutineScope,
@@ -132,11 +132,11 @@ internal class RustMatrixClient internal constructor(
override fun getRoom(roomId: RoomId): MatrixRoom? {
val slidingSyncRoom = slidingSync.getRoom(roomId.value) ?: return null
val room = slidingSyncRoom.fullRoom() ?: return null
val fullRoom = slidingSyncRoom.fullRoom() ?: return null
return RustMatrixRoom(
slidingSyncUpdateFlow = slidingSyncObserverProxy.updateSummaryFlow,
slidingSyncRoom = slidingSyncRoom,
room = room,
innerRoom = fullRoom,
coroutineScope = coroutineScope,
coroutineDispatchers = dispatchers
)

View File

@@ -31,6 +31,6 @@ object MatrixModule {
@Provides
@SingleIn(AppScope::class)
fun providesRustAuthenticationService(baseDirectory: File): AuthenticationService {
return AuthenticationService(baseDirectory.absolutePath, null)
return AuthenticationService(baseDirectory.absolutePath, null, null)
}
}

View File

@@ -33,6 +33,8 @@ interface MatrixRoom {
fun timeline(): MatrixTimeline
suspend fun fetchMembers(): Result<Unit>
suspend fun userDisplayName(userId: String): Result<String?>
suspend fun userAvatarUrl(userId: String): Result<String?>
@@ -44,4 +46,5 @@ interface MatrixRoom {
suspend fun replyMessage(eventId: EventId, message: String): Result<Unit>
suspend fun redactEvent(eventId: EventId, reason: String? = null): Result<Unit>
}

View File

@@ -1,40 +0,0 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.matrix.room
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.launch
import org.matrix.rustcomponents.sdk.Room
import org.matrix.rustcomponents.sdk.TimelineDiff
import org.matrix.rustcomponents.sdk.TimelineListener
fun Room.timelineDiff(scope: CoroutineScope): Flow<TimelineDiff> = callbackFlow {
val listener = object : TimelineListener {
override fun onUpdate(update: TimelineDiff) {
scope.launch {
send(update)
}
}
}
addTimelineListener(listener)
awaitClose {
removeTimeline()
}
}

View File

@@ -32,11 +32,12 @@ import org.matrix.rustcomponents.sdk.SlidingSyncRoom
import org.matrix.rustcomponents.sdk.UpdateSummary
import org.matrix.rustcomponents.sdk.genTransactionId
import org.matrix.rustcomponents.sdk.messageEventContentFromMarkdown
import timber.log.Timber
class RustMatrixRoom(
private val slidingSyncUpdateFlow: Flow<UpdateSummary>,
private val slidingSyncRoom: SlidingSyncRoom,
private val room: Room,
private val innerRoom: Room,
private val coroutineScope: CoroutineScope,
private val coroutineDispatchers: CoroutineDispatchers,
) : MatrixRoom {
@@ -44,7 +45,7 @@ class RustMatrixRoom(
override fun syncUpdateFlow(): Flow<Long> {
return slidingSyncUpdateFlow
.filter {
it.rooms.contains(room.id())
it.rooms.contains(innerRoom.id())
}
.map {
System.currentTimeMillis()
@@ -55,14 +56,14 @@ class RustMatrixRoom(
override fun timeline(): MatrixTimeline {
return RustMatrixTimeline(
matrixRoom = this,
room = room,
innerRoom = innerRoom,
slidingSyncRoom = slidingSyncRoom,
coroutineScope = coroutineScope,
coroutineDispatchers = coroutineDispatchers
)
}
override val roomId = RoomId(room.id())
override val roomId = RoomId(innerRoom.id())
override val name: String?
get() {
@@ -71,35 +72,41 @@ class RustMatrixRoom(
override val bestName: String
get() {
return name?.takeIf { it.isNotEmpty() } ?: room.id()
return name?.takeIf { it.isNotEmpty() } ?: innerRoom.id()
}
override val displayName: String
get() {
return room.displayName()
return innerRoom.displayName()
}
override val topic: String?
get() {
return room.topic()
return innerRoom.topic()
}
override val avatarUrl: String?
get() {
return room.avatarUrl()
return innerRoom.avatarUrl()
}
override suspend fun fetchMembers(): Result<Unit> = withContext(coroutineDispatchers.io) {
runCatching {
innerRoom.fetchMembers()
}
}
override suspend fun userDisplayName(userId: String): Result<String?> =
withContext(coroutineDispatchers.io) {
runCatching {
room.memberDisplayName(userId)
innerRoom.memberDisplayName(userId)
}
}
override suspend fun userAvatarUrl(userId: String): Result<String?> =
withContext(coroutineDispatchers.io) {
runCatching {
room.memberAvatarUrl(userId)
innerRoom.memberAvatarUrl(userId)
}
}
@@ -107,7 +114,7 @@ class RustMatrixRoom(
val transactionId = genTransactionId()
val content = messageEventContentFromMarkdown(message)
runCatching {
room.send(content, transactionId)
innerRoom.send(content, transactionId)
}
}
@@ -115,7 +122,7 @@ class RustMatrixRoom(
val transactionId = genTransactionId()
// val content = messageEventContentFromMarkdown(message)
runCatching {
room.edit(/* TODO use content */ message, originalEventId.value, transactionId)
innerRoom.edit(/* TODO use content */ message, originalEventId.value, transactionId)
}
}
@@ -123,14 +130,14 @@ class RustMatrixRoom(
val transactionId = genTransactionId()
// val content = messageEventContentFromMarkdown(message)
runCatching {
room.sendReply(/* TODO use content */ message, eventId.value, transactionId)
innerRoom.sendReply(/* TODO use content */ message, eventId.value, transactionId)
}
}
override suspend fun redactEvent(eventId: EventId, reason: String?) = withContext(coroutineDispatchers.io) {
val transactionId = genTransactionId()
runCatching {
room.redact(eventId.value, reason, transactionId)
innerRoom.redact(eventId.value, reason, transactionId)
}
}
}

View File

@@ -54,7 +54,8 @@ class PreferencesSessionStore @Inject constructor(
val homeserverUrl: String,
val isSoftLogout: Boolean,
val refreshToken: String?,
val userId: String
val userId: String,
val slidingSyncProxy: String?
)
private val store = context.dataStore
@@ -73,7 +74,8 @@ class PreferencesSessionStore @Inject constructor(
homeserverUrl = session.homeserverUrl,
isSoftLogout = session.isSoftLogout,
refreshToken = session.refreshToken,
userId = session.userId
userId = session.userId,
slidingSyncProxy = session.slidingSyncProxy
)
val encodedSession = Json.encodeToString(sessionData)
prefs[sessionKey] = encodedSession
@@ -90,7 +92,8 @@ class PreferencesSessionStore @Inject constructor(
homeserverUrl = sessionData.homeserverUrl,
isSoftLogout = sessionData.isSoftLogout,
refreshToken = sessionData.refreshToken,
userId = sessionData.userId
userId = sessionData.userId,
slidingSyncProxy = sessionData.slidingSyncProxy
)
}
}

View File

@@ -34,15 +34,25 @@ import org.matrix.rustcomponents.sdk.TimelineChange
import org.matrix.rustcomponents.sdk.TimelineDiff
import org.matrix.rustcomponents.sdk.TimelineListener
import timber.log.Timber
import java.util.*
import java.util.Collections
class RustMatrixTimeline(
private val matrixRoom: RustMatrixRoom,
private val room: Room,
private val innerRoom: Room,
private val slidingSyncRoom: SlidingSyncRoom,
private val coroutineScope: CoroutineScope,
private val coroutineDispatchers: CoroutineDispatchers,
) : TimelineListener, MatrixTimeline {
) : MatrixTimeline {
private val innerTimelineListener = object : TimelineListener {
override fun onUpdate(update: TimelineDiff) {
coroutineScope.launch {
updateTimelineItems {
applyDiff(update)
}
}
}
}
override var callback: MatrixTimeline.Callback? = null
@@ -59,46 +69,38 @@ class RustMatrixTimeline(
private fun MutableList<MatrixTimelineItem>.applyDiff(diff: TimelineDiff) {
when (diff.change()) {
TimelineChange.PUSH -> {
Timber.v("Apply push on list with size: $size")
val item = diff.push()?.asMatrixTimelineItem() ?: return
callback?.onPushedTimelineItem(item)
add(item)
}
TimelineChange.UPDATE_AT -> {
val updateAtData = diff.updateAt() ?: return
Timber.v("Apply $updateAtData on list with size: $size")
val item = updateAtData.item.asMatrixTimelineItem()
callback?.onUpdatedTimelineItem(item)
set(updateAtData.index.toInt(), item)
}
TimelineChange.INSERT_AT -> {
val insertAtData = diff.insertAt() ?: return
Timber.v("Apply $insertAtData on list with size: $size")
val item = insertAtData.item.asMatrixTimelineItem()
add(insertAtData.index.toInt(), item)
}
TimelineChange.MOVE -> {
val moveData = diff.move() ?: return
Timber.v("Apply $moveData on list with size: $size")
Collections.swap(this, moveData.oldIndex.toInt(), moveData.newIndex.toInt())
}
TimelineChange.REMOVE_AT -> {
val removeAtData = diff.removeAt() ?: return
Timber.v("Apply $removeAtData on list with size: $size")
removeAt(removeAtData.toInt())
}
TimelineChange.REPLACE -> {
Timber.v("Apply REPLACE on list with size: $size")
clear()
val items = diff.replace()?.map { it.asMatrixTimelineItem() } ?: return
addAll(items)
}
TimelineChange.POP -> {
Timber.v("Apply POP on list with size: $size")
removeLast()
}
TimelineChange.CLEAR -> {
Timber.v("Apply CLEAR on list with size: $size")
clear()
}
}
@@ -106,11 +108,16 @@ class RustMatrixTimeline(
override suspend fun paginateBackwards(requestSize: Int, untilNumberOfItems: Int): Result<Unit> = withContext(coroutineDispatchers.io) {
runCatching {
Timber.v("Start back paginating for room ${slidingSyncRoom.roomId()} ")
val paginationOptions = PaginationOptions.UntilNumItems(
eventLimit = requestSize.toUShort(),
items = untilNumberOfItems.toUShort()
)
room.paginateBackwards(paginationOptions)
innerRoom.paginateBackwards(paginationOptions)
}.onFailure {
Timber.e(it, "Fail to paginate for room ${slidingSyncRoom.roomId()}")
}.onSuccess {
Timber.v("Success back paginating for room ${slidingSyncRoom.roomId()}")
}
}
@@ -122,14 +129,24 @@ class RustMatrixTimeline(
}
override fun addListener(timelineListener: TimelineListener) {
listenerTokens += slidingSyncRoom.subscribeAndAddTimelineListener(timelineListener, settings = null)
listenerTokens += slidingSyncRoom.subscribeAndAddTimelineListener(timelineListener, null)
}
override fun initialize() {
addListener(this)
Timber.v("Init timeline for room ${slidingSyncRoom.roomId()}")
coroutineScope.launch {
matrixRoom.fetchMembers()
.onFailure {
Timber.e(it, "Fail to fetch members for room ${slidingSyncRoom.roomId()}")
}.onSuccess {
Timber.v("Success fetching members for room ${slidingSyncRoom.roomId()}")
}
}
addListener(innerTimelineListener)
}
override fun dispose() {
Timber.v("Dispose timeline for room ${slidingSyncRoom.roomId()}")
listenerTokens.dispose()
}
@@ -147,12 +164,4 @@ class RustMatrixTimeline(
override suspend fun replyMessage(inReplyToEventId: EventId, message: String): Result<Unit> {
return matrixRoom.replyMessage(inReplyToEventId, message)
}
override fun onUpdate(update: TimelineDiff) {
coroutineScope.launch {
updateTimelineItems {
applyDiff(update)
}
}
}
}

View File

@@ -23,15 +23,16 @@ data class TracingConfiguration(
) {
// Order should matters
private val targets = mutableMapOf(
Target.MatrixSdk.HttpClient to LogLevel.Trace,
Target.MatrixSdk.SlidingSync to LogLevel.Trace,
Target.MatrixSdk.BaseSlidingSync to LogLevel.Trace,
Target.MatrixSdk.Root to LogLevel.Warn,
Target.MatrixSdk.Sled to LogLevel.Warn,
private val targets: MutableMap<Target, LogLevel> = mutableMapOf(
Target.Common to LogLevel.Warn,
Target.Hyper to LogLevel.Warn,
Target.Sled to LogLevel.Warn,
Target.Common to LogLevel.Warn,
Target.MatrixSdk.Root to LogLevel.Warn,
Target.MatrixSdk.Sled to LogLevel.Warn,
Target.MatrixSdk.Crypto to LogLevel.Debug,
Target.MatrixSdk.HttpClient to LogLevel.Debug,
Target.MatrixSdk.SlidingSync to LogLevel.Trace,
Target.MatrixSdk.BaseSlidingSync to LogLevel.Trace,
)
val filter: String
@@ -56,6 +57,7 @@ sealed class Target(open val filter: String) {
sealed class MatrixSdk(override val filter: String) : Target(filter) {
object Root : MatrixSdk("matrix_sdk")
object Sled : MatrixSdk("matrix_sdk_sled")
object Crypto: MatrixSdk("matrix_sdk_crypto")
object FFI : MatrixSdk("matrix_sdk_ffi")
object HttpClient : MatrixSdk("matrix_sdk::http_client")
object UniffiAPI : MatrixSdk("matrix_sdk_ffi::uniffi_api")

View File

@@ -41,6 +41,10 @@ class FakeMatrixRoom(
return FakeMatrixTimeline()
}
override suspend fun fetchMembers(): Result<Unit> {
return Result.success(Unit)
}
override suspend fun userDisplayName(userId: String): Result<String?> {
return Result.success("")
}