Skip to content

Commit

Permalink
refactor(timeline): factor out in-reply-to updates
Browse files Browse the repository at this point in the history
  • Loading branch information
bnjbvr committed Nov 4, 2024
1 parent 590c2dd commit 90d6a37
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 73 deletions.
96 changes: 37 additions & 59 deletions crates/matrix-sdk-ui/src/timeline/event_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,25 +547,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
let internal_id = item.internal_id.to_owned();

// Update all events that replied to this message with the edited content.
self.items.for_each(|mut entry| {
let Some(event_item) = entry.as_event() else { return };
let Some(message) = event_item.content.as_message() else { return };
let Some(in_reply_to) = message.in_reply_to() else { return };
if replacement.event_id == in_reply_to.event_id {
trace!(reply_event_id = ?event_item.identifier(), "Updating response to edited event");
let in_reply_to = InReplyToDetails {
event_id: in_reply_to.event_id.clone(),
event: TimelineDetails::Ready(Box::new(
RepliedToEvent::from_timeline_item(&new_item),
)),
};
let new_reply_content =
TimelineItemContent::Message(message.with_in_reply_to(in_reply_to));
let new_reply_item =
entry.with_kind(event_item.with_content(new_reply_content, None));
ObservableVectorTransactionEntry::set(&mut entry, new_reply_item);
}
});
Self::maybe_update_responses(self.items, &replacement.event_id, &new_item);

// Update the event itself.
self.items.set(item_pos, TimelineItem::new(new_item, internal_id));
Expand Down Expand Up @@ -945,7 +927,13 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
debug!("event item is already redacted");
} else {
let new_item = item.redact(&self.meta.room_version);
self.items.set(idx, TimelineItem::new(new_item, item.internal_id.to_owned()));
let internal_id = item.internal_id.to_owned();

// Look for any timeline event that's a reply to the redacted event, and redact
// the replied-to event there as well.
Self::maybe_update_responses(self.items, &redacted, &new_item);

self.items.set(idx, TimelineItem::new(new_item, internal_id));
self.result.items_updated += 1;
}
} else {
Expand All @@ -954,26 +942,6 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
} else {
debug!("Timeline item not found, discarding redaction");
};

// Look for any timeline event that's a reply to the redacted event, and redact
// the replied-to event there as well.
self.items.for_each(|mut entry| {
let Some(event_item) = entry.as_event() else { return };
let Some(message) = event_item.content.as_message() else { return };
let Some(in_reply_to) = message.in_reply_to() else { return };
let TimelineDetails::Ready(replied_to_event) = &in_reply_to.event else { return };
if redacted == in_reply_to.event_id {
let replied_to_event = replied_to_event.redact(&self.meta.room_version);
let in_reply_to = InReplyToDetails {
event_id: in_reply_to.event_id.clone(),
event: TimelineDetails::Ready(Box::new(replied_to_event)),
};
let content = TimelineItemContent::Message(message.with_in_reply_to(in_reply_to));
let new_item = entry.with_kind(event_item.with_content(content, None));

ObservableVectorTransactionEntry::set(&mut entry, new_item);
}
});
}

/// Attempts to redact a reaction, local or remote.
Expand Down Expand Up @@ -1198,25 +1166,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
trace!("Updating timeline item at position {idx}");

// Update all events that replied to this previously encrypted message.
self.items.for_each(|mut entry| {
let Some(event_item) = entry.as_event() else { return };
let Some(message) = event_item.content.as_message() else { return };
let Some(in_reply_to) = message.in_reply_to() else { return };
if *decrypted_event_id == in_reply_to.event_id {
trace!(reply_event_id = ?event_item.identifier(), "Updating response to edited event");
let in_reply_to = InReplyToDetails {
event_id: in_reply_to.event_id.clone(),
event: TimelineDetails::Ready(Box::new(
RepliedToEvent::from_timeline_item(&item),
)),
};
let new_reply_content =
TimelineItemContent::Message(message.with_in_reply_to(in_reply_to));
let new_reply_item =
entry.with_kind(event_item.with_content(new_reply_content, None));
ObservableVectorTransactionEntry::set(&mut entry, new_reply_item);
}
});
Self::maybe_update_responses(self.items, decrypted_event_id, &item);

