Skip to content

Commit 7c7cbb2

Browse files
committed
feat(sdk,ui): Support edits as LatestEventValue.
This patch supports any edits at a possible `LatestEventValue` candidate.
1 parent 32b4bbc commit 7c7cbb2

File tree

2 files changed

+91
-24
lines changed

2 files changed

+91
-24
lines changed

crates/matrix-sdk-ui/src/timeline/latest_event.rs

Lines changed: 89 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,17 @@
1414

1515
use matrix_sdk::{Client, Room, latest_events::LocalLatestEventValue};
1616
use matrix_sdk_base::latest_event::LatestEventValue as BaseLatestEventValue;
17-
use ruma::{MilliSecondsSinceUnixEpoch, OwnedUserId};
17+
use ruma::{
18+
MilliSecondsSinceUnixEpoch, OwnedUserId,
19+
events::{
20+
AnyMessageLikeEventContent, relation::Replacement, room::message::RoomMessageEventContent,
21+
},
22+
};
1823
use tracing::trace;
1924

2025
use crate::timeline::{
21-
Profile, TimelineDetails, TimelineItemContent, event_handler::TimelineAction,
26+
Profile, TimelineDetails, TimelineItemContent,
27+
event_handler::{HandleAggregationKind, TimelineAction},
2228
traits::RoomDataProvider,
2329
};
2430

@@ -92,7 +98,7 @@ impl LatestEventValue {
9298
.map(TimelineDetails::Ready)
9399
.unwrap_or(TimelineDetails::Unavailable);
94100

95-
let Some(TimelineAction::AddItem { content }) = TimelineAction::from_event(
101+
match TimelineAction::from_event(
96102
any_sync_timeline_event,
97103
&raw_any_sync_timeline_event,
98104
room,
@@ -102,11 +108,50 @@ impl LatestEventValue {
102108
None,
103109
)
104110
.await
105-
else {
106-
return Self::None;
107-
};
111+
{
112+
// Easy path: no aggregation, direct event.
113+
Some(TimelineAction::AddItem { content }) => {
114+
Self::Remote { timestamp, sender, is_own, profile, content }
115+
}
108116

109-
Self::Remote { timestamp, sender, is_own, profile, content }
117+
// Aggregated event.
118+
//
119+
// Only edits are supported for the moment.
120+
Some(TimelineAction::HandleAggregation {
121+
kind:
122+
HandleAggregationKind::Edit { replacement: Replacement { new_content, .. } },
123+
..
124+
}) => {
125+
// Let's map the edit into a regular message.
126+
match TimelineAction::from_content(
127+
AnyMessageLikeEventContent::RoomMessage(RoomMessageEventContent::new(
128+
new_content.msgtype,
129+
)),
130+
// We don't care about the `InReplyToDetails` in the context of a
131+
// `LatestEventValue`.
132+
None,
133+
// We don't care about the thread information in the context of a
134+
// `LatestEventValue`.
135+
None,
136+
None,
137+
) {
138+
// The expected case.
139+
TimelineAction::AddItem { content } => {
140+
Self::Remote { timestamp, sender, is_own, profile, content }
141+
}
142+
143+
// Supposedly unreachable, but let's pretend there is no
144+
// `LatestEventValue` if it happens.
145+
_ => {
146+
trace!("latest event was an edit that failed to be un-aggregated");
147+
148+
Self::None
149+
}
150+
}
151+
}
152+
153+
_ => Self::None,
154+
}
110155
}
111156
BaseLatestEventValue::LocalIsSending(LocalLatestEventValue {
112157
timestamp,
@@ -209,7 +254,9 @@ mod tests {
209254
assert_matches!(profile, TimelineDetails::Unavailable);
210255
assert_matches!(
211256
content,
212-
TimelineItemContent::MsgLike(MsgLikeContent { kind: MsgLikeKind::Message(_), .. })
257+
TimelineItemContent::MsgLike(MsgLikeContent { kind: MsgLikeKind::Message(message), .. }) => {
258+
assert_eq!(message.body(), "raclette");
259+
}
213260
);
214261
})
215262
}
@@ -275,4 +322,38 @@ mod tests {
275322
assert!(is_sending.not());
276323
})
277324
}
325+
326+
#[async_test]
327+
async fn test_remote_edit() {
328+
let server = MatrixMockServer::new().await;
329+
let client = server.client_builder().build().await;
330+
let room = server.sync_room(&client, JoinedRoomBuilder::new(room_id!("!r0"))).await;
331+
let sender = user_id!("@mnt_io:matrix.org");
332+
let event_factory = EventFactory::new();
333+
334+
let base_value = BaseLatestEventValue::Remote(RemoteLatestEventValue::from_plaintext(
335+
event_factory
336+
.server_ts(42)
337+
.sender(sender)
338+
.text_msg("bonjour")
339+
.event_id(event_id!("$ev1"))
340+
.edit(event_id!("$ev0"), RoomMessageEventContent::text_plain("fondue").into())
341+
.into_raw_sync(),
342+
));
343+
let value =
344+
LatestEventValue::from_base_latest_event_value(base_value, &room, &client).await;
345+
346+
assert_matches!(value, LatestEventValue::Remote { timestamp, sender: received_sender, is_own, profile, content } => {
347+
assert_eq!(u64::from(timestamp.get()), 42u64);
348+
assert_eq!(received_sender, sender);
349+
assert!(is_own.not());
350+
assert_matches!(profile, TimelineDetails::Unavailable);
351+
assert_matches!(
352+
content,
353+
TimelineItemContent::MsgLike(MsgLikeContent { kind: MsgLikeKind::Message(message), .. }) => {
354+
assert_eq!(message.body(), "fondue");
355+
}
356+
);
357+
})
358+
}
278359
}

crates/matrix-sdk/src/latest_events/latest_event.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use ruma::{
2929
EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, TransactionId, UserId,
3030
events::{
3131
AnyMessageLikeEventContent, AnySyncStateEvent, AnySyncTimelineEvent, SyncStateEvent,
32-
relation::RelationType,
3332
room::{member::MembershipState, message::MessageType, power_levels::RoomPowerLevels},
3433
},
3534
};
@@ -977,20 +976,7 @@ fn filter_any_message_like_event_content(event: AnyMessageLikeEventContent) -> b
977976
return false;
978977
}
979978

980-
// Check if this is a replacement for another message. If it is, ignore
981-
// it.
982-
//
983-
// TODO: if we want to support something like
984-
// `LatestEventContent::EditedRoomMessage`, it's here :-].
985-
let is_replacement = message.relates_to.as_ref().is_some_and(|relates_to| {
986-
if let Some(relation_type) = relates_to.rel_type() {
987-
relation_type == RelationType::Replacement
988-
} else {
989-
false
990-
}
991-
});
992-
993-
!is_replacement
979+
true
994980
}
995981

996982
AnyMessageLikeEventContent::UnstablePollStart(_)
@@ -1124,7 +1110,7 @@ mod tests_latest_event_content {
11241110
.edit(event_id!("$ev0"), RoomMessageEventContent::text_plain("hello").into())
11251111
.into_event()
11261112
}
1127-
is not a candidate
1113+
is a candidate
11281114
);
11291115
}
11301116

0 commit comments

Comments
 (0)