From f5cda21d59d3a894ce9eea925fb8d21b9434660a Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 12 Dec 2025 14:38:04 +0000 Subject: [PATCH 1/5] ui: `TimelineEventItem::get_shield`: stop returning `Option` The `ShieldState` enum has a `None` variant, so we don't need an `Option` on top of it. --- bindings/matrix-sdk-ffi/src/timeline/mod.rs | 2 +- .../src/timeline/event_item/mod.rs | 18 +++++++++--------- .../src/timeline/tests/shields.rs | 12 ++++++------ .../tests/integration/timeline/mod.rs | 11 ++++++----- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/bindings/matrix-sdk-ffi/src/timeline/mod.rs b/bindings/matrix-sdk-ffi/src/timeline/mod.rs index db1be1ee5a9..8cb78e72446 100644 --- a/bindings/matrix-sdk-ffi/src/timeline/mod.rs +++ b/bindings/matrix-sdk-ffi/src/timeline/mod.rs @@ -1278,7 +1278,7 @@ pub struct LazyTimelineItemProvider(Arc Option { - self.0.get_shield(strict).map(Into::into) + Some(self.0.get_shield(strict).into()) } /// Returns some debug information for this event timeline item. diff --git a/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs b/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs index 97595a4fb93..8b9be1ea59d 100644 --- a/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs @@ -309,30 +309,30 @@ impl EventTimelineItem { } } - /// Gets the [`ShieldState`] which can be used to decorate messages in the - /// recommended way. - pub fn get_shield(&self, strict: bool) -> Option { + /// Gets the [`ShieldState`] which can be used to decorate + /// messages in the recommended way. + pub fn get_shield(&self, strict: bool) -> ShieldState { if !self.is_room_encrypted || self.is_local_echo() { - return None; + return ShieldState::None; } // An unable-to-decrypt message has no authenticity shield. if self.content().is_unable_to_decrypt() { - return None; + return ShieldState::None; } match self.encryption_info() { Some(info) => { if strict { - Some(info.verification_state.to_shield_state_strict()) + info.verification_state.to_shield_state_strict().into() } else { - Some(info.verification_state.to_shield_state_lax()) + info.verification_state.to_shield_state_lax().into() } } - None => Some(ShieldState::Red { + None => ShieldState::Red { code: ShieldStateCode::SentInClear, message: SENT_IN_CLEAR, - }), + }, } } diff --git a/crates/matrix-sdk-ui/src/timeline/tests/shields.rs b/crates/matrix-sdk-ui/src/timeline/tests/shields.rs index ee25822fc46..e816e2bb712 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/shields.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/shields.rs @@ -31,7 +31,7 @@ async fn test_no_shield_in_unencrypted_room() { let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); let shield = item.as_event().unwrap().get_shield(false); - assert!(shield.is_none()); + assert_eq!(shield, ShieldState::None); } #[async_test] @@ -46,7 +46,7 @@ async fn test_sent_in_clear_shield() { let shield = item.as_event().unwrap().get_shield(false); assert_eq!( shield, - Some(ShieldState::Red { code: ShieldStateCode::SentInClear, message: "Not encrypted." }) + ShieldState::Red { code: ShieldStateCode::SentInClear, message: "Not encrypted." } ); } @@ -75,7 +75,7 @@ async fn test_local_sent_in_clear_shield() { // available). assert!(event_item.is_local_echo()); let shield = event_item.get_shield(false); - assert_eq!(shield, None); + assert_eq!(shield, ShieldState::None); { // The date divider comes in late. @@ -96,7 +96,7 @@ async fn test_local_sent_in_clear_shield() { // Then the local echo still should not have a shield. assert!(event_item.is_local_echo()); let shield = event_item.get_shield(false); - assert_eq!(shield, None); + assert_eq!(shield, ShieldState::None); // When the remote echo comes in. timeline @@ -118,7 +118,7 @@ async fn test_local_sent_in_clear_shield() { let shield = event_item.get_shield(false); assert_eq!( shield, - Some(ShieldState::Red { code: ShieldStateCode::SentInClear, message: "Not encrypted." }) + ShieldState::Red { code: ShieldStateCode::SentInClear, message: "Not encrypted." } ); // Date divider is adjusted. @@ -168,5 +168,5 @@ async fn test_utd_shield() { // Then the message is displayed with no shield let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); let shield = item.as_event().unwrap().get_shield(false); - assert!(shield.is_none()); + assert_eq!(shield, ShieldState::None); } diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/mod.rs b/crates/matrix-sdk-ui/tests/integration/timeline/mod.rs index 4a38f8eb971..5a9ed4ce807 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/mod.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/mod.rs @@ -22,6 +22,7 @@ use matrix_sdk::{ linked_chunk::{ChunkIdentifier, LinkedChunkId, Position, Update}, test_utils::mocks::{MatrixMockServer, RoomContextResponseTemplate}, }; +use matrix_sdk_common::deserialized_responses::ShieldState; use matrix_sdk_test::{ ALICE, BOB, JoinedRoomBuilder, RoomAccountDataTestEvent, StateTestEvent, async_test, event_factory::EventFactory, @@ -757,7 +758,7 @@ async fn test_timeline_without_encryption_info() { assert_eq!(items.len(), 2); assert!(items[0].as_virtual().is_some()); // No encryption, no shields. - assert!(items[1].as_event().unwrap().get_shield(false).is_none()); + assert_eq!(items[1].as_event().unwrap().get_shield(false), ShieldState::None); } #[async_test] @@ -787,7 +788,7 @@ async fn test_timeline_without_encryption_can_update() { assert_eq!(items.len(), 2); assert!(items[0].as_virtual().is_some()); // No encryption, no shields - assert!(items[1].as_event().unwrap().get_shield(false).is_none()); + assert_eq!(items[1].as_event().unwrap().get_shield(false), ShieldState::None); let encryption_event_content = RoomEncryptionEventContent::with_recommended_defaults(); server @@ -805,17 +806,17 @@ async fn test_timeline_without_encryption_can_update() { // Previous timeline event now has a shield. assert_let!(VectorDiff::Set { index, value } = &timeline_updates[0]); assert_eq!(*index, 1); - assert!(value.as_event().unwrap().get_shield(false).is_some()); + assert_ne!(value.as_event().unwrap().get_shield(false), ShieldState::None); // Room encryption event is received. assert_let!(VectorDiff::PushBack { value } = &timeline_updates[1]); assert_let!(TimelineItemContent::OtherState(other_state) = value.as_event().unwrap().content()); assert_let!(AnyOtherFullStateEventContent::RoomEncryption(_) = other_state.content()); - assert!(value.as_event().unwrap().get_shield(false).is_some()); + assert_ne!(value.as_event().unwrap().get_shield(false), ShieldState::None); // New message event is received and has a shield. assert_let!(VectorDiff::PushBack { value } = &timeline_updates[2]); - assert!(value.as_event().unwrap().get_shield(false).is_some()); + assert_ne!(value.as_event().unwrap().get_shield(false), ShieldState::None); assert_pending!(stream); } From 7438c59acdf418acb342064eac7f422050f0c813 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 18 Dec 2025 13:05:40 +0000 Subject: [PATCH 2/5] bindings: `get_shields`: stop returning `Option` Again, there is no need for an `Option` as well as a `None` variant --- bindings/matrix-sdk-ffi/src/timeline/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/matrix-sdk-ffi/src/timeline/mod.rs b/bindings/matrix-sdk-ffi/src/timeline/mod.rs index 8cb78e72446..20c3e1f3867 100644 --- a/bindings/matrix-sdk-ffi/src/timeline/mod.rs +++ b/bindings/matrix-sdk-ffi/src/timeline/mod.rs @@ -1277,8 +1277,8 @@ pub struct LazyTimelineItemProvider(Arc Option { - Some(self.0.get_shield(strict).into()) + fn get_shields(&self, strict: bool) -> ShieldState { + self.0.get_shield(strict).into() } /// Returns some debug information for this event timeline item. From dbefaef77723d59759301f6f95833bfa4f7c93f3 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 18 Dec 2025 13:09:54 +0000 Subject: [PATCH 3/5] bindings: remove `message` from `ShieldState` Since this can't be localised, apps shouldn't be using it. --- bindings/matrix-sdk-ffi/CHANGELOG.md | 5 +++++ bindings/matrix-sdk-ffi/src/timeline/mod.rs | 20 ++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/bindings/matrix-sdk-ffi/CHANGELOG.md b/bindings/matrix-sdk-ffi/CHANGELOG.md index 91497beb548..268ff38f0fa 100644 --- a/bindings/matrix-sdk-ffi/CHANGELOG.md +++ b/bindings/matrix-sdk-ffi/CHANGELOG.md @@ -15,6 +15,11 @@ All notable changes to this project will be documented in this file. ### Features +- [**breaking**] `LazyTimelineItemProvider::get_shields` no longer returns an + an `Option`: the `ShieldState` type contains a `None` variant, so the + `Option` was redundant. The `message` field has also been removed: since there + was no way to localise the returned string, applications should not be using it. + ([#5959](https://github.com/matrix-org/matrix-rust-sdk/pull/5959)) - Add `SpaceService::get_space_room` to get a space given its id from the space graph if available. [#5944](https://github.com/matrix-org/matrix-rust-sdk/pull/5944) - Add `QrCodeData::to_bytes()` to allow generation of a QR code. diff --git a/bindings/matrix-sdk-ffi/src/timeline/mod.rs b/bindings/matrix-sdk-ffi/src/timeline/mod.rs index 20c3e1f3867..964a19dd01e 100644 --- a/bindings/matrix-sdk-ffi/src/timeline/mod.rs +++ b/bindings/matrix-sdk-ffi/src/timeline/mod.rs @@ -980,12 +980,12 @@ impl From<&matrix_sdk_ui::timeline::EventSendState> for EventSendState { /// authenticity properties. #[derive(uniffi::Enum, Clone)] pub enum ShieldState { - /// A red shield with a tooltip containing the associated message should be - /// presented. - Red { code: ShieldStateCode, message: String }, - /// A grey shield with a tooltip containing the associated message should be - /// presented. - Grey { code: ShieldStateCode, message: String }, + /// A red shield with a tooltip containing a message appropriate to the + /// associated code should be presented. + Red { code: TimelineEventShieldStateCode }, + /// A grey shield with a tooltip containing a message appropriate to the + /// associated code should be presented. + Grey { code: TimelineEventShieldStateCode }, /// No shield should be presented. None, } @@ -993,12 +993,8 @@ pub enum ShieldState { impl From for ShieldState { fn from(value: SdkShieldState) -> Self { match value { - SdkShieldState::Red { code, message } => { - Self::Red { code, message: message.to_owned() } - } - SdkShieldState::Grey { code, message } => { - Self::Grey { code, message: message.to_owned() } - } + SdkShieldState::Red { code, message: _ } => Self::Red { code }, + SdkShieldState::Grey { code, message: _ } => Self::Grey { code }, SdkShieldState::None => Self::None, } } From d5ce01acabe07f3a4624f3261bc4f67265e3fae0 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 18 Dec 2025 13:14:38 +0000 Subject: [PATCH 4/5] ui: new type for `EventTimelineItem::get_shield` Separate the shield types between common and UI, so that we can change common without breaking UI. The new type does not include a `message` field: since it cannot be localised, clients should not be using it. --- bindings/matrix-sdk-ffi/src/timeline/mod.rs | 6 +- .../src/deserialized_responses.rs | 1 - crates/matrix-sdk-ui/CHANGELOG.md | 4 + .../src/timeline/event_item/mod.rs | 86 +++++++++++++++++-- crates/matrix-sdk-ui/src/timeline/mod.rs | 3 +- .../src/timeline/tests/shields.rs | 15 ++-- .../tests/integration/timeline/mod.rs | 15 ++-- 7 files changed, 100 insertions(+), 30 deletions(-) diff --git a/bindings/matrix-sdk-ffi/src/timeline/mod.rs b/bindings/matrix-sdk-ffi/src/timeline/mod.rs index 964a19dd01e..9ff9ebe990f 100644 --- a/bindings/matrix-sdk-ffi/src/timeline/mod.rs +++ b/bindings/matrix-sdk-ffi/src/timeline/mod.rs @@ -21,7 +21,6 @@ use matrix_sdk::{ attachment::{ AttachmentInfo, BaseAudioInfo, BaseFileInfo, BaseImageInfo, BaseVideoInfo, Thumbnail, }, - deserialized_responses::{ShieldState as SdkShieldState, ShieldStateCode}, event_cache::RoomPaginationStatus, room::edit::EditedContent as SdkEditedContent, }; @@ -33,6 +32,7 @@ use matrix_sdk_ui::timeline::{ self, AttachmentConfig, AttachmentSource, EventItemOrigin, LatestEventValue as UiLatestEventValue, LatestEventValueLocalState, MediaUploadProgress as SdkMediaUploadProgress, Profile, TimelineDetails, + TimelineEventShieldState as SdkShieldState, TimelineEventShieldStateCode, TimelineUniqueId as SdkTimelineUniqueId, }; use mime::Mime; @@ -993,8 +993,8 @@ pub enum ShieldState { impl From for ShieldState { fn from(value: SdkShieldState) -> Self { match value { - SdkShieldState::Red { code, message: _ } => Self::Red { code }, - SdkShieldState::Grey { code, message: _ } => Self::Grey { code }, + SdkShieldState::Red { code } => Self::Red { code }, + SdkShieldState::Grey { code } => Self::Grey { code }, SdkShieldState::None => Self::None, } } diff --git a/crates/matrix-sdk-common/src/deserialized_responses.rs b/crates/matrix-sdk-common/src/deserialized_responses.rs index a0211abc79d..93d8a615398 100644 --- a/crates/matrix-sdk-common/src/deserialized_responses.rs +++ b/crates/matrix-sdk-common/src/deserialized_responses.rs @@ -46,7 +46,6 @@ const UNKNOWN_DEVICE: &str = "Encrypted by an unknown or deleted device."; const MISMATCHED_SENDER: &str = "\ The sender of the event does not match the owner of the device \ that created the Megolm session."; -pub const SENT_IN_CLEAR: &str = "Not encrypted."; /// Represents the state of verification for a decrypted message sent by a /// device. diff --git a/crates/matrix-sdk-ui/CHANGELOG.md b/crates/matrix-sdk-ui/CHANGELOG.md index 73ff2147469..90ea430dac2 100644 --- a/crates/matrix-sdk-ui/CHANGELOG.md +++ b/crates/matrix-sdk-ui/CHANGELOG.md @@ -18,6 +18,10 @@ All notable changes to this project will be documented in this file. ### Features +- [**breaking**] `EventTimelineItem::get_shield` now returns a new type, + `TimelineEventShieldState`, which extends the old `ShieldState` with a code + for `SentInClear`, now that the latter has been removed from `ShieldState`. + ([#5959](https://github.com/matrix-org/matrix-rust-sdk/pull/5959)) - Add `SpaceService::get_space_room` to get a space given its id from the space graph if available. ([#5944](https://github.com/matrix-org/matrix-rust-sdk/pull/5944)) diff --git a/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs b/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs index 8b9be1ea59d..a14c53a84da 100644 --- a/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs @@ -24,7 +24,7 @@ use matrix_sdk::{ deserialized_responses::{EncryptionInfo, ShieldState}, send_queue::{SendHandle, SendReactionHandle}, }; -use matrix_sdk_base::deserialized_responses::{SENT_IN_CLEAR, ShieldStateCode}; +use matrix_sdk_base::deserialized_responses::ShieldStateCode; use once_cell::sync::Lazy; use ruma::{ EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedMxcUri, OwnedTransactionId, @@ -309,16 +309,16 @@ impl EventTimelineItem { } } - /// Gets the [`ShieldState`] which can be used to decorate + /// Gets the [`TimelineEventShieldState`] which can be used to decorate /// messages in the recommended way. - pub fn get_shield(&self, strict: bool) -> ShieldState { + pub fn get_shield(&self, strict: bool) -> TimelineEventShieldState { if !self.is_room_encrypted || self.is_local_echo() { - return ShieldState::None; + return TimelineEventShieldState::None; } // An unable-to-decrypt message has no authenticity shield. if self.content().is_unable_to_decrypt() { - return ShieldState::None; + return TimelineEventShieldState::None; } match self.encryption_info() { @@ -329,10 +329,9 @@ impl EventTimelineItem { info.verification_state.to_shield_state_lax().into() } } - None => ShieldState::Red { - code: ShieldStateCode::SentInClear, - message: SENT_IN_CLEAR, - }, + None => { + TimelineEventShieldState::Red { code: TimelineEventShieldStateCode::SentInClear } + } } } @@ -693,3 +692,72 @@ impl ReactionsByKeyBySender { None } } + +/// Extends [`ShieldState`] to allow for a `SentInClear` code. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum TimelineEventShieldState { + /// A red shield with a tooltip containing a message appropriate to the + /// associated code should be presented. + Red { + /// A machine-readable representation. + code: TimelineEventShieldStateCode, + }, + /// A grey shield with a tooltip containing a message appropriate to the + /// associated code should be presented. + Grey { + /// A machine-readable representation. + code: TimelineEventShieldStateCode, + }, + /// No shield should be presented. + None, +} + +impl From for TimelineEventShieldState { + fn from(value: ShieldState) -> Self { + match value { + ShieldState::Red { code, message: _ } => { + TimelineEventShieldState::Red { code: code.into() } + } + ShieldState::Grey { code, message: _ } => { + TimelineEventShieldState::Grey { code: code.into() } + } + ShieldState::None => TimelineEventShieldState::None, + } + } +} + +/// Extends [`ShieldStateCode`] to allow for a `SentInClear` code. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] +pub enum TimelineEventShieldStateCode { + /// Not enough information available to check the authenticity. + AuthenticityNotGuaranteed, + /// The sending device isn't yet known by the Client. + UnknownDevice, + /// The sending device hasn't been verified by the sender. + UnsignedDevice, + /// The sender hasn't been verified by the Client's user. + UnverifiedIdentity, + /// The sender was previously verified but changed their identity. + VerificationViolation, + /// The `sender` field on the event does not match the owner of the device + /// that established the Megolm session. + MismatchedSender, + /// An unencrypted event in an encrypted room. + SentInClear, +} + +impl From for TimelineEventShieldStateCode { + fn from(value: ShieldStateCode) -> Self { + use TimelineEventShieldStateCode::*; + match value { + ShieldStateCode::AuthenticityNotGuaranteed => AuthenticityNotGuaranteed, + ShieldStateCode::UnknownDevice => UnknownDevice, + ShieldStateCode::UnsignedDevice => UnsignedDevice, + ShieldStateCode::UnverifiedIdentity => UnverifiedIdentity, + ShieldStateCode::SentInClear => SentInClear, + ShieldStateCode::VerificationViolation => VerificationViolation, + ShieldStateCode::MismatchedSender => MismatchedSender, + } + } +} diff --git a/crates/matrix-sdk-ui/src/timeline/mod.rs b/crates/matrix-sdk-ui/src/timeline/mod.rs index af8bec3fc87..741da8f15bd 100644 --- a/crates/matrix-sdk-ui/src/timeline/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/mod.rs @@ -97,7 +97,8 @@ pub use self::{ MemberProfileChange, MembershipChange, Message, MsgLikeContent, MsgLikeKind, OtherMessageLike, OtherState, PollResult, PollState, Profile, ReactionInfo, ReactionStatus, ReactionsByKeyBySender, RoomMembershipChange, RoomPinnedEventsChange, Sticker, - ThreadSummary, TimelineDetails, TimelineEventItemId, TimelineItemContent, + ThreadSummary, TimelineDetails, TimelineEventItemId, TimelineEventShieldState, + TimelineEventShieldStateCode, TimelineItemContent, }, event_type_filter::TimelineEventTypeFilter, item::{TimelineItem, TimelineItemKind, TimelineUniqueId}, diff --git a/crates/matrix-sdk-ui/src/timeline/tests/shields.rs b/crates/matrix-sdk-ui/src/timeline/tests/shields.rs index e816e2bb712..25901d21d26 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/shields.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/shields.rs @@ -1,6 +1,5 @@ use assert_matches::assert_matches; use eyeball_im::VectorDiff; -use matrix_sdk_base::deserialized_responses::{ShieldState, ShieldStateCode}; use matrix_sdk_test::{ALICE, async_test, event_factory::EventFactory}; use ruma::{ event_id, @@ -17,7 +16,7 @@ use ruma::{ use stream_assert::{assert_next_matches, assert_pending}; use crate::timeline::{ - EventSendState, + EventSendState, TimelineEventShieldState, TimelineEventShieldStateCode, tests::{TestTimeline, TestTimelineBuilder}, }; @@ -31,7 +30,7 @@ async fn test_no_shield_in_unencrypted_room() { let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); let shield = item.as_event().unwrap().get_shield(false); - assert_eq!(shield, ShieldState::None); + assert_eq!(shield, TimelineEventShieldState::None); } #[async_test] @@ -46,7 +45,7 @@ async fn test_sent_in_clear_shield() { let shield = item.as_event().unwrap().get_shield(false); assert_eq!( shield, - ShieldState::Red { code: ShieldStateCode::SentInClear, message: "Not encrypted." } + TimelineEventShieldState::Red { code: TimelineEventShieldStateCode::SentInClear } ); } @@ -75,7 +74,7 @@ async fn test_local_sent_in_clear_shield() { // available). assert!(event_item.is_local_echo()); let shield = event_item.get_shield(false); - assert_eq!(shield, ShieldState::None); + assert_eq!(shield, TimelineEventShieldState::None); { // The date divider comes in late. @@ -96,7 +95,7 @@ async fn test_local_sent_in_clear_shield() { // Then the local echo still should not have a shield. assert!(event_item.is_local_echo()); let shield = event_item.get_shield(false); - assert_eq!(shield, ShieldState::None); + assert_eq!(shield, TimelineEventShieldState::None); // When the remote echo comes in. timeline @@ -118,7 +117,7 @@ async fn test_local_sent_in_clear_shield() { let shield = event_item.get_shield(false); assert_eq!( shield, - ShieldState::Red { code: ShieldStateCode::SentInClear, message: "Not encrypted." } + TimelineEventShieldState::Red { code: TimelineEventShieldStateCode::SentInClear } ); // Date divider is adjusted. @@ -168,5 +167,5 @@ async fn test_utd_shield() { // Then the message is displayed with no shield let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); let shield = item.as_event().unwrap().get_shield(false); - assert_eq!(shield, ShieldState::None); + assert_eq!(shield, TimelineEventShieldState::None); } diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/mod.rs b/crates/matrix-sdk-ui/tests/integration/timeline/mod.rs index 5a9ed4ce807..0a21f5cf8d5 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/mod.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/mod.rs @@ -22,7 +22,6 @@ use matrix_sdk::{ linked_chunk::{ChunkIdentifier, LinkedChunkId, Position, Update}, test_utils::mocks::{MatrixMockServer, RoomContextResponseTemplate}, }; -use matrix_sdk_common::deserialized_responses::ShieldState; use matrix_sdk_test::{ ALICE, BOB, JoinedRoomBuilder, RoomAccountDataTestEvent, StateTestEvent, async_test, event_factory::EventFactory, @@ -31,8 +30,8 @@ use matrix_sdk_ui::{ Timeline, timeline::{ AnyOtherFullStateEventContent, Error, EventSendState, MsgLikeKind, OtherMessageLike, - RedactError, RoomExt, TimelineBuilder, TimelineEventItemId, TimelineFocus, - TimelineItemContent, VirtualTimelineItem, default_event_filter, + RedactError, RoomExt, TimelineBuilder, TimelineEventItemId, TimelineEventShieldState, + TimelineFocus, TimelineItemContent, VirtualTimelineItem, default_event_filter, }, }; use ruma::{ @@ -758,7 +757,7 @@ async fn test_timeline_without_encryption_info() { assert_eq!(items.len(), 2); assert!(items[0].as_virtual().is_some()); // No encryption, no shields. - assert_eq!(items[1].as_event().unwrap().get_shield(false), ShieldState::None); + assert_eq!(items[1].as_event().unwrap().get_shield(false), TimelineEventShieldState::None); } #[async_test] @@ -788,7 +787,7 @@ async fn test_timeline_without_encryption_can_update() { assert_eq!(items.len(), 2); assert!(items[0].as_virtual().is_some()); // No encryption, no shields - assert_eq!(items[1].as_event().unwrap().get_shield(false), ShieldState::None); + assert_eq!(items[1].as_event().unwrap().get_shield(false), TimelineEventShieldState::None); let encryption_event_content = RoomEncryptionEventContent::with_recommended_defaults(); server @@ -806,17 +805,17 @@ async fn test_timeline_without_encryption_can_update() { // Previous timeline event now has a shield. assert_let!(VectorDiff::Set { index, value } = &timeline_updates[0]); assert_eq!(*index, 1); - assert_ne!(value.as_event().unwrap().get_shield(false), ShieldState::None); + assert_ne!(value.as_event().unwrap().get_shield(false), TimelineEventShieldState::None); // Room encryption event is received. assert_let!(VectorDiff::PushBack { value } = &timeline_updates[1]); assert_let!(TimelineItemContent::OtherState(other_state) = value.as_event().unwrap().content()); assert_let!(AnyOtherFullStateEventContent::RoomEncryption(_) = other_state.content()); - assert_ne!(value.as_event().unwrap().get_shield(false), ShieldState::None); + assert_ne!(value.as_event().unwrap().get_shield(false), TimelineEventShieldState::None); // New message event is received and has a shield. assert_let!(VectorDiff::PushBack { value } = &timeline_updates[2]); - assert_ne!(value.as_event().unwrap().get_shield(false), ShieldState::None); + assert_ne!(value.as_event().unwrap().get_shield(false), TimelineEventShieldState::None); assert_pending!(stream); } From b5f2128db17129cab978fd8b121a4ee89fb635cb Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 12 Dec 2025 15:01:17 +0000 Subject: [PATCH 5/5] common: remove now-unused `ShieldStateCode::SentInClear` --- crates/matrix-sdk-common/CHANGELOG.md | 7 +++++++ crates/matrix-sdk-common/src/deserialized_responses.rs | 3 --- .../src/snapshots/snapshot_test_shield_codes-5.snap | 4 ++-- crates/matrix-sdk-ui/src/timeline/event_item/mod.rs | 1 - 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/crates/matrix-sdk-common/CHANGELOG.md b/crates/matrix-sdk-common/CHANGELOG.md index 1a9cb7d7d22..80e352021f4 100644 --- a/crates/matrix-sdk-common/CHANGELOG.md +++ b/crates/matrix-sdk-common/CHANGELOG.md @@ -6,6 +6,13 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - ReleaseDate +### Features + +- [**breaking**] `ShieldStateCode` no longer includes + `SentInClear`. `VeificationState::to_shield_state_{lax,strict}` never + returned that code, ans so having it in the enum was somewhat misleading. + ([#5959](https://github.com/matrix-org/matrix-rust-sdk/pull/5959)) + ### Bug Fixes - Fix `TimelineEvent::from_bundled_latest_event` sometimes removing the `session_id` of UTDs. This broken event could later be saved to the event cache and become an unresolvable UTD. ([#5970](https://github.com/matrix-org/matrix-rust-sdk/pull/5970)). diff --git a/crates/matrix-sdk-common/src/deserialized_responses.rs b/crates/matrix-sdk-common/src/deserialized_responses.rs index 93d8a615398..1d1daa03136 100644 --- a/crates/matrix-sdk-common/src/deserialized_responses.rs +++ b/crates/matrix-sdk-common/src/deserialized_responses.rs @@ -282,8 +282,6 @@ pub enum ShieldStateCode { UnsignedDevice, /// The sender hasn't been verified by the Client's user. UnverifiedIdentity, - /// An unencrypted event in an encrypted room. - SentInClear, /// The sender was previously verified but changed their identity. #[serde(alias = "PreviouslyVerified")] VerificationViolation, @@ -1983,7 +1981,6 @@ mod tests { assert_json_snapshot!(ShieldStateCode::UnknownDevice); assert_json_snapshot!(ShieldStateCode::UnsignedDevice); assert_json_snapshot!(ShieldStateCode::UnverifiedIdentity); - assert_json_snapshot!(ShieldStateCode::SentInClear); assert_json_snapshot!(ShieldStateCode::VerificationViolation); }); } diff --git a/crates/matrix-sdk-common/src/snapshots/snapshot_test_shield_codes-5.snap b/crates/matrix-sdk-common/src/snapshots/snapshot_test_shield_codes-5.snap index 7b294abf051..753b4b44402 100644 --- a/crates/matrix-sdk-common/src/snapshots/snapshot_test_shield_codes-5.snap +++ b/crates/matrix-sdk-common/src/snapshots/snapshot_test_shield_codes-5.snap @@ -1,5 +1,5 @@ --- source: crates/matrix-sdk-common/src/deserialized_responses.rs -expression: "ShieldStateCode::SentInClear" +expression: "ShieldStateCode::VerificationViolation" --- -"SentInClear" +"VerificationViolation" diff --git a/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs b/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs index a14c53a84da..09f48b9d645 100644 --- a/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs @@ -755,7 +755,6 @@ impl From for TimelineEventShieldStateCode { ShieldStateCode::UnknownDevice => UnknownDevice, ShieldStateCode::UnsignedDevice => UnsignedDevice, ShieldStateCode::UnverifiedIdentity => UnverifiedIdentity, - ShieldStateCode::SentInClear => SentInClear, ShieldStateCode::VerificationViolation => VerificationViolation, ShieldStateCode::MismatchedSender => MismatchedSender, }