From 6181387776496d1cc9e89bbf91be4ae22ef990e5 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Wed, 21 Aug 2024 18:22:24 +0200 Subject: [PATCH] timeline: allow reactions in local|remote event timeline items --- .../src/timeline/day_dividers.rs | 2 +- .../src/timeline/event_handler.rs | 24 ++++----------- .../src/timeline/event_item/mod.rs | 30 ++++++++++++------- .../src/timeline/event_item/remote.rs | 22 ++------------ crates/matrix-sdk-ui/src/timeline/util.rs | 7 +---- 5 files changed, 29 insertions(+), 56 deletions(-) diff --git a/crates/matrix-sdk-ui/src/timeline/day_dividers.rs b/crates/matrix-sdk-ui/src/timeline/day_dividers.rs index 8fd295f41..f8e1e7485 100644 --- a/crates/matrix-sdk-ui/src/timeline/day_dividers.rs +++ b/crates/matrix-sdk-ui/src/timeline/day_dividers.rs @@ -623,7 +623,6 @@ mod tests { let event_kind = EventTimelineItemKind::Remote(RemoteEventTimelineItem { event_id: owned_event_id!("$1"), transaction_id: None, - reactions: Default::default(), read_receipts: Default::default(), is_own: false, is_highlighted: false, @@ -638,6 +637,7 @@ mod tests { timestamp, TimelineItemContent::RedactedMessage, event_kind, + Default::default(), false, ) } diff --git a/crates/matrix-sdk-ui/src/timeline/event_handler.rs b/crates/matrix-sdk-ui/src/timeline/event_handler.rs index 3f0d2bde8..a3d71d8ac 100644 --- a/crates/matrix-sdk-ui/src/timeline/event_handler.rs +++ b/crates/matrix-sdk-ui/src/timeline/event_handler.rs @@ -572,11 +572,6 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> { }; if let Some((idx, event_item)) = rfind_event_by_id(self.items, reacted_to_event_id) { - let Some(remote_event_item) = event_item.as_remote() else { - error!("received reaction to a local echo"); - return; - }; - // Ignore reactions on redacted events. if let TimelineItemContent::RedactedMessage = event_item.content() { debug!("Ignoring reaction on redacted event"); @@ -586,7 +581,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> { trace!("Added reaction"); // Add the reaction to the event item's bundled reactions. - let mut reactions = remote_event_item.reactions.clone(); + let mut reactions = event_item.reactions.clone(); reactions.entry(c.relates_to.key.clone()).or_default().insert( self.ctx.sender.clone(), @@ -839,16 +834,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> { return false; }; - let Some(remote_event_item) = item.as_remote() else { - error!("inconsistent state: redaction received on a non-remote event item"); - return false; - }; - - let mut reactions = remote_event_item.reactions.clone(); + let mut reactions = item.reactions.clone(); if reactions.remove_reaction(&sender, &key).is_some() { trace!("Removing reaction"); - let new_item = item.with_kind(remote_event_item.with_reactions(reactions)); - self.items.set(item_pos, TimelineItem::new(new_item, item.internal_id.to_owned())); + self.items.set(item_pos, item.with_reactions(reactions)); self.result.items_updated += 1; return true; } @@ -894,7 +883,6 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> { RemoteEventTimelineItem { event_id: event_id.clone(), transaction_id: txn_id.clone(), - reactions, read_receipts: self.ctx.read_receipts.clone(), is_own: self.ctx.is_own_event, is_highlighted: self.ctx.is_highlighted, @@ -915,6 +903,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> { timestamp, content, kind, + reactions, is_room_encrypted, ); @@ -967,10 +956,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> { if old_item.content.is_redacted() && !item.content.is_redacted() { warn!("Got original form of an event that was previously redacted"); item.content = item.content.redact(&self.meta.room_version); - item.as_remote_mut() - .expect("Can't have a local item when flow == Remote") - .reactions - .clear(); + item.reactions.clear(); } } 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 192d34da8..52abb9766 100644 --- a/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs @@ -66,6 +66,8 @@ pub struct EventTimelineItem { pub(super) sender: OwnedUserId, /// The sender's profile of the event. pub(super) sender_profile: TimelineDetails, + /// All bundled reactions about the event. + pub(super) reactions: ReactionsByKeyBySender, /// The timestamp of the event. pub(super) timestamp: MilliSecondsSinceUnixEpoch, /// The content of the event. @@ -114,10 +116,11 @@ impl EventTimelineItem { timestamp: MilliSecondsSinceUnixEpoch, content: TimelineItemContent, kind: EventTimelineItemKind, + reactions: ReactionsByKeyBySender, is_room_encrypted: bool, ) -> Self { let is_room_encrypted = Some(is_room_encrypted); - Self { sender, sender_profile, timestamp, content, kind, is_room_encrypted } + Self { sender, sender_profile, timestamp, content, reactions, kind, is_room_encrypted } } /// If the supplied low-level `SyncTimelineEvent` is suitable for use as the @@ -175,7 +178,6 @@ impl EventTimelineItem { let kind = RemoteEventTimelineItem { event_id, transaction_id: None, - reactions, read_receipts, is_own, is_highlighted, @@ -199,9 +201,16 @@ impl EventTimelineItem { } else { TimelineDetails::Unavailable }; - let is_room_encrypted = None; - Some(Self { sender, sender_profile, timestamp, content, kind, is_room_encrypted }) + Some(Self { + sender, + sender_profile, + timestamp, + content, + kind, + reactions, + is_room_encrypted: None, + }) } /// Check whether this item is a local echo. @@ -291,12 +300,7 @@ impl EventTimelineItem { /// Get the reactions of this item. pub fn reactions(&self) -> &ReactionsByKeyBySender { - // There's not much of a point in allowing reactions to local echoes. - static EMPTY_REACTIONS: Lazy = Lazy::new(Default::default); - match &self.kind { - EventTimelineItemKind::Local(_) => &EMPTY_REACTIONS, - EventTimelineItemKind::Remote(remote_event) => &remote_event.reactions, - } + &self.reactions } /// Get the read receipts of this item. @@ -453,6 +457,11 @@ impl EventTimelineItem { Self { kind: kind.into(), ..self.clone() } } + /// Clone the current event item, and update its `reactions`. + pub fn with_reactions(&self, reactions: ReactionsByKeyBySender) -> Self { + Self { reactions, ..self.clone() } + } + /// Clone the current event item, and update its content. /// /// Optionally update `latest_edit_json` if the update is an edit received @@ -490,6 +499,7 @@ impl EventTimelineItem { content, kind, is_room_encrypted: self.is_room_encrypted, + reactions: ReactionsByKeyBySender::default(), } } diff --git a/crates/matrix-sdk-ui/src/timeline/event_item/remote.rs b/crates/matrix-sdk-ui/src/timeline/event_item/remote.rs index c86e6a539..4510910c4 100644 --- a/crates/matrix-sdk-ui/src/timeline/event_item/remote.rs +++ b/crates/matrix-sdk-ui/src/timeline/event_item/remote.rs @@ -22,8 +22,6 @@ use ruma::{ OwnedEventId, OwnedTransactionId, OwnedUserId, }; -use super::ReactionsByKeyBySender; - /// An item for an event that was received from the homeserver. #[derive(Clone)] pub(in crate::timeline) struct RemoteEventTimelineItem { @@ -33,9 +31,6 @@ pub(in crate::timeline) struct RemoteEventTimelineItem { /// If available, the transaction id we've used to send this event. pub transaction_id: Option, - /// All bundled reactions about the event. - pub reactions: ReactionsByKeyBySender, - /// All read receipts for the event. /// /// The key is the ID of a room member and the value are details about the @@ -78,20 +73,9 @@ impl RemoteEventTimelineItem { Self { encryption_info, ..self.clone() } } - /// Clone the current event item, and update its `reactions`. - pub fn with_reactions(&self, reactions: ReactionsByKeyBySender) -> Self { - Self { reactions, ..self.clone() } - } - - /// Clone the current event item, and clear its `reactions` as well as the - /// JSON representation fields. + /// Clone the current event item, and redacts its fields. pub fn redact(&self) -> Self { - Self { - reactions: ReactionsByKeyBySender::default(), - original_json: None, - latest_edit_json: None, - ..self.clone() - } + Self { original_json: None, latest_edit_json: None, ..self.clone() } } } @@ -116,7 +100,6 @@ impl fmt::Debug for RemoteEventTimelineItem { let Self { event_id, transaction_id, - reactions, read_receipts, is_own, encryption_info, @@ -129,7 +112,6 @@ impl fmt::Debug for RemoteEventTimelineItem { f.debug_struct("RemoteEventTimelineItem") .field("event_id", event_id) .field("transaction_id", transaction_id) - .field("reactions", reactions) .field("read_receipts", read_receipts) .field("is_own", is_own) .field("is_highlighted", is_highlighted) diff --git a/crates/matrix-sdk-ui/src/timeline/util.rs b/crates/matrix-sdk-ui/src/timeline/util.rs index 7d1c648be..f88428af7 100644 --- a/crates/matrix-sdk-ui/src/timeline/util.rs +++ b/crates/matrix-sdk-ui/src/timeline/util.rs @@ -39,12 +39,7 @@ impl<'a> EventTimelineItemWithId<'a> { /// Create a clone of the underlying [`TimelineItem`] with the given /// reactions. pub fn with_reactions(&self, reactions: ReactionsByKeyBySender) -> Arc { - let remote_item = self - .inner - .as_remote() - .expect("should only be remote at the moment (TODO: local)") - .with_reactions(reactions); - let event_item = self.inner.with_kind(remote_item); + let event_item = self.inner.with_reactions(reactions); TimelineItem::new(event_item, self.internal_id.to_owned()) } }