Upgrade Rust bindings to v25.04.11 (#4580)

* Upgrade Rust bindings to `v25.04.11`

* Rename `mapMessageKind` back to `mapMessageType`

* Fix tests and fixtures
This commit is contained in:
Jorge Martin Espinosa
2025-04-11 18:22:16 +02:00
committed by GitHub
parent 4dda027ed4
commit 73b4ac8c12
14 changed files with 90 additions and 64 deletions

View File

@@ -47,7 +47,7 @@ open class JoinRoomStateProvider : PreviewParameterProvider<JoinRoomState> {
),
aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin),
joinAction = AsyncAction.Failure(ClientException.Generic("Something went wrong"))
joinAction = AsyncAction.Failure(ClientException.Generic("Something went wrong", null))
),
aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited(null))

View File

@@ -250,7 +250,7 @@ class JoinRoomPresenterTest {
val presenter = createJoinRoomPresenter(
roomDescription = Optional.of(roomDescription),
joinRoomLambda = { _, _, _ ->
Result.failure(ClientException.MatrixApi(ErrorKind.Forbidden, "403", "Forbidden"))
Result.failure(ClientException.MatrixApi(ErrorKind.Forbidden, "403", "Forbidden", null))
},
)
presenter.test {
@@ -742,7 +742,7 @@ class JoinRoomPresenterTest {
fun `present - when room is not known RoomPreview is loaded with error Forbidden`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
Result.failure(ClientException.MatrixApi(ErrorKind.Forbidden, "403", "Forbidden"))
Result.failure(ClientException.MatrixApi(ErrorKind.Forbidden, "403", "Forbidden", null))
}
)
val presenter = createJoinRoomPresenter(

View File

@@ -18,7 +18,7 @@ open class RoomAliasResolverStateProvider : PreviewParameterProvider<RoomAliasRe
get() = sequenceOf(
aRoomAliasResolverState(),
aRoomAliasResolverState(
resolveState = AsyncData.Failure(ClientException.Generic("Something went wrong")),
resolveState = AsyncData.Failure(ClientException.Generic("Something went wrong", null)),
),
aRoomAliasResolverState(
resolveState = AsyncData.Failure(RoomAliasResolverFailures.UnknownAlias),

View File

@@ -174,7 +174,7 @@ jsoup = "org.jsoup:jsoup:1.19.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:25.4.8"
matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.4.11"
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

@@ -7,10 +7,10 @@
package io.element.android.libraries.matrix.api.exception
sealed class ClientException(message: String) : Exception(message) {
class Generic(message: String) : ClientException(message)
class MatrixApi(val kind: ErrorKind, val code: String, message: String) : ClientException(message)
class Other(message: String) : ClientException(message)
sealed class ClientException(message: String, val details: String?) : Exception(message) {
class Generic(message: String, details: String?) : ClientException(message, details)
class MatrixApi(val kind: ErrorKind, val code: String, message: String, details: String?) : ClientException(message, details)
class Other(message: String) : ClientException(message, null)
}
fun ClientException.isNetworkError(): Boolean {

View File

@@ -14,11 +14,12 @@ fun Throwable.mapClientException(): ClientException {
return when (this) {
is RustClientException -> {
when (this) {
is RustClientException.Generic -> ClientException.Generic(msg)
is RustClientException.Generic -> ClientException.Generic(msg, details)
is RustClientException.MatrixApi -> ClientException.MatrixApi(
kind = kind.map(),
code = code,
message = msg
message = msg,
details = details,
)
}
}

View File

@@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.impl.roomlist.roomOrNull
import io.element.android.libraries.matrix.impl.timeline.runWithTimelineListenerRegistered
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.withTimeout
import org.matrix.rustcomponents.sdk.MsgLikeKind
import org.matrix.rustcomponents.sdk.RoomListService
import org.matrix.rustcomponents.sdk.Timeline
import org.matrix.rustcomponents.sdk.TimelineItemContent
@@ -42,7 +43,10 @@ class RoomContentForwarder(
toRoomIds: List<RoomId>,
timeoutMs: Long = 5000L
) {
val content = (fromTimeline.getEventTimelineItemByEventId(eventId.value).content as? TimelineItemContent.Message)?.content
val messageLikeContent = (fromTimeline.getEventTimelineItemByEventId(eventId.value).content as? TimelineItemContent.MsgLike)?.content
?: throw ForwardEventException(toRoomIds)
val content = (messageLikeContent.kind as? MsgLikeKind.Message)?.content
?: throw ForwardEventException(toRoomIds)
val targetSlidingSyncRooms = toRoomIds.mapNotNull { roomId -> roomListService.roomOrNull(roomId.value) }

View File

@@ -48,8 +48,8 @@ class RustRoomPreview(
override suspend fun membershipDetails(): Result<RoomMembershipDetails?> = runCatching {
val details = inner.ownMembershipDetails() ?: return@runCatching null
RoomMembershipDetails(
currentUserMember = RoomMemberMapper.map(details.ownRoomMember),
senderMember = details.senderRoomMember?.let { RoomMemberMapper.map(it) },
currentUserMember = RoomMemberMapper.map(details.roomMember),
senderMember = details.senderInfo?.let { RoomMemberMapper.map(it) },
)
}

View File

@@ -23,24 +23,25 @@ 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.InReplyToDetails
import org.matrix.rustcomponents.sdk.MessageType
import org.matrix.rustcomponents.sdk.MsgLikeKind
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
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)
fun map(message: MsgLikeKind.Message, inReplyTo: InReplyToDetails?, isThreaded: Boolean): MessageContent = message.use {
val type = it.content.msgType.use(this::mapMessageType)
val inReplyToEvent: InReplyTo? = inReplyTo?.use(inReplyToMapper::map)
MessageContent(
body = it.body,
body = it.content.body,
inReplyTo = inReplyToEvent,
isEdited = it.isEdited,
isThreaded = it.threadRoot != null,
isEdited = it.content.isEdited,
isThreaded = isThreaded,
type = type
)
}

View File

@@ -28,6 +28,7 @@ import org.matrix.rustcomponents.sdk.EventOrTransactionId
import org.matrix.rustcomponents.sdk.QueueWedgeError
import org.matrix.rustcomponents.sdk.Reaction
import org.matrix.rustcomponents.sdk.ShieldState
import org.matrix.rustcomponents.sdk.TimelineItemContent
import uniffi.matrix_sdk_common.ShieldStateCode
import org.matrix.rustcomponents.sdk.EventSendState as RustEventSendState
import org.matrix.rustcomponents.sdk.EventTimelineItem as RustEventTimelineItem
@@ -48,7 +49,7 @@ class EventTimelineItemMapper(
isOwn = isOwn,
isRemote = isRemote,
localSendState = localSendState?.map(),
reactions = reactions.map(),
reactions = (content as? TimelineItemContent.MsgLike)?.content?.reactions.map(),
receipts = readReceipts.map(),
sender = UserId(sender),
senderProfile = senderProfile.map(),

View File

@@ -27,6 +27,7 @@ import io.element.android.libraries.matrix.impl.media.map
import io.element.android.libraries.matrix.impl.poll.map
import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toImmutableMap
import org.matrix.rustcomponents.sdk.MsgLikeKind
import org.matrix.rustcomponents.sdk.TimelineItemContent
import org.matrix.rustcomponents.sdk.use
import uniffi.matrix_sdk_ui.RoomPinnedEventsChange
@@ -54,8 +55,43 @@ class TimelineEventContentMapper(
error = it.error
)
}
is TimelineItemContent.Message -> {
eventMessageMapper.map(it.content)
is TimelineItemContent.MsgLike -> {
when (val kind = it.content.kind) {
is MsgLikeKind.Message -> {
val inReplyTo = it.content.inReplyTo
val isThreaded = it.content.threadRoot != null
eventMessageMapper.map(kind, inReplyTo, isThreaded)
}
is MsgLikeKind.Redacted -> {
RedactedContent
}
is MsgLikeKind.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 MsgLikeKind.UnableToDecrypt -> {
UnableToDecryptContent(
data = kind.msg.map()
)
}
is MsgLikeKind.Sticker -> {
StickerContent(
filename = kind.body,
body = null,
info = kind.info.map(),
source = kind.source.map(),
)
}
}
}
is TimelineItemContent.ProfileChange -> {
ProfileChangeContent(
@@ -65,9 +101,6 @@ class TimelineEventContentMapper(
prevAvatarUrl = it.prevAvatarUrl
)
}
TimelineItemContent.RedactedMessage -> {
RedactedContent
}
is TimelineItemContent.RoomMembership -> {
RoomMembershipContent(
userId = UserId(it.userId),
@@ -81,32 +114,6 @@ class TimelineEventContentMapper(
content = it.content.map()
)
}
is TimelineItemContent.Sticker -> {
StickerContent(
filename = it.body,
body = null,
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
}

View File

@@ -15,7 +15,6 @@ import org.matrix.rustcomponents.sdk.EventSendState
import org.matrix.rustcomponents.sdk.EventTimelineItem
import org.matrix.rustcomponents.sdk.EventTimelineItemDebugInfo
import org.matrix.rustcomponents.sdk.ProfileDetails
import org.matrix.rustcomponents.sdk.Reaction
import org.matrix.rustcomponents.sdk.Receipt
import org.matrix.rustcomponents.sdk.ShieldState
import org.matrix.rustcomponents.sdk.TimelineItemContent
@@ -30,7 +29,6 @@ fun aRustEventTimelineItem(
isEditable: Boolean = true,
content: TimelineItemContent = aRustTimelineItemMessageContent(),
timestamp: ULong = 0uL,
reactions: List<Reaction> = emptyList(),
debugInfo: EventTimelineItemDebugInfo = anEventTimelineItemDebugInfo(),
localSendState: EventSendState? = null,
readReceipts: Map<String, Receipt> = emptyMap(),
@@ -49,7 +47,6 @@ fun aRustEventTimelineItem(
canBeRepliedTo = canBeRepliedTo,
content = content,
localSendState = localSendState,
reactions = reactions,
readReceipts = readReceipts,
origin = origin,
localCreatedAt = localCreatedAt,

View File

@@ -9,16 +9,23 @@ package io.element.android.libraries.matrix.impl.fixtures.factories
import org.matrix.rustcomponents.sdk.MessageContent
import org.matrix.rustcomponents.sdk.MessageType
import org.matrix.rustcomponents.sdk.MsgLikeContent
import org.matrix.rustcomponents.sdk.MsgLikeKind
import org.matrix.rustcomponents.sdk.TextMessageContent
import org.matrix.rustcomponents.sdk.TimelineItemContent
fun aRustTimelineItemMessageContent(body: String = "Hello") = TimelineItemContent.Message(
content = MessageContent(
msgType = MessageType.Text(content = TextMessageContent(body = body, formatted = null)),
body = body,
inReplyTo = null,
fun aRustTimelineItemMessageContent(body: String = "Hello") = TimelineItemContent.MsgLike(
content = MsgLikeContent(
kind = MsgLikeKind.Message(
content = MessageContent(
msgType = MessageType.Text(content = TextMessageContent(body = body, formatted = null)),
body = body,
isEdited = false,
mentions = null,
)
),
reactions = emptyList(),
threadRoot = null,
isEdited = false,
mentions = null,
)
inReplyTo = null,
),
)

View File

@@ -7,9 +7,11 @@
package io.element.android.libraries.matrix.impl.fixtures.factories
import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustTimelineEvent
import io.element.android.libraries.matrix.test.A_ROOM_NAME
import io.element.android.libraries.matrix.test.A_USER_NAME
import org.matrix.rustcomponents.sdk.JoinRule
import org.matrix.rustcomponents.sdk.NotificationEvent
import org.matrix.rustcomponents.sdk.NotificationItem
import org.matrix.rustcomponents.sdk.NotificationRoomInfo
@@ -22,12 +24,14 @@ fun aRustNotificationItem(
roomInfo: NotificationRoomInfo = aRustNotificationRoomInfo(),
isNoisy: Boolean? = false,
hasMention: Boolean? = false,
threadId: ThreadId? = null,
) = NotificationItem(
event = event,
senderInfo = senderInfo,
roomInfo = roomInfo,
isNoisy = isNoisy,
hasMention = hasMention,
threadId = threadId?.value,
)
fun aRustNotificationSenderInfo(
@@ -47,6 +51,8 @@ fun aRustNotificationRoomInfo(
joinedMembersCount: ULong = 2u,
isEncrypted: Boolean? = true,
isDirect: Boolean = false,
joinRule: JoinRule? = null,
isPublic: Boolean = true,
) = NotificationRoomInfo(
displayName = displayName,
avatarUrl = avatarUrl,
@@ -54,6 +60,8 @@ fun aRustNotificationRoomInfo(
joinedMembersCount = joinedMembersCount,
isEncrypted = isEncrypted,
isDirect = isDirect,
joinRule = joinRule,
isPublic = isPublic,
)
fun aRustNotificationEventTimeline(