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:
renovate[bot]
2024-10-01 09:44:52 +02:00
committed by GitHub
parent 6b257dcef0
commit bb11bc5494
26 changed files with 216 additions and 175 deletions

View File

@@ -162,7 +162,7 @@ internal fun aTimelineItemEvent(
groupPosition = groupPosition,
localSendState = sendState,
inReplyTo = inReplyTo,
debugInfo = debugInfo,
debugInfoProvider = { debugInfo },
isThreaded = isThreaded,
origin = null,
messageShield = messageShield,

View File

@@ -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)
)
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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,

View File

@@ -41,7 +41,7 @@ class TimelineItemGrouperTest {
canBeRepliedTo = false,
inReplyTo = null,
isThreaded = false,
debugInfo = aTimelineItemDebugInfo(),
debugInfoProvider = { aTimelineItemDebugInfo() },
origin = null,
messageShield = null,
)

View File

@@ -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 },
),
)
)

View File

@@ -59,7 +59,7 @@ class PollRepository @Inject constructor(
suspend fun deletePoll(
pollStartId: EventId,
): Result<Boolean> =
): Result<Unit> =
timelineProvider
.getActiveTimeline()
.redactEvent(

View File

@@ -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()

View File

@@ -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" }

View File

@@ -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>

View File

@@ -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.

View File

@@ -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?
}

View File

@@ -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 { }

View File

@@ -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))
}
}
}

View File

@@ -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)
}

View File

@@ -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,
)
}

View File

@@ -41,5 +41,5 @@ internal fun TimelineDiff.eventOrigin(): EventItemOrigin? {
}
private fun TimelineItem.eventOrigin(): EventItemOrigin? {
return asEvent()?.origin()
return asEvent()?.origin
}

View File

@@ -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
)
}

View File

@@ -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) }
}

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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)
}

View File

@@ -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,

View File

@@ -66,9 +66,9 @@ fun anEventTimelineItem(
senderProfile = senderProfile,
timestamp = timestamp,
content = content,
debugInfo = debugInfo,
debugInfoProvider = { debugInfo },
origin = null,
messageShield = messageShield,
messageShieldProvider = { messageShield },
)
fun aProfileTimelineDetails(

View File

@@ -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"))