Update dependency org.matrix.rustcomponents:sdk-android to v0.2.50 (#3565)
* Adapt to changes in the SDK * Update dependency org.matrix.rustcomponents:sdk-android to v0.2.50 * Use lambda instead of overriding the `EventDebugInfoProvider` interface * Fix test proposal. We may find a better way to compare data class instance if we need to do more comparison in the future... --------- Co-authored-by: Jorge Martín <jorgem@element.io> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Benoit Marty <benoit@matrix.org>
This commit is contained in:
@@ -162,7 +162,7 @@ internal fun aTimelineItemEvent(
|
||||
groupPosition = groupPosition,
|
||||
localSendState = sendState,
|
||||
inReplyTo = inReplyTo,
|
||||
debugInfo = debugInfo,
|
||||
debugInfoProvider = { debugInfo },
|
||||
isThreaded = isThreaded,
|
||||
origin = null,
|
||||
messageShield = messageShield,
|
||||
|
||||
@@ -85,9 +85,9 @@ class TimelineItemEventFactory @AssistedInject constructor(
|
||||
localSendState = currentTimelineItem.event.localSendState,
|
||||
inReplyTo = currentTimelineItem.event.inReplyTo()?.map(permalinkParser = permalinkParser),
|
||||
isThreaded = currentTimelineItem.event.isThreaded(),
|
||||
debugInfo = currentTimelineItem.event.debugInfo,
|
||||
debugInfoProvider = currentTimelineItem.event.debugInfoProvider,
|
||||
origin = currentTimelineItem.event.origin,
|
||||
messageShield = currentTimelineItem.event.messageShield,
|
||||
messageShield = currentTimelineItem.event.messageShieldProvider.getShield(strict = false)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.TransactionId
|
||||
import io.element.android.libraries.matrix.api.core.UniqueId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventDebugInfoProvider
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails
|
||||
@@ -74,7 +74,7 @@ sealed interface TimelineItem {
|
||||
val localSendState: LocalEventSendState?,
|
||||
val inReplyTo: InReplyToDetails?,
|
||||
val isThreaded: Boolean,
|
||||
val debugInfo: TimelineItemDebugInfo,
|
||||
val debugInfoProvider: EventDebugInfoProvider,
|
||||
val origin: TimelineItemEventOrigin?,
|
||||
val messageShield: MessageShield?,
|
||||
) : TimelineItem {
|
||||
@@ -89,6 +89,8 @@ sealed interface TimelineItem {
|
||||
val isSticker: Boolean = content is TimelineItemStickerContent
|
||||
|
||||
val isRemote = eventId != null
|
||||
|
||||
val debugInfo = debugInfoProvider.get()
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
||||
@@ -493,7 +493,7 @@ class MessagesPresenterTest {
|
||||
canUserPinUnpinResult = { Result.success(true) },
|
||||
)
|
||||
|
||||
val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(true) }
|
||||
val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(Unit) }
|
||||
liveTimeline.redactEventLambda = redactEventLambda
|
||||
|
||||
val presenter = createMessagesPresenter(matrixRoom = matrixRoom, coroutineDispatchers = coroutineDispatchers)
|
||||
|
||||
@@ -58,7 +58,7 @@ internal fun aMessageEvent(
|
||||
readReceiptState = TimelineItemReadReceipts(emptyList<ReadReceiptData>().toImmutableList()),
|
||||
localSendState = sendState,
|
||||
inReplyTo = inReplyTo,
|
||||
debugInfo = debugInfo,
|
||||
debugInfoProvider = { debugInfo },
|
||||
isThreaded = isThreaded,
|
||||
origin = null,
|
||||
messageShield = messageShield,
|
||||
|
||||
@@ -41,7 +41,7 @@ class TimelineItemGrouperTest {
|
||||
canBeRepliedTo = false,
|
||||
inReplyTo = null,
|
||||
isThreaded = false,
|
||||
debugInfo = aTimelineItemDebugInfo(),
|
||||
debugInfoProvider = { aTimelineItemDebugInfo() },
|
||||
origin = null,
|
||||
messageShield = null,
|
||||
)
|
||||
|
||||
@@ -88,13 +88,15 @@ fun aRedactedMatrixTimeline(eventId: EventId) = listOf<MatrixTimelineItem>(
|
||||
senderProfile = ProfileTimelineDetails.Unavailable,
|
||||
timestamp = 9442,
|
||||
content = RedactedContent,
|
||||
debugInfo = TimelineItemDebugInfo(
|
||||
model = "enim",
|
||||
originalJson = null,
|
||||
latestEditedJson = null
|
||||
),
|
||||
debugInfoProvider = {
|
||||
TimelineItemDebugInfo(
|
||||
model = "enim",
|
||||
originalJson = null,
|
||||
latestEditedJson = null
|
||||
)
|
||||
},
|
||||
origin = null,
|
||||
messageShield = null,
|
||||
messageShieldProvider = { null },
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -59,7 +59,7 @@ class PollRepository @Inject constructor(
|
||||
|
||||
suspend fun deletePoll(
|
||||
pollStartId: EventId,
|
||||
): Result<Boolean> =
|
||||
): Result<Unit> =
|
||||
timelineProvider
|
||||
.getActiveTimeline()
|
||||
.redactEvent(
|
||||
|
||||
@@ -466,7 +466,7 @@ class CreatePollPresenterTest {
|
||||
@Test
|
||||
fun `delete confirms`() = runTest {
|
||||
val presenter = createCreatePollPresenter(mode = CreatePollMode.EditPoll(pollEventId))
|
||||
val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(true) }
|
||||
val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(Unit) }
|
||||
timeline.redactEventLambda = redactEventLambda
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
@@ -481,7 +481,7 @@ class CreatePollPresenterTest {
|
||||
@Test
|
||||
fun `delete can be cancelled`() = runTest {
|
||||
val presenter = createCreatePollPresenter(mode = CreatePollMode.EditPoll(pollEventId))
|
||||
val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(true) }
|
||||
val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(Unit) }
|
||||
timeline.redactEventLambda = redactEventLambda
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
@@ -499,7 +499,7 @@ class CreatePollPresenterTest {
|
||||
@Test
|
||||
fun `delete can be confirmed`() = runTest {
|
||||
val presenter = createCreatePollPresenter(mode = CreatePollMode.EditPoll(pollEventId))
|
||||
val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(true) }
|
||||
val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(Unit) }
|
||||
timeline.redactEventLambda = redactEventLambda
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
||||
@@ -163,7 +163,7 @@ jsoup = "org.jsoup:jsoup:1.18.1"
|
||||
appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" }
|
||||
molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0"
|
||||
timber = "com.jakewharton.timber:timber:5.0.1"
|
||||
matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.49"
|
||||
matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.50"
|
||||
matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" }
|
||||
matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" }
|
||||
sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }
|
||||
|
||||
@@ -154,7 +154,7 @@ interface MatrixRoom : Closeable {
|
||||
|
||||
suspend fun retrySendMessage(transactionId: TransactionId): Result<Unit>
|
||||
|
||||
suspend fun cancelSend(transactionId: TransactionId): Result<Boolean>
|
||||
suspend fun cancelSend(transactionId: TransactionId): Result<Unit>
|
||||
|
||||
suspend fun leave(): Result<Unit>
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ interface Timeline : AutoCloseable {
|
||||
progressCallback: ProgressCallback?
|
||||
): Result<MediaUploadHandler>
|
||||
|
||||
suspend fun redactEvent(eventId: EventId?, transactionId: TransactionId?, reason: String?): Result<Boolean>
|
||||
suspend fun redactEvent(eventId: EventId?, transactionId: TransactionId?, reason: String?): Result<Unit>
|
||||
|
||||
suspend fun sendAudio(file: File, audioInfo: AudioInfo, progressCallback: ProgressCallback?): Result<MediaUploadHandler>
|
||||
|
||||
@@ -99,7 +99,7 @@ interface Timeline : AutoCloseable {
|
||||
|
||||
suspend fun forwardEvent(eventId: EventId, roomIds: List<RoomId>): Result<Unit>
|
||||
|
||||
suspend fun cancelSend(transactionId: TransactionId): Result<Boolean>
|
||||
suspend fun cancelSend(transactionId: TransactionId): Result<Unit>
|
||||
|
||||
/**
|
||||
* Share a location message in the room.
|
||||
|
||||
@@ -28,9 +28,9 @@ data class EventTimelineItem(
|
||||
val senderProfile: ProfileTimelineDetails,
|
||||
val timestamp: Long,
|
||||
val content: EventContent,
|
||||
val debugInfo: TimelineItemDebugInfo,
|
||||
val debugInfoProvider: EventDebugInfoProvider,
|
||||
val origin: TimelineItemEventOrigin?,
|
||||
val messageShield: MessageShield?,
|
||||
val messageShieldProvider: EventShieldsProvider,
|
||||
) {
|
||||
fun inReplyTo(): InReplyTo? {
|
||||
return (content as? MessageContent)?.inReplyTo
|
||||
@@ -45,3 +45,11 @@ data class EventTimelineItem(
|
||||
return details is InReplyTo.NotLoaded
|
||||
}
|
||||
}
|
||||
|
||||
fun interface EventDebugInfoProvider {
|
||||
fun get(): TimelineItemDebugInfo
|
||||
}
|
||||
|
||||
fun interface EventShieldsProvider {
|
||||
fun getShield(strict: Boolean): MessageShield?
|
||||
}
|
||||
|
||||
@@ -114,7 +114,8 @@ internal class RustEncryptionService(
|
||||
override fun onUpdate(status: RustEnableRecoveryProgress) {
|
||||
enableRecoveryProgressStateFlow.value = enableRecoveryProgressMapper.map(status)
|
||||
}
|
||||
}
|
||||
},
|
||||
passphrase = null,
|
||||
)
|
||||
// enableRecovery returns the encryption key, but we read it from the state flow
|
||||
.let { }
|
||||
|
||||
@@ -18,6 +18,8 @@ import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import org.matrix.rustcomponents.sdk.RoomListService
|
||||
import org.matrix.rustcomponents.sdk.Timeline
|
||||
import org.matrix.rustcomponents.sdk.TimelineItemContent
|
||||
import org.matrix.rustcomponents.sdk.contentWithoutRelationFromMessage
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
/**
|
||||
@@ -40,11 +42,7 @@ class RoomContentForwarder(
|
||||
toRoomIds: List<RoomId>,
|
||||
timeoutMs: Long = 5000L
|
||||
) {
|
||||
val content = fromTimeline
|
||||
.getEventTimelineItemByEventId(eventId.value)
|
||||
.content()
|
||||
.asMessage()
|
||||
?.content()
|
||||
val content = (fromTimeline.getEventTimelineItemByEventId(eventId.value).content as? TimelineItemContent.Message)?.content
|
||||
?: throw ForwardEventException(toRoomIds)
|
||||
|
||||
val targetSlidingSyncRooms = toRoomIds.mapNotNull { roomId -> roomListService.roomOrNull(roomId.value) }
|
||||
@@ -58,7 +56,7 @@ class RoomContentForwarder(
|
||||
// Sending a message requires a registered timeline listener
|
||||
targetRoom.timeline().runWithTimelineListenerRegistered {
|
||||
withTimeout(timeoutMs.milliseconds) {
|
||||
targetRoom.timeline().send(content)
|
||||
targetRoom.timeline().send(contentWithoutRelationFromMessage(content))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,7 +462,7 @@ class RustMatrixRoom(
|
||||
innerRoom.tryResend(transactionId.value)
|
||||
}
|
||||
|
||||
override suspend fun cancelSend(transactionId: TransactionId): Result<Boolean> {
|
||||
override suspend fun cancelSend(transactionId: TransactionId): Result<Unit> {
|
||||
return liveTimeline.cancelSend(transactionId)
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.rustcomponents.sdk.EditedContent
|
||||
import org.matrix.rustcomponents.sdk.EventOrTransactionId
|
||||
import org.matrix.rustcomponents.sdk.EventTimelineItem
|
||||
import org.matrix.rustcomponents.sdk.FormattedBody
|
||||
import org.matrix.rustcomponents.sdk.MessageFormat
|
||||
@@ -274,11 +275,14 @@ class RustTimeline(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun redactEvent(eventId: EventId?, transactionId: TransactionId?, reason: String?): Result<Boolean> = withContext(dispatcher) {
|
||||
override suspend fun redactEvent(eventId: EventId?, transactionId: TransactionId?, reason: String?): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
getEventTimelineItem(eventId, transactionId).use { item ->
|
||||
inner.redactEvent(item = item, reason = reason)
|
||||
val eventOrTransactionId = if (eventId != null) {
|
||||
EventOrTransactionId.EventId(eventId.value)
|
||||
} else {
|
||||
EventOrTransactionId.TransactionId(transactionId!!.value)
|
||||
}
|
||||
inner.redactEvent(eventOrTransactionId = eventOrTransactionId, reason = reason)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,19 +295,22 @@ class RustTimeline(
|
||||
): Result<Unit> =
|
||||
withContext(dispatcher) {
|
||||
runCatching<Unit> {
|
||||
getEventTimelineItem(originalEventId, transactionId).use { item ->
|
||||
val editedContent = EditedContent.RoomMessage(
|
||||
content = MessageEventContent.from(
|
||||
body = body,
|
||||
htmlBody = htmlBody,
|
||||
intentionalMentions = intentionalMentions
|
||||
),
|
||||
)
|
||||
inner.edit(
|
||||
newContent = editedContent,
|
||||
item = item,
|
||||
)
|
||||
val eventOrTransactionId = if (originalEventId != null) {
|
||||
EventOrTransactionId.EventId(originalEventId.value)
|
||||
} else {
|
||||
EventOrTransactionId.TransactionId(transactionId!!.value)
|
||||
}
|
||||
val editedContent = EditedContent.RoomMessage(
|
||||
content = MessageEventContent.from(
|
||||
body = body,
|
||||
htmlBody = htmlBody,
|
||||
intentionalMentions = intentionalMentions
|
||||
),
|
||||
)
|
||||
inner.edit(
|
||||
newContent = editedContent,
|
||||
eventOrTransactionId = eventOrTransactionId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,6 +350,7 @@ class RustTimeline(
|
||||
}
|
||||
|
||||
@Throws
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private suspend fun getEventTimelineItem(eventId: EventId?, transactionId: TransactionId?): EventTimelineItem {
|
||||
return try {
|
||||
when {
|
||||
@@ -411,7 +419,8 @@ class RustTimeline(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun cancelSend(transactionId: TransactionId): Result<Boolean> = redactEvent(eventId = null, transactionId = transactionId, reason = null)
|
||||
override suspend fun cancelSend(transactionId: TransactionId): Result<Unit> =
|
||||
redactEvent(eventId = null, transactionId = transactionId, reason = null)
|
||||
|
||||
override suspend fun sendLocation(
|
||||
body: String,
|
||||
@@ -455,10 +464,6 @@ class RustTimeline(
|
||||
pollKind: PollKind,
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
val pollStartEvent =
|
||||
inner.getEventTimelineItemByEventId(
|
||||
eventId = pollStartId.value
|
||||
)
|
||||
val editedContent = EditedContent.PollStart(
|
||||
pollData = PollData(
|
||||
question = question,
|
||||
@@ -467,12 +472,10 @@ class RustTimeline(
|
||||
pollKind = pollKind.toInner(),
|
||||
),
|
||||
)
|
||||
pollStartEvent.use {
|
||||
inner.edit(
|
||||
newContent = editedContent,
|
||||
item = it,
|
||||
)
|
||||
}
|
||||
inner.edit(
|
||||
newContent = editedContent,
|
||||
eventOrTransactionId = EventOrTransactionId.EventId(pollStartId.value),
|
||||
)
|
||||
}.map { }
|
||||
}
|
||||
|
||||
@@ -482,7 +485,7 @@ class RustTimeline(
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
inner.sendPollResponse(
|
||||
pollStartId = pollStartId.value,
|
||||
pollStartEventId = pollStartId.value,
|
||||
answers = answers,
|
||||
)
|
||||
}
|
||||
@@ -494,7 +497,7 @@ class RustTimeline(
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
inner.endPoll(
|
||||
pollStartId = pollStartId.value,
|
||||
pollStartEventId = pollStartId.value,
|
||||
text = text,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -41,5 +41,5 @@ internal fun TimelineDiff.eventOrigin(): EventItemOrigin? {
|
||||
}
|
||||
|
||||
private fun TimelineItem.eventOrigin(): EventItemOrigin? {
|
||||
return asEvent()?.origin()
|
||||
return asEvent()?.origin
|
||||
}
|
||||
|
||||
@@ -23,10 +23,10 @@ import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageT
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType
|
||||
import io.element.android.libraries.matrix.impl.media.map
|
||||
import io.element.android.libraries.matrix.impl.timeline.reply.InReplyToMapper
|
||||
import org.matrix.rustcomponents.sdk.Message
|
||||
import org.matrix.rustcomponents.sdk.MessageType
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
import org.matrix.rustcomponents.sdk.FormattedBody as RustFormattedBody
|
||||
import org.matrix.rustcomponents.sdk.MessageContent as Message
|
||||
import org.matrix.rustcomponents.sdk.MessageFormat as RustMessageFormat
|
||||
import org.matrix.rustcomponents.sdk.MessageType as RustMessageType
|
||||
|
||||
@@ -34,13 +34,13 @@ class EventMessageMapper {
|
||||
private val inReplyToMapper by lazy { InReplyToMapper(TimelineEventContentMapper()) }
|
||||
|
||||
fun map(message: Message): MessageContent = message.use {
|
||||
val type = it.msgtype().use(this::mapMessageType)
|
||||
val inReplyToEvent: InReplyTo? = it.inReplyTo()?.use(inReplyToMapper::map)
|
||||
val type = it.msgType.use(this::mapMessageType)
|
||||
val inReplyToEvent: InReplyTo? = it.inReplyTo?.use(inReplyToMapper::map)
|
||||
MessageContent(
|
||||
body = it.body(),
|
||||
body = it.body,
|
||||
inReplyTo = inReplyToEvent,
|
||||
isEdited = it.isEdited(),
|
||||
isThreaded = it.isThreaded(),
|
||||
isEdited = it.isEdited,
|
||||
isThreaded = it.threadRoot != null,
|
||||
type = type
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@ import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.TransactionId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventDebugInfoProvider
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventReaction
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventShieldsProvider
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
|
||||
@@ -23,11 +25,14 @@ import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemE
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import org.matrix.rustcomponents.sdk.EventOrTransactionId
|
||||
import org.matrix.rustcomponents.sdk.EventSendState
|
||||
import org.matrix.rustcomponents.sdk.EventTimelineItemDebugInfoProvider
|
||||
import org.matrix.rustcomponents.sdk.Reaction
|
||||
import org.matrix.rustcomponents.sdk.ShieldState
|
||||
import uniffi.matrix_sdk_common.ShieldStateCode
|
||||
import org.matrix.rustcomponents.sdk.EventSendState as RustEventSendState
|
||||
import org.matrix.rustcomponents.sdk.EventShieldsProvider as RustEventShieldsProvider
|
||||
import org.matrix.rustcomponents.sdk.EventTimelineItem as RustEventTimelineItem
|
||||
import org.matrix.rustcomponents.sdk.EventTimelineItemDebugInfo as RustEventTimelineItemDebugInfo
|
||||
import org.matrix.rustcomponents.sdk.ProfileDetails as RustProfileDetails
|
||||
@@ -37,25 +42,25 @@ import uniffi.matrix_sdk_ui.EventItemOrigin as RustEventItemOrigin
|
||||
class EventTimelineItemMapper(
|
||||
private val contentMapper: TimelineEventContentMapper = TimelineEventContentMapper(),
|
||||
) {
|
||||
fun map(eventTimelineItem: RustEventTimelineItem): EventTimelineItem = eventTimelineItem.use {
|
||||
fun map(eventTimelineItem: RustEventTimelineItem): EventTimelineItem = eventTimelineItem.run {
|
||||
EventTimelineItem(
|
||||
eventId = it.eventId()?.let(::EventId),
|
||||
transactionId = it.transactionId()?.let(::TransactionId),
|
||||
isEditable = it.isEditable(),
|
||||
canBeRepliedTo = it.canBeRepliedTo(),
|
||||
isLocal = it.isLocal(),
|
||||
isOwn = it.isOwn(),
|
||||
isRemote = it.isRemote(),
|
||||
localSendState = it.localSendState()?.map(),
|
||||
reactions = it.reactions().map(),
|
||||
receipts = it.readReceipts().map(),
|
||||
sender = UserId(it.sender()),
|
||||
senderProfile = it.senderProfile().map(),
|
||||
timestamp = it.timestamp().toLong(),
|
||||
content = contentMapper.map(it.content()),
|
||||
debugInfo = it.debugInfo().map(),
|
||||
origin = it.origin()?.map(),
|
||||
messageShield = it.getShield(false)?.map(),
|
||||
eventId = eventOrTransactionId.eventId(),
|
||||
transactionId = eventOrTransactionId.transactionId(),
|
||||
isEditable = isEditable,
|
||||
canBeRepliedTo = canBeRepliedTo,
|
||||
isLocal = isLocal,
|
||||
isOwn = isOwn,
|
||||
isRemote = isRemote,
|
||||
localSendState = localSendState?.map(),
|
||||
reactions = reactions.map(),
|
||||
receipts = readReceipts.map(),
|
||||
sender = UserId(sender),
|
||||
senderProfile = senderProfile.map(),
|
||||
timestamp = timestamp.toLong(),
|
||||
content = contentMapper.map(content),
|
||||
debugInfoProvider = RustEventDebugInfoProvider(debugInfoProvider),
|
||||
origin = origin?.map(),
|
||||
messageShieldProvider = RustEventShieldsProvider(shieldsProvider)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -162,3 +167,23 @@ private fun ShieldState?.map(): MessageShield? {
|
||||
ShieldStateCode.PREVIOUSLY_VERIFIED -> MessageShield.PreviouslyVerified(isCritical)
|
||||
}
|
||||
}
|
||||
|
||||
class RustEventDebugInfoProvider(private val debugInfoProvider: EventTimelineItemDebugInfoProvider) : EventDebugInfoProvider {
|
||||
override fun get(): TimelineItemDebugInfo {
|
||||
return debugInfoProvider.get().map()
|
||||
}
|
||||
}
|
||||
|
||||
class RustEventShieldsProvider(private val shieldsProvider: RustEventShieldsProvider) : EventShieldsProvider {
|
||||
override fun getShield(strict: Boolean): MessageShield? {
|
||||
return shieldsProvider.getShields(strict)?.map()
|
||||
}
|
||||
}
|
||||
|
||||
private fun EventOrTransactionId.eventId(): EventId? {
|
||||
return (this as? EventOrTransactionId.EventId)?.let { EventId(it.eventId) }
|
||||
}
|
||||
|
||||
private fun EventOrTransactionId.transactionId(): TransactionId? {
|
||||
return (this as? EventOrTransactionId.TransactionId)?.let { TransactionId(it.transactionId) }
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import io.element.android.libraries.matrix.impl.poll.map
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableMap
|
||||
import org.matrix.rustcomponents.sdk.TimelineItemContent
|
||||
import org.matrix.rustcomponents.sdk.TimelineItemContentKind
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
import uniffi.matrix_sdk_ui.RoomPinnedEventsChange
|
||||
import org.matrix.rustcomponents.sdk.EncryptedMessage as RustEncryptedMessage
|
||||
@@ -42,87 +41,78 @@ class TimelineEventContentMapper(
|
||||
) {
|
||||
fun map(content: TimelineItemContent): EventContent {
|
||||
return content.use {
|
||||
content.kind().use { kind ->
|
||||
map(content, kind)
|
||||
when (it) {
|
||||
is TimelineItemContent.FailedToParseMessageLike -> {
|
||||
FailedToParseMessageLikeContent(
|
||||
eventType = it.eventType,
|
||||
error = it.error
|
||||
)
|
||||
}
|
||||
is TimelineItemContent.FailedToParseState -> {
|
||||
FailedToParseStateContent(
|
||||
eventType = it.eventType,
|
||||
stateKey = it.stateKey,
|
||||
error = it.error
|
||||
)
|
||||
}
|
||||
is TimelineItemContent.Message -> {
|
||||
eventMessageMapper.map(it.content)
|
||||
}
|
||||
is TimelineItemContent.ProfileChange -> {
|
||||
ProfileChangeContent(
|
||||
displayName = it.displayName,
|
||||
prevDisplayName = it.prevDisplayName,
|
||||
avatarUrl = it.avatarUrl,
|
||||
prevAvatarUrl = it.prevAvatarUrl
|
||||
)
|
||||
}
|
||||
TimelineItemContent.RedactedMessage -> {
|
||||
RedactedContent
|
||||
}
|
||||
is TimelineItemContent.RoomMembership -> {
|
||||
RoomMembershipContent(
|
||||
userId = UserId(it.userId),
|
||||
userDisplayName = it.userDisplayName,
|
||||
change = it.change?.map()
|
||||
)
|
||||
}
|
||||
is TimelineItemContent.State -> {
|
||||
StateContent(
|
||||
stateKey = it.stateKey,
|
||||
content = it.content.map()
|
||||
)
|
||||
}
|
||||
is TimelineItemContent.Sticker -> {
|
||||
StickerContent(
|
||||
body = it.body,
|
||||
info = it.info.map(),
|
||||
source = it.source.map(),
|
||||
)
|
||||
}
|
||||
is TimelineItemContent.Poll -> {
|
||||
PollContent(
|
||||
question = it.question,
|
||||
kind = it.kind.map(),
|
||||
maxSelections = it.maxSelections,
|
||||
answers = it.answers.map { answer -> answer.map() }.toImmutableList(),
|
||||
votes = it.votes.mapValues { vote ->
|
||||
vote.value.map { userId -> UserId(userId) }.toImmutableList()
|
||||
}.toImmutableMap(),
|
||||
endTime = it.endTime,
|
||||
isEdited = it.hasBeenEdited,
|
||||
)
|
||||
}
|
||||
is TimelineItemContent.UnableToDecrypt -> {
|
||||
UnableToDecryptContent(
|
||||
data = it.msg.map()
|
||||
)
|
||||
}
|
||||
is TimelineItemContent.CallInvite -> LegacyCallInviteContent
|
||||
is TimelineItemContent.CallNotify -> CallNotifyContent
|
||||
else -> UnknownContent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun map(content: TimelineItemContent, kind: TimelineItemContentKind) = when (kind) {
|
||||
is TimelineItemContentKind.FailedToParseMessageLike -> {
|
||||
FailedToParseMessageLikeContent(
|
||||
eventType = kind.eventType,
|
||||
error = kind.error
|
||||
)
|
||||
}
|
||||
is TimelineItemContentKind.FailedToParseState -> {
|
||||
FailedToParseStateContent(
|
||||
eventType = kind.eventType,
|
||||
stateKey = kind.stateKey,
|
||||
error = kind.error
|
||||
)
|
||||
}
|
||||
TimelineItemContentKind.Message -> {
|
||||
val message = content.asMessage()
|
||||
if (message == null) {
|
||||
UnknownContent
|
||||
} else {
|
||||
eventMessageMapper.map(message)
|
||||
}
|
||||
}
|
||||
is TimelineItemContentKind.ProfileChange -> {
|
||||
ProfileChangeContent(
|
||||
displayName = kind.displayName,
|
||||
prevDisplayName = kind.prevDisplayName,
|
||||
avatarUrl = kind.avatarUrl,
|
||||
prevAvatarUrl = kind.prevAvatarUrl
|
||||
)
|
||||
}
|
||||
TimelineItemContentKind.RedactedMessage -> {
|
||||
RedactedContent
|
||||
}
|
||||
is TimelineItemContentKind.RoomMembership -> {
|
||||
RoomMembershipContent(
|
||||
userId = UserId(kind.userId),
|
||||
userDisplayName = kind.userDisplayName,
|
||||
change = kind.change?.map()
|
||||
)
|
||||
}
|
||||
is TimelineItemContentKind.State -> {
|
||||
StateContent(
|
||||
stateKey = kind.stateKey,
|
||||
content = kind.content.map()
|
||||
)
|
||||
}
|
||||
is TimelineItemContentKind.Sticker -> {
|
||||
StickerContent(
|
||||
body = kind.body,
|
||||
info = kind.info.map(),
|
||||
source = kind.source.map(),
|
||||
)
|
||||
}
|
||||
is TimelineItemContentKind.Poll -> {
|
||||
PollContent(
|
||||
question = kind.question,
|
||||
kind = kind.kind.map(),
|
||||
maxSelections = kind.maxSelections,
|
||||
answers = kind.answers.map { answer -> answer.map() }.toImmutableList(),
|
||||
votes = kind.votes.mapValues { vote ->
|
||||
vote.value.map { userId -> UserId(userId) }.toImmutableList()
|
||||
}.toImmutableMap(),
|
||||
endTime = kind.endTime,
|
||||
isEdited = kind.hasBeenEdited,
|
||||
)
|
||||
}
|
||||
is TimelineItemContentKind.UnableToDecrypt -> {
|
||||
UnableToDecryptContent(
|
||||
data = kind.msg.map()
|
||||
)
|
||||
}
|
||||
is TimelineItemContentKind.CallInvite -> LegacyCallInviteContent
|
||||
is TimelineItemContentKind.CallNotify -> CallNotifyContent
|
||||
else -> UnknownContent
|
||||
}
|
||||
}
|
||||
|
||||
private fun RustMembershipChange.map(): MembershipChange {
|
||||
|
||||
@@ -19,8 +19,8 @@ class InReplyToMapper(
|
||||
private val timelineEventContentMapper: TimelineEventContentMapper,
|
||||
) {
|
||||
fun map(inReplyToDetails: InReplyToDetails): InReplyTo {
|
||||
val inReplyToId = EventId(inReplyToDetails.eventId)
|
||||
return when (val event = inReplyToDetails.event) {
|
||||
val inReplyToId = EventId(inReplyToDetails.eventId())
|
||||
return when (val event = inReplyToDetails.event()) {
|
||||
is RepliedToEventDetails.Ready -> {
|
||||
InReplyTo.Ready(
|
||||
eventId = inReplyToId,
|
||||
|
||||
@@ -103,7 +103,7 @@ class FakeMatrixRoom(
|
||||
private val updateUserRoleResult: () -> Result<Unit> = { lambdaError() },
|
||||
private val toggleReactionResult: (String, UniqueId) -> Result<Unit> = { _, _ -> lambdaError() },
|
||||
private val retrySendMessageResult: (TransactionId) -> Result<Unit> = { lambdaError() },
|
||||
private val cancelSendResult: (TransactionId) -> Result<Boolean> = { lambdaError() },
|
||||
private val cancelSendResult: (TransactionId) -> Result<Unit> = { lambdaError() },
|
||||
private val forwardEventResult: (EventId, List<RoomId>) -> Result<Unit> = { _, _ -> lambdaError() },
|
||||
private val reportContentResult: (EventId, String, UserId?) -> Result<Unit> = { _, _, _ -> lambdaError() },
|
||||
private val kickUserResult: (UserId, String?) -> Result<Unit> = { _, _ -> lambdaError() },
|
||||
@@ -233,7 +233,7 @@ class FakeMatrixRoom(
|
||||
return retrySendMessageResult(transactionId)
|
||||
}
|
||||
|
||||
override suspend fun cancelSend(transactionId: TransactionId): Result<Boolean> {
|
||||
override suspend fun cancelSend(transactionId: TransactionId): Result<Unit> {
|
||||
return cancelSendResult(transactionId)
|
||||
}
|
||||
|
||||
|
||||
@@ -63,15 +63,15 @@ class FakeTimeline(
|
||||
intentionalMentions: List<IntentionalMention>,
|
||||
): Result<Unit> = sendMessageLambda(body, htmlBody, intentionalMentions)
|
||||
|
||||
var redactEventLambda: (eventId: EventId?, transactionId: TransactionId?, reason: String?) -> Result<Boolean> = { _, _, _ ->
|
||||
Result.success(true)
|
||||
var redactEventLambda: (eventId: EventId?, transactionId: TransactionId?, reason: String?) -> Result<Unit> = { _, _, _ ->
|
||||
Result.success(Unit)
|
||||
}
|
||||
|
||||
override suspend fun redactEvent(
|
||||
eventId: EventId?,
|
||||
transactionId: TransactionId?,
|
||||
reason: String?
|
||||
): Result<Boolean> = redactEventLambda(eventId, transactionId, reason)
|
||||
): Result<Unit> = redactEventLambda(eventId, transactionId, reason)
|
||||
|
||||
var editMessageLambda: (
|
||||
originalEventId: EventId?,
|
||||
@@ -217,7 +217,7 @@ class FakeTimeline(
|
||||
var forwardEventLambda: (eventId: EventId, roomIds: List<RoomId>) -> Result<Unit> = { _, _ -> Result.success(Unit) }
|
||||
override suspend fun forwardEvent(eventId: EventId, roomIds: List<RoomId>): Result<Unit> = forwardEventLambda(eventId, roomIds)
|
||||
|
||||
override suspend fun cancelSend(transactionId: TransactionId): Result<Boolean> = redactEvent(null, transactionId, null)
|
||||
override suspend fun cancelSend(transactionId: TransactionId): Result<Unit> = redactEvent(null, transactionId, null)
|
||||
|
||||
var sendLocationLambda: (
|
||||
body: String,
|
||||
|
||||
@@ -66,9 +66,9 @@ fun anEventTimelineItem(
|
||||
senderProfile = senderProfile,
|
||||
timestamp = timestamp,
|
||||
content = content,
|
||||
debugInfo = debugInfo,
|
||||
debugInfoProvider = { debugInfo },
|
||||
origin = null,
|
||||
messageShield = messageShield,
|
||||
messageShieldProvider = { messageShield },
|
||||
)
|
||||
|
||||
fun aProfileTimelineDetails(
|
||||
|
||||
@@ -68,7 +68,19 @@ class RoomSelectPresenterTest {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(awaitItem().resultState as? SearchBarResultState.Results).isEqualTo(SearchBarResultState.Results(listOf(aRoomSummary())))
|
||||
val expectedRoomSummary = aRoomSummary()
|
||||
// Do not compare the lambda because they will be different. So copy the lambda from expectedRoomSummary to result
|
||||
val result = (awaitItem().resultState as SearchBarResultState.Results).results.map { roomSummary ->
|
||||
roomSummary.copy(
|
||||
lastMessage = roomSummary.lastMessage!!.copy(
|
||||
event = roomSummary.lastMessage!!.event.copy(
|
||||
debugInfoProvider = expectedRoomSummary.lastMessage!!.event.debugInfoProvider,
|
||||
messageShieldProvider = expectedRoomSummary.lastMessage!!.event.messageShieldProvider,
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
assertThat(result).isEqualTo(listOf(expectedRoomSummary))
|
||||
initialState.eventSink(RoomSelectEvents.ToggleSearchActive)
|
||||
skipItems(1)
|
||||
initialState.eventSink(RoomSelectEvents.UpdateQuery("string not contained"))
|
||||
|
||||
Reference in New Issue
Block a user