events: Don't require threads to contain m.in_reply_to

This commit is contained in:
Jonas Platte 2023-01-18 09:38:37 +01:00 committed by Jonas Platte
parent 145356217d
commit 11d5020565
6 changed files with 39 additions and 17 deletions

View File

@ -188,7 +188,7 @@ pub struct Thread {
/// If this event is not a reply, this is used as a fallback mechanism for clients that do not /// If this event is not a reply, this is used as a fallback mechanism for clients that do not
/// support threads. This should point to the latest message-like event in the thread and /// support threads. This should point to the latest message-like event in the thread and
/// `is_falling_back` must be set to `true`. /// `is_falling_back` must be set to `true`.
pub in_reply_to: InReplyTo, pub in_reply_to: Option<InReplyTo>,
/// Whether the `m.in_reply_to` field is a fallback for older clients or a genuine reply in a /// Whether the `m.in_reply_to` field is a fallback for older clients or a genuine reply in a
/// thread. /// thread.
@ -199,13 +199,17 @@ impl Thread {
/// Convenience method to create a regular `Thread` with the given event ID and latest /// Convenience method to create a regular `Thread` with the given event ID and latest
/// message-like event ID. /// message-like event ID.
pub fn plain(event_id: OwnedEventId, latest_event_id: OwnedEventId) -> Self { pub fn plain(event_id: OwnedEventId, latest_event_id: OwnedEventId) -> Self {
Self { event_id, in_reply_to: InReplyTo::new(latest_event_id), is_falling_back: true } Self { event_id, in_reply_to: Some(InReplyTo::new(latest_event_id)), is_falling_back: true }
} }
/// Convenience method to create a reply `Thread` with the given event ID and replied-to event /// Convenience method to create a reply `Thread` with the given event ID and replied-to event
/// ID. /// ID.
pub fn reply(event_id: OwnedEventId, reply_to_event_id: OwnedEventId) -> Self { pub fn reply(event_id: OwnedEventId, reply_to_event_id: OwnedEventId) -> Self {
Self { event_id, in_reply_to: InReplyTo::new(reply_to_event_id), is_falling_back: false } Self {
event_id,
in_reply_to: Some(InReplyTo::new(reply_to_event_id)),
is_falling_back: false,
}
} }
} }

View File

