mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-02-08 14:42:14 -05:00
fix(ui): populate the thread_root and in_reply_to fields for stickers and polls
They have never been set and there was no way of telling if stickers and polls belong on a thread or come in reply of any other message. This patch also exposes methods for setting these relations on the event factory level.
This commit is contained in:
committed by
Stefan Ceriu
parent
69b8878890
commit
da2dda0e45
@@ -31,7 +31,8 @@ use ruma::{
|
||||
receipt::Receipt,
|
||||
relation::Replacement,
|
||||
room::message::{
|
||||
Relation, RoomMessageEventContent, RoomMessageEventContentWithoutRelation,
|
||||
Relation, RelationWithoutReplacement, RoomMessageEventContent,
|
||||
RoomMessageEventContentWithoutRelation,
|
||||
},
|
||||
AnyMessageLikeEventContent, AnySyncMessageLikeEvent, AnySyncStateEvent,
|
||||
AnySyncTimelineEvent, BundledMessageLikeRelations, EventContent, FullStateEventContent,
|
||||
@@ -354,11 +355,44 @@ impl TimelineAction {
|
||||
}
|
||||
|
||||
AnyMessageLikeEventContent::Sticker(content) => {
|
||||
let mut replied_to_event_id = None;
|
||||
let mut thread_root = None;
|
||||
let in_reply_to_details =
|
||||
content.relates_to.as_ref().and_then(|relation| match relation {
|
||||
Relation::Reply { in_reply_to } => {
|
||||
replied_to_event_id = Some(in_reply_to.event_id.clone());
|
||||
Some(InReplyToDetails::new(
|
||||
in_reply_to.event_id.clone(),
|
||||
timeline_items,
|
||||
))
|
||||
}
|
||||
Relation::Thread(thread) => {
|
||||
thread_root = Some(thread.event_id.clone());
|
||||
thread.in_reply_to.as_ref().map(|in_reply_to| {
|
||||
replied_to_event_id = Some(in_reply_to.event_id.clone());
|
||||
InReplyToDetails::new(in_reply_to.event_id.clone(), timeline_items)
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
// If this message is a reply to another message, add an entry in the
|
||||
// inverted mapping.
|
||||
if let Some(event_id) = event_id {
|
||||
if let Some(replied_to_event_id) = replied_to_event_id {
|
||||
// This is a reply! Add an entry.
|
||||
meta.replies
|
||||
.entry(replied_to_event_id)
|
||||
.or_default()
|
||||
.insert(event_id.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
Self::add_item(TimelineItemContent::MsgLike(MsgLikeContent {
|
||||
kind: MsgLikeKind::Sticker(Sticker { content }),
|
||||
reactions: Default::default(),
|
||||
thread_root: None,
|
||||
in_reply_to: None,
|
||||
thread_root,
|
||||
in_reply_to: in_reply_to_details,
|
||||
thread_summary: None,
|
||||
}))
|
||||
}
|
||||
@@ -393,6 +427,39 @@ impl TimelineAction {
|
||||
.or(pending_edit)
|
||||
.unzip();
|
||||
|
||||
let mut replied_to_event_id = None;
|
||||
let mut thread_root = None;
|
||||
let in_reply_to_details =
|
||||
c.relates_to.as_ref().and_then(|relation| match relation {
|
||||
RelationWithoutReplacement::Reply { in_reply_to } => {
|
||||
replied_to_event_id = Some(in_reply_to.event_id.clone());
|
||||
Some(InReplyToDetails::new(
|
||||
in_reply_to.event_id.clone(),
|
||||
timeline_items,
|
||||
))
|
||||
}
|
||||
RelationWithoutReplacement::Thread(thread) => {
|
||||
thread_root = Some(thread.event_id.clone());
|
||||
thread.in_reply_to.as_ref().map(|in_reply_to| {
|
||||
replied_to_event_id = Some(in_reply_to.event_id.clone());
|
||||
InReplyToDetails::new(in_reply_to.event_id.clone(), timeline_items)
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
// If this message is a reply to another message, add an entry in the
|
||||
// inverted mapping.
|
||||
if let Some(event_id) = event_id {
|
||||
if let Some(replied_to_event_id) = replied_to_event_id {
|
||||
// This is a reply! Add an entry.
|
||||
meta.replies
|
||||
.entry(replied_to_event_id)
|
||||
.or_default()
|
||||
.insert(event_id.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
let poll_state = PollState::new(c, edit_content);
|
||||
|
||||
let edit_json = edit_json.flatten();
|
||||
@@ -401,8 +468,8 @@ impl TimelineAction {
|
||||
content: TimelineItemContent::MsgLike(MsgLikeContent {
|
||||
kind: MsgLikeKind::Poll(poll_state),
|
||||
reactions: Default::default(),
|
||||
thread_root: None,
|
||||
in_reply_to: None,
|
||||
thread_root,
|
||||
in_reply_to: in_reply_to_details,
|
||||
thread_summary: None,
|
||||
}),
|
||||
edit_json,
|
||||
|
||||
@@ -22,6 +22,7 @@ use matrix_sdk_test::{
|
||||
async_test, event_factory::PreviousMembership, sync_timeline_event, ALICE, BOB, CAROL,
|
||||
};
|
||||
use ruma::{
|
||||
event_id,
|
||||
events::{
|
||||
receipt::{Receipt, ReceiptThread, ReceiptType},
|
||||
room::{
|
||||
@@ -141,6 +142,13 @@ async fn test_sticker() {
|
||||
"w": 394
|
||||
},
|
||||
"url": "mxc://server.name/JWEIFJgwEIhweiWJE",
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.thread",
|
||||
"event_id": "$thread_root",
|
||||
"m.in_reply_to": {
|
||||
"event_id": "$in_reply_to"
|
||||
}
|
||||
}
|
||||
},
|
||||
"event_id": "$143273582443PhrSn",
|
||||
"origin_server_ts": 143273582,
|
||||
@@ -151,6 +159,11 @@ async fn test_sticker() {
|
||||
|
||||
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
|
||||
assert!(item.content().is_sticker());
|
||||
|
||||
assert_eq!(item.content().thread_root(), Some(event_id!("$thread_root").to_owned()));
|
||||
|
||||
assert_let!(Some(details) = item.content().in_reply_to());
|
||||
assert_eq!(details.event_id, event_id!("$in_reply_to").to_owned())
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use assert_matches2::assert_let;
|
||||
use fakes::poll_a2;
|
||||
use matrix_sdk_test::{async_test, ALICE, BOB};
|
||||
use ruma::{
|
||||
event_id,
|
||||
events::{
|
||||
poll::{
|
||||
unstable_end::UnstablePollEndEventContent,
|
||||
@@ -230,6 +232,28 @@ async fn test_ending_poll_doesnt_clear_latest_json_edit() {
|
||||
assert!(timeline.event_items().await[0].latest_edit_json().is_some());
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_poll_contains_relations() {
|
||||
let timeline = TestTimeline::new();
|
||||
|
||||
let thread_root_id = event_id!("$thread_root");
|
||||
let in_reply_to_id = event_id!("$in_reply_to");
|
||||
|
||||
let poll_start = poll_a2(&timeline.factory)
|
||||
.in_thread(thread_root_id, in_reply_to_id)
|
||||
.sender(&ALICE)
|
||||
.event_id(event_id!("$poll"));
|
||||
|
||||
timeline.handle_live_event(poll_start).await;
|
||||
|
||||
let poll = timeline.event_items().await[0].clone();
|
||||
|
||||
assert_eq!(poll.content().thread_root(), Some(thread_root_id.to_owned()));
|
||||
|
||||
assert_let!(Some(details) = poll.content().in_reply_to());
|
||||
assert_eq!(details.event_id, in_reply_to_id);
|
||||
}
|
||||
|
||||
impl TestTimeline {
|
||||
async fn event_items(&self) -> Vec<EventTimelineItem> {
|
||||
self.controller.items().await.iter().filter_map(|item| item.as_event().cloned()).collect()
|
||||
|
||||
@@ -45,7 +45,8 @@ use ruma::{
|
||||
member::{MembershipState, RoomMemberEventContent},
|
||||
message::{
|
||||
FormattedBody, ImageMessageEventContent, MessageType, Relation,
|
||||
RoomMessageEventContent, RoomMessageEventContentWithoutRelation,
|
||||
RelationWithoutReplacement, RoomMessageEventContent,
|
||||
RoomMessageEventContentWithoutRelation,
|
||||
},
|
||||
name::RoomNameEventContent,
|
||||
power_levels::RoomPowerLevelsEventContent,
|
||||
@@ -360,6 +361,29 @@ impl EventBuilder<RoomMessageEventContent> {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventBuilder<UnstablePollStartEventContent> {
|
||||
/// Adds a reply relation to the current event.
|
||||
pub fn reply_to(mut self, event_id: &EventId) -> Self {
|
||||
if let UnstablePollStartEventContent::New(content) = &mut self.content {
|
||||
content.relates_to = Some(RelationWithoutReplacement::Reply {
|
||||
in_reply_to: InReplyTo::new(event_id.to_owned()),
|
||||
});
|
||||
};
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a thread relation to the root event, setting the reply to
|
||||
/// event id as well.
|
||||
pub fn in_thread(mut self, root: &EventId, reply_to_event_id: &EventId) -> Self {
|
||||
let thread = Thread::reply(root.to_owned(), reply_to_event_id.to_owned());
|
||||
|
||||
if let UnstablePollStartEventContent::New(content) = &mut self.content {
|
||||
content.relates_to = Some(RelationWithoutReplacement::Thread(thread));
|
||||
};
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EventContent> From<EventBuilder<E>> for Raw<AnySyncTimelineEvent>
|
||||
where
|
||||
E::EventType: Serialize,
|
||||
|
||||
Reference in New Issue
Block a user