Skip to content

Commit

Permalink
Bump rust-sdk version to rust-sdk 0.2.57 (#3735)
Browse files Browse the repository at this point in the history
* Bump rust-sdk version to rust-sdk 0.2.57

* rust sdk update: Support persisted WedgeQueueError

* Trust & Decoration | Support new expected UTD causes

* Room Subscribtion settings not needed anymore (see matrix-org/matrix-rust-sdk#4159)

* File/Attachement upload: update to support `storeInCache`

* feat(knock): update API to use reason and serverNames

* Add another `Konsist` exception

* Update screenshots

---------

Co-authored-by: Jorge Martín <jorgem@element.io>
Co-authored-by: ElementBot <android@element.io>
Co-authored-by: Benoit Marty <benoit@matrix.org>
  • Loading branch information
4 people authored Oct 24, 2024
1 parent f44c8dd commit 9fb68fc
Show file tree
Hide file tree
Showing 23 changed files with 223 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/

package io.element.android.features.messages.impl.timeline.components

import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent
import io.element.android.libraries.matrix.api.timeline.item.event.UtdCause

@PreviewsDayNight
@Composable
internal fun TimelineItemEventRowUtdPreview() = ElementPreview {
Column {
ATimelineItemEventRow(
event = aTimelineItemEvent(
senderDisplayName = "Alice",
isMine = false,
content = TimelineItemEncryptedContent(
data = UnableToDecryptContent.Data.MegolmV1AesSha2(
sessionId = "sessionId",
utdCause = UtdCause.UnsignedDevice,
)
),
timelineItemReactions = aTimelineItemReactions(count = 0),
groupPosition = TimelineItemGroupPosition.First,
),
)
ATimelineItemEventRow(
event = aTimelineItemEvent(
senderDisplayName = "Bob",
isMine = false,
content = TimelineItemEncryptedContent(
data = UnableToDecryptContent.Data.MegolmV1AesSha2(
sessionId = "sessionId",
utdCause = UtdCause.VerificationViolation,
)
),
groupPosition = TimelineItemGroupPosition.First,
timelineItemReactions = aTimelineItemReactions(count = 0)
),
)

ATimelineItemEventRow(
event = aTimelineItemEvent(
senderDisplayName = "Bob",
isMine = false,
content = TimelineItemEncryptedContent(
data = UnableToDecryptContent.Data.MegolmV1AesSha2(
sessionId = "sessionId",
utdCause = UtdCause.SentBeforeWeJoined,
)
),
groupPosition = TimelineItemGroupPosition.Last,
timelineItemReactions = aTimelineItemReactions(count = 0)
),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,28 @@ fun TimelineItemEncryptedView(
onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit,
modifier: Modifier = Modifier
) {
val isMembershipUtd = (content.data as? UnableToDecryptContent.Data.MegolmV1AesSha2)?.utdCause == UtdCause.Membership
val (textId, iconId) = if (isMembershipUtd) {
CommonStrings.common_unable_to_decrypt_no_access to CompoundDrawables.ic_compound_block
} else {
CommonStrings.common_waiting_for_decryption_key to CompoundDrawables.ic_compound_time
val (textId, iconId) = when (content.data) {
is UnableToDecryptContent.Data.MegolmV1AesSha2 -> {
when (content.data.utdCause) {
UtdCause.SentBeforeWeJoined -> {
CommonStrings.common_unable_to_decrypt_no_access to CompoundDrawables.ic_compound_block
}
UtdCause.VerificationViolation -> {
CommonStrings.common_unable_to_decrypt_verification_violation to CompoundDrawables.ic_compound_block
}
UtdCause.UnsignedDevice,
UtdCause.UnknownDevice -> {
CommonStrings.common_unable_to_decrypt_insecure_device to CompoundDrawables.ic_compound_block
}
else -> {
CommonStrings.common_waiting_for_decryption_key to CompoundDrawables.ic_compound_time
}
}
}
else -> {
// Should not happen, we only supports megolm in rooms
CommonStrings.common_waiting_for_decryption_key to CompoundDrawables.ic_compound_time
}
}
TimelineItemInformativeView(
text = stringResource(id = textId),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,19 @@ open class TimelineItemEncryptedContentProvider : PreviewParameterProvider<Timel
aTimelineItemEncryptedContent(
data = UnableToDecryptContent.Data.MegolmV1AesSha2(
sessionId = "sessionId",
utdCause = UtdCause.Membership,
utdCause = UtdCause.SentBeforeWeJoined,
)
),
aTimelineItemEncryptedContent(
data = UnableToDecryptContent.Data.MegolmV1AesSha2(
sessionId = "sessionId",
utdCause = UtdCause.VerificationViolation,
)
),
aTimelineItemEncryptedContent(
data = UnableToDecryptContent.Data.MegolmV1AesSha2(
sessionId = "sessionId",
utdCause = UtdCause.UnsignedDevice,
)
),
aTimelineItemEncryptedContent(
Expand Down
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,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.56"
matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.57"
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" }
Expand All @@ -193,7 +193,7 @@ zxing_cpp = "io.github.zxing-cpp:android:2.2.0"
posthog = "com.posthog:posthog-android:3.8.2"
sentry = "io.sentry:sentry-android:7.15.0"
# main branch can be tested replacing the version with main-SNAPSHOT
matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.25.0"
matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.27.0"

# Emojibase
matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.3.3"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ sealed interface LocalEventSendState {
data object Sending : LocalEventSendState
sealed interface Failed : LocalEventSendState {
data class Unknown(val error: String) : Failed
data object CrossSigningNotSetup : Failed
data object SendingFromUnverifiedDevice : Failed

sealed interface VerifiedUser : Failed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@ package io.element.android.libraries.matrix.api.timeline.item.event

enum class UtdCause {
Unknown,
Membership,
SentBeforeWeJoined,
VerificationViolation,
UnsignedDevice,
UnknownDevice
}
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ class RustMatrixClient(
sessionDispatcher
) {
runCatching {
client.knock(roomIdOrAlias.identifier).destroy()
client.knock(roomIdOrAlias.identifier, message, serverNames).destroy()
try {
awaitRoom(roomIdOrAlias, 10.seconds, CurrentUserMembership.KNOCKED)
} catch (e: Exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ class UtdTracker(
Timber.d("onUtd for event ${info.eventId}, timeToDecryptMs: ${info.timeToDecryptMs}")
val name = when (info.cause) {
UtdCause.UNKNOWN -> Error.Name.OlmKeysNotSentError
UtdCause.MEMBERSHIP -> Error.Name.ExpectedDueToMembership
UtdCause.SENT_BEFORE_WE_JOINED -> Error.Name.ExpectedDueToMembership
UtdCause.VERIFICATION_VIOLATION -> Error.Name.ExpectedVerificationViolation
UtdCause.UNSIGNED_DEVICE,
UtdCause.UNKNOWN_DEVICE -> {
Error.Name.ExpectedSentByInsecureDevice
}
}
val event = Error(
context = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,47 +9,27 @@ package io.element.android.libraries.matrix.impl.room

import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.timeline.item.event.EventType
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import org.matrix.rustcomponents.sdk.RequiredState
import org.matrix.rustcomponents.sdk.RoomListService
import org.matrix.rustcomponents.sdk.RoomSubscription
import timber.log.Timber

private const val DEFAULT_TIMELINE_LIMIT = 20u

class RoomSyncSubscriber(
private val roomListService: RoomListService,
private val dispatchers: CoroutineDispatchers,
) {
private val subscribedRoomIds = mutableSetOf<RoomId>()
private val mutex = Mutex()

private val settings = RoomSubscription(
requiredState = listOf(
RequiredState(key = EventType.STATE_ROOM_NAME, value = ""),
RequiredState(key = EventType.STATE_ROOM_TOPIC, value = ""),
RequiredState(key = EventType.STATE_ROOM_AVATAR, value = ""),
RequiredState(key = EventType.STATE_ROOM_CANONICAL_ALIAS, value = ""),
RequiredState(key = EventType.STATE_ROOM_JOIN_RULES, value = ""),
RequiredState(key = EventType.STATE_ROOM_POWER_LEVELS, value = ""),
RequiredState(key = EventType.STATE_ROOM_PINNED_EVENT, value = ""),
),
timelineLimit = DEFAULT_TIMELINE_LIMIT,
// We don't need heroes here as they're already included in the `all_rooms` list
includeHeroes = false,
)

suspend fun subscribe(roomId: RoomId) {
mutex.withLock {
withContext(dispatchers.io) {
try {
if (!isSubscribedTo(roomId)) {
Timber.d("Subscribing to room $roomId}")
roomListService.subscribeToRooms(listOf(roomId.value), settings)
roomListService.subscribeToRooms(listOf(roomId.value))
}
subscribedRoomIds.add(roomId)
} catch (exception: Exception) {
Expand All @@ -65,7 +45,7 @@ class RoomSyncSubscriber(
val roomIdsToSubscribeTo = roomIds.filterNot { isSubscribedTo(it) }
if (roomIdsToSubscribeTo.isNotEmpty()) {
Timber.d("Subscribing to rooms: $roomIds")
roomListService.subscribeToRooms(roomIdsToSubscribeTo.map { it.value }, settings)
roomListService.subscribeToRooms(roomIdsToSubscribeTo.map { it.value })
subscribedRoomIds.addAll(roomIds)
}
} catch (cancellationException: CancellationException) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ class RustTimeline(
formattedCaption = formattedBody?.let {
FormattedBody(body = it, format = MessageFormat.Html)
},
storeInCache = true,
progressWatcher = progressCallback?.toProgressWatcher()
)
}
Expand All @@ -361,6 +362,7 @@ class RustTimeline(
formattedCaption = formattedBody?.let {
FormattedBody(body = it, format = MessageFormat.Html)
},
storeInCache = true,
progressWatcher = progressCallback?.toProgressWatcher()
)
}
Expand All @@ -374,14 +376,15 @@ class RustTimeline(
// Maybe allow a caption in the future?
caption = null,
formattedCaption = null,
storeInCache = true,
progressWatcher = progressCallback?.toProgressWatcher()
)
}
}

override suspend fun sendFile(file: File, fileInfo: FileInfo, progressCallback: ProgressCallback?): Result<MediaUploadHandler> {
return sendAttachment(listOf(file)) {
inner.sendFile(file.path, fileInfo.map(), progressCallback?.toProgressWatcher())
inner.sendFile(file.path, fileInfo.map(), false, progressCallback?.toProgressWatcher())
}
}

Expand Down Expand Up @@ -496,6 +499,7 @@ class RustTimeline(
// Maybe allow a caption in the future?
caption = null,
formattedCaption = null,
storeInCache = true,
progressWatcher = progressCallback?.toProgressWatcher(),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ 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.QueueWedgeError
import org.matrix.rustcomponents.sdk.Reaction
import org.matrix.rustcomponents.sdk.ShieldState
import uniffi.matrix_sdk_common.ShieldStateCode
Expand Down Expand Up @@ -78,25 +78,31 @@ fun RustEventSendState?.map(): LocalEventSendState? {
null -> null
RustEventSendState.NotSentYet -> LocalEventSendState.Sending
is RustEventSendState.SendingFailed -> {
if (isRecoverable) {
LocalEventSendState.Sending
} else {
LocalEventSendState.Failed.Unknown(error)
when (val queueWedgeError = error) {
QueueWedgeError.CrossVerificationRequired -> {
// The current device is not cross-signed (or cross signing is not setup)
LocalEventSendState.Failed.SendingFromUnverifiedDevice
}
is QueueWedgeError.IdentityViolations -> {
LocalEventSendState.Failed.VerifiedUserChangedIdentity(queueWedgeError.users.map { UserId(it) })
}
is QueueWedgeError.InsecureDevices -> {
LocalEventSendState.Failed.VerifiedUserHasUnsignedDevice(
devices = queueWedgeError.userDeviceMap.entries.associate { entry ->
UserId(entry.key) to entry.value.map { DeviceId(it) }
}
)
}
is QueueWedgeError.GenericApiError -> {
if (isRecoverable) {
LocalEventSendState.Sending
} else {
LocalEventSendState.Failed.Unknown(queueWedgeError.msg)
}
}
}
}
is RustEventSendState.Sent -> LocalEventSendState.Sent(EventId(eventId))
is RustEventSendState.VerifiedUserChangedIdentity -> {
LocalEventSendState.Failed.VerifiedUserChangedIdentity(users.map { UserId(it) })
}
is RustEventSendState.VerifiedUserHasUnsignedDevice -> {
LocalEventSendState.Failed.VerifiedUserHasUnsignedDevice(
devices = devices.entries.associate { entry ->
UserId(entry.key) to entry.value.map { DeviceId(it) }
}
)
}
EventSendState.CrossSigningNotSetup -> LocalEventSendState.Failed.CrossSigningNotSetup
EventSendState.SendingFromUnverifiedDevice -> LocalEventSendState.Failed.SendingFromUnverifiedDevice
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,11 @@ private fun RustMembershipChange.map(): MembershipChange {

private fun RustUtdCause.map(): UtdCause {
return when (this) {
RustUtdCause.MEMBERSHIP -> UtdCause.Membership
RustUtdCause.SENT_BEFORE_WE_JOINED -> UtdCause.SentBeforeWeJoined
RustUtdCause.UNKNOWN -> UtdCause.Unknown
RustUtdCause.VERIFICATION_VIOLATION -> UtdCause.VerificationViolation
RustUtdCause.UNSIGNED_DEVICE -> UtdCause.UnsignedDevice
RustUtdCause.UNKNOWN_DEVICE -> UtdCause.UnknownDevice
}
}

Expand Down
Loading

0 comments on commit 9fb68fc

Please sign in to comment.