@ -16,10 +16,7 @@ where
| RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr { event_id, is_falling_back }), | RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr { event_id, is_falling_back }),
) = ev.relates_to.relation ) = ev.relates_to.relation
{ {
let in_reply_to = ev let in_reply_to = ev.relates_to.in_reply_to;
.relates_to
.in_reply_to
.ok_or_else(|| serde::de::Error::missing_field("m.in_reply_to"))?;
return Ok(Some(Relation::Thread(Thread { event_id, in_reply_to, is_falling_back }))); return Ok(Some(Relation::Thread(Thread { event_id, in_reply_to, is_falling_back })));
} }
let rel = if let Some(in_reply_to) = ev.relates_to.in_reply_to { let rel = if let Some(in_reply_to) = ev.relates_to.in_reply_to {
@ -69,7 +66,7 @@ impl Serialize for Relation {
} }
Relation::Thread(Thread { event_id, in_reply_to, is_falling_back }) => { Relation::Thread(Thread { event_id, in_reply_to, is_falling_back }) => {
RelatesToJsonRepr { RelatesToJsonRepr {
in_reply_to: Some(in_reply_to.clone()), in_reply_to: in_reply_to.clone(),
relation: Some(RelationJsonRepr::ThreadStable(ThreadStableJsonRepr { relation: Some(RelationJsonRepr::ThreadStable(ThreadStableJsonRepr {
event_id: event_id.clone(), event_id: event_id.clone(),
is_falling_back: *is_falling_back, is_falling_back: *is_falling_back,

View File

@ -213,7 +213,7 @@ impl RoomMessageEventContent {
self.relates_to = Some(Relation::Thread(Thread { self.relates_to = Some(Relation::Thread(Thread {
event_id: thread_root, event_id: thread_root,
in_reply_to: InReplyTo { event_id: previous_message.event_id.clone() }, in_reply_to: Some(InReplyTo { event_id: previous_message.event_id.clone() }),
is_falling_back: is_reply == ReplyWithinThread::No, is_falling_back: is_reply == ReplyWithinThread::No,
})); }));

View File

@ -32,10 +32,7 @@ where
| RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr { event_id, is_falling_back }), | RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr { event_id, is_falling_back }),
) = ev.relates_to.relation ) = ev.relates_to.relation
{ {
let in_reply_to = ev let in_reply_to = ev.relates_to.in_reply_to;
.relates_to
.in_reply_to
.ok_or_else(|| serde::de::Error::missing_field("m.in_reply_to"))?;
return Ok(Some(Relation::Thread(Thread { event_id, in_reply_to, is_falling_back }))); return Ok(Some(Relation::Thread(Thread { event_id, in_reply_to, is_falling_back })));
} }
@ -92,7 +89,7 @@ where
} }
Relation::Thread(Thread { event_id, in_reply_to, is_falling_back }) => { Relation::Thread(Thread { event_id, in_reply_to, is_falling_back }) => {
EventWithRelatesToJsonRepr::new(RelatesToJsonRepr { EventWithRelatesToJsonRepr::new(RelatesToJsonRepr {
in_reply_to: Some(in_reply_to.clone()), in_reply_to: in_reply_to.clone(),
relation: Some(RelationJsonRepr::ThreadStable(ThreadStableJsonRepr { relation: Some(RelationJsonRepr::ThreadStable(ThreadStableJsonRepr {
event_id: event_id.clone(), event_id: event_id.clone(),
is_falling_back: *is_falling_back, is_falling_back: *is_falling_back,

View File

@ -381,7 +381,7 @@ fn content_thread_deserialization() {
Some(Relation::Thread(thread)) => thread Some(Relation::Thread(thread)) => thread
); );
assert_eq!(thread.event_id, "$thread_root"); assert_eq!(thread.event_id, "$thread_root");
assert_eq!(thread.in_reply_to.event_id, "$prev_event"); assert_eq!(thread.in_reply_to.unwrap().event_id, "$prev_event");
assert!(!thread.is_falling_back); assert!(!thread.is_falling_back);
} }

View File

@ -174,6 +174,30 @@ fn thread_reply_serialize() {
#[test] #[test]
fn thread_stable_deserialize() { fn thread_stable_deserialize() {
let json = json!({
"msgtype": "m.text",
"body": "<text msg>",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$1598361704261elfgc",
},
});
let thread = assert_matches!(
from_json_value::<RoomMessageEventContent>(json),
Ok(RoomMessageEventContent {
msgtype: MessageType::Text(_),
relates_to: Some(Relation::Thread(thread)),
..
}) => thread
);
assert_eq!(thread.event_id, "$1598361704261elfgc");
assert_matches!(thread.in_reply_to, None);
assert!(!thread.is_falling_back);
}
#[test]
fn thread_stable_reply_deserialize() {
let json = json!({ let json = json!({
"msgtype": "m.text", "msgtype": "m.text",
"body": "<text msg>", "body": "<text msg>",
@ -195,7 +219,7 @@ fn thread_stable_deserialize() {
}) => thread }) => thread
); );
assert_eq!(thread.event_id, "$1598361704261elfgc"); assert_eq!(thread.event_id, "$1598361704261elfgc");
assert_eq!(thread.in_reply_to.event_id, "$latesteventid"); assert_eq!(thread.in_reply_to.unwrap().event_id, "$latesteventid");
assert!(!thread.is_falling_back); assert!(!thread.is_falling_back);
} }
@ -222,6 +246,6 @@ fn thread_unstable_deserialize() {
}) => thread }) => thread
); );
assert_eq!(thread.event_id, "$1598361704261elfgc"); assert_eq!(thread.event_id, "$1598361704261elfgc");
assert_eq!(thread.in_reply_to.event_id, "$latesteventid"); assert_eq!(thread.in_reply_to.unwrap().event_id, "$latesteventid");
assert!(!thread.is_falling_back); assert!(!thread.is_falling_back);
} }