let internal_id = self.items[*idx].internal_id.clone();
self.items.set(*idx, TimelineItem::new(item, internal_id));
Expand All @@ -1229,6 +1179,34 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
}
}

/// After updating the timeline item `new_item` which id is
/// `target_event_id`, update other items that are responses to this item.
fn maybe_update_responses(
items: &mut ObservableVectorTransaction<'_, Arc<TimelineItem>>,
target_event_id: &EventId,
new_item: &EventTimelineItem,
) {
items.for_each(|mut entry| {
let Some(event_item) = entry.as_event() else { return };
let Some(message) = event_item.content.as_message() else { return };
let Some(in_reply_to) = message.in_reply_to() else { return };
if target_event_id == in_reply_to.event_id {
trace!(reply_event_id = ?event_item.identifier(), "Updating response to edited event");
let in_reply_to = InReplyToDetails {
event_id: in_reply_to.event_id.clone(),
event: TimelineDetails::Ready(Box::new(
RepliedToEvent::from_timeline_item(new_item),
)),
};
let new_reply_content =
TimelineItemContent::Message(message.with_in_reply_to(in_reply_to));
let new_reply_item =
entry.with_kind(event_item.with_content(new_reply_content, None));
ObservableVectorTransactionEntry::set(&mut entry, new_reply_item);
}
});
}

fn pending_reactions(
&mut self,
content: &TimelineItemContent,
Expand Down
10 changes: 1 addition & 9 deletions crates/matrix-sdk-ui/src/timeline/event_item/content/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use ruma::{
},
html::RemoveReplyFallback,
serde::Raw,
OwnedEventId, OwnedUserId, RoomVersionId, UserId,
OwnedEventId, OwnedUserId, UserId,
};
use tracing::{error, trace};

Expand Down Expand Up @@ -337,14 +337,6 @@ impl RepliedToEvent {
}
}

pub(in crate::timeline) fn redact(&self, room_version: &RoomVersionId) -> Self {
Self {
content: self.content.redact(room_version),
sender: self.sender.clone(),
sender_profile: self.sender_profile.clone(),
}
}

/// Try to create a `RepliedToEvent` from a `TimelineEvent` by providing the
/// room.
pub async fn try_from_timeline_event_for_room(
Expand Down
10 changes: 5 additions & 5 deletions crates/matrix-sdk-ui/src/timeline/tests/redaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,17 @@ async fn test_redact_replied_to_event() {

timeline.handle_live_event(f.redaction(first_item.event_id().unwrap()).sender(&ALICE)).await;

let first_item_again =
assert_next_matches!(stream, VectorDiff::Set { index: 0, value } => value);
assert_matches!(first_item_again.content(), TimelineItemContent::RedactedMessage);
assert_matches!(first_item_again.original_json(), None);

let second_item_again =
assert_next_matches!(stream, VectorDiff::Set { index: 1, value } => value);
let message = second_item_again.content().as_message().unwrap();
let in_reply_to = message.in_reply_to().unwrap();
assert_let!(TimelineDetails::Ready(replied_to_event) = &in_reply_to.event);
assert_matches!(replied_to_event.content(), TimelineItemContent::RedactedMessage);

let first_item_again =
assert_next_matches!(stream, VectorDiff::Set { index: 0, value } => value);
assert_matches!(first_item_again.content(), TimelineItemContent::RedactedMessage);
assert_matches!(first_item_again.original_json(), None);
}

#[async_test]
Expand Down

0 comments on commit 90d6a37

Please sign in to comment.