From ca0fc3cf6de522589dbb673b315a5d3acd259c23 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 9 Jun 2025 17:00:33 +0200 Subject: [PATCH] fix(timeline): correctly use the bundled event id when handling replacements --- .../src/timeline/controller/aggregations.rs | 3 + .../src/timeline/controller/metadata.rs | 84 +++++++++---------- .../timeline/event_item/content/message.rs | 13 +-- 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/crates/matrix-sdk-ui/src/timeline/controller/aggregations.rs b/crates/matrix-sdk-ui/src/timeline/controller/aggregations.rs index 239392811..ba8d4882d 100644 --- a/crates/matrix-sdk-ui/src/timeline/controller/aggregations.rs +++ b/crates/matrix-sdk-ui/src/timeline/controller/aggregations.rs @@ -638,6 +638,9 @@ fn resolve_edits( } /// Apply the selected edit to the given EventTimelineItem. +/// +/// Returns true if the edit was applied, false otherwise (because the edit and +/// original timeline item types didn't match, for instance). fn edit_item(item: &mut Cow<'_, EventTimelineItem>, edit: PendingEdit) -> bool { let PendingEdit { kind: edit_kind, edit_json, encryption_info } = edit; diff --git a/crates/matrix-sdk-ui/src/timeline/controller/metadata.rs b/crates/matrix-sdk-ui/src/timeline/controller/metadata.rs index 7b596469a..c50a1bc32 100644 --- a/crates/matrix-sdk-ui/src/timeline/controller/metadata.rs +++ b/crates/matrix-sdk-ui/src/timeline/controller/metadata.rs @@ -376,28 +376,26 @@ impl TimelineMetadata { // Record the bundled edit in the aggregations set, if any. if let Some(ctx) = remote_ctx { - if let Some(new_content) = extract_poll_edit_content(ctx.relations) { - // It is replacing the current event. - if let Some(edit_event_id) = - ctx.raw_event.get_field::("event_id").ok().flatten() - { - let edit_json = extract_bundled_edit_event_json(ctx.raw_event); - let aggregation = Aggregation::new( - TimelineEventItemId::EventId(edit_event_id), - AggregationKind::Edit(PendingEdit { - kind: PendingEditKind::Poll(Replacement::new( - ctx.event_id.to_owned(), - new_content, - )), - edit_json, - encryption_info: ctx.bundled_edit_encryption_info, - }), - ); - self.aggregations.add( - TimelineEventItemId::EventId(ctx.event_id.to_owned()), - aggregation, - ); - } + // Extract a potentially bundled edit. + if let Some((edit_event_id, new_content)) = + extract_poll_edit_content(ctx.relations) + { + let edit_json = extract_bundled_edit_event_json(ctx.raw_event); + let aggregation = Aggregation::new( + TimelineEventItemId::EventId(edit_event_id), + AggregationKind::Edit(PendingEdit { + kind: PendingEditKind::Poll(Replacement::new( + ctx.event_id.to_owned(), + new_content, + )), + edit_json, + encryption_info: ctx.bundled_edit_encryption_info, + }), + ); + self.aggregations.add( + TimelineEventItemId::EventId(ctx.event_id.to_owned()), + aggregation, + ); } self.mark_response(ctx.event_id, in_reply_to.as_ref()); @@ -415,28 +413,26 @@ impl TimelineMetadata { // Record the bundled edit in the aggregations set, if any. if let Some(ctx) = remote_ctx { - if let Some(new_content) = extract_room_msg_edit_content(ctx.relations) { - // It is replacing the current event. - if let Some(edit_event_id) = - ctx.raw_event.get_field::("event_id").ok().flatten() - { - let edit_json = extract_bundled_edit_event_json(ctx.raw_event); - let aggregation = Aggregation::new( - TimelineEventItemId::EventId(edit_event_id), - AggregationKind::Edit(PendingEdit { - kind: PendingEditKind::RoomMessage(Replacement::new( - ctx.event_id.to_owned(), - new_content, - )), - edit_json, - encryption_info: ctx.bundled_edit_encryption_info, - }), - ); - self.aggregations.add( - TimelineEventItemId::EventId(ctx.event_id.to_owned()), - aggregation, - ); - } + // Extract a potentially bundled edit. + if let Some((edit_event_id, new_content)) = + extract_room_msg_edit_content(ctx.relations) + { + let edit_json = extract_bundled_edit_event_json(ctx.raw_event); + let aggregation = Aggregation::new( + TimelineEventItemId::EventId(edit_event_id), + AggregationKind::Edit(PendingEdit { + kind: PendingEditKind::RoomMessage(Replacement::new( + ctx.event_id.to_owned(), + new_content, + )), + edit_json, + encryption_info: ctx.bundled_edit_encryption_info, + }), + ); + self.aggregations.add( + TimelineEventItemId::EventId(ctx.event_id.to_owned()), + aggregation, + ); } self.mark_response(ctx.event_id, in_reply_to.as_ref()); diff --git a/crates/matrix-sdk-ui/src/timeline/event_item/content/message.rs b/crates/matrix-sdk-ui/src/timeline/event_item/content/message.rs index 5125bc73b..0df441283 100644 --- a/crates/matrix-sdk-ui/src/timeline/event_item/content/message.rs +++ b/crates/matrix-sdk-ui/src/timeline/event_item/content/message.rs @@ -29,6 +29,7 @@ use ruma::{ }, html::RemoveReplyFallback, serde::Raw, + OwnedEventId, }; use tracing::{error, trace}; @@ -110,10 +111,10 @@ pub(crate) fn extract_bundled_edit_event_json( } /// Extracts a replacement for a room message, if present in the bundled -/// relations. +/// relations , along with the event ID of the replacement event. pub(crate) fn extract_room_msg_edit_content( relations: BundledMessageLikeRelations, -) -> Option { +) -> Option<(OwnedEventId, RoomMessageEventContentWithoutRelation)> { match *relations.replace? { AnySyncMessageLikeEvent::RoomMessage(SyncRoomMessageEvent::Original(ev)) => match ev .content @@ -121,7 +122,7 @@ pub(crate) fn extract_room_msg_edit_content( { Some(Relation::Replacement(re)) => { trace!("found a bundled edit event in a room message"); - Some(re.new_content) + Some((ev.event_id, re.new_content)) } _ => { error!("got m.room.message event with an edit without a valid m.replace relation"); @@ -139,16 +140,16 @@ pub(crate) fn extract_room_msg_edit_content( } /// Extracts a replacement for a room message, if present in the bundled -/// relations. +/// relations, along with the event ID of the replacement event. pub(crate) fn extract_poll_edit_content( relations: BundledMessageLikeRelations, -) -> Option { +) -> Option<(OwnedEventId, NewUnstablePollStartEventContentWithoutRelation)> { match *relations.replace? { AnySyncMessageLikeEvent::UnstablePollStart(SyncUnstablePollStartEvent::Original(ev)) => { match ev.content { UnstablePollStartEventContent::Replacement(re) => { trace!("found a bundled edit event in a poll"); - Some(re.relates_to.new_content) + Some((ev.event_id, re.relates_to.new_content)) } _ => { error!("got new poll start event in a bundled edit");