events: Stabilize current support for threads

This commit is contained in:
Kévin Commaille 2022-09-30 17:40:08 +02:00 committed by Kévin Commaille
parent 279c9d0fa6
commit 003f0abebf
9 changed files with 35 additions and 73 deletions

View File

@ -13,6 +13,8 @@ Improvements:
* Stabilize default room server ACL push rule
* Stabilize `room_types` in `directory::Filter` and `room_type` in `directory::PublicRoomsChunk`
* Stabilize support for private read receipts
* Add stable support for threads
* Move `Relation::Thread` and associated types and methods out of `unstable-msc3440`
# 0.10.3

View File

@ -38,7 +38,6 @@ unstable-msc2870 = []
unstable-msc3245 = ["unstable-msc3246"]
unstable-msc3246 = ["unstable-msc3551", "dep:thiserror"]
unstable-msc3381 = ["unstable-msc1767"]
unstable-msc3440 = []
unstable-msc3488 = ["unstable-msc1767"]
unstable-msc3551 = ["unstable-msc1767"]
unstable-msc3552 = ["unstable-msc3551"]

View File

@ -4,17 +4,16 @@
use std::fmt::Debug;
#[cfg(any(feature = "unstable-msc2677", feature = "unstable-msc3440"))]
use js_int::UInt;
use serde::{Deserialize, Serialize};
#[cfg(feature = "unstable-msc3440")]
use super::AnySyncMessageLikeEvent;
#[cfg(feature = "unstable-msc3440")]
use crate::serde::Raw;
use super::AnyMessageLikeEvent;
#[cfg(any(feature = "unstable-msc2676", feature = "unstable-msc2677"))]
use crate::MilliSecondsSinceUnixEpoch;
use crate::{serde::StringEnum, PrivOwnedStr};
use crate::{
serde::{Raw, StringEnum},
PrivOwnedStr,
};
#[cfg(feature = "unstable-msc2676")]
use crate::{OwnedEventId, OwnedUserId};
@ -112,11 +111,10 @@ impl BundledReplacement {
/// A bundled thread.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg(feature = "unstable-msc3440")]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct BundledThread {
/// The latest event in the thread.
pub latest_event: Box<Raw<AnySyncMessageLikeEvent>>,
pub latest_event: Box<Raw<AnyMessageLikeEvent>>,
/// The number of events in the thread.
pub count: UInt,
@ -125,11 +123,10 @@ pub struct BundledThread {
pub current_user_participated: bool,
}
#[cfg(feature = "unstable-msc3440")]
impl BundledThread {
/// Creates a new `BundledThread` with the given event, count and user participated flag.
pub fn new(
latest_event: Box<Raw<AnySyncMessageLikeEvent>>,
latest_event: Box<Raw<AnyMessageLikeEvent>>,
count: UInt,
current_user_participated: bool,
) -> Self {
@ -154,8 +151,7 @@ pub struct Relations {
pub replace: Option<BundledReplacement>,
/// Thread relation.
#[cfg(feature = "unstable-msc3440")]
#[serde(rename = "io.element.thread", alias = "m.thread")]
#[serde(rename = "m.thread")]
pub thread: Option<BundledThread>,
}
@ -182,8 +178,7 @@ pub enum RelationType {
Replacement,
/// `m.thread`, a participant to a thread.
#[cfg(feature = "unstable-msc3440")]
#[ruma_enum(rename = "io.element.thread", alias = "m.thread")]
#[ruma_enum(rename = "m.thread")]
Thread,
#[doc(hidden)]

View File

@ -102,7 +102,6 @@ pub enum Relation {
Annotation(Annotation),
/// An event that belongs to a thread.
#[cfg(feature = "unstable-msc3440")]
Thread(Thread),
#[doc(hidden)]
@ -117,7 +116,6 @@ impl From<message::Relation> for Relation {
message::Relation::Replacement(re) => {
Self::Replacement(Replacement { event_id: re.event_id })
}
#[cfg(feature = "unstable-msc3440")]
message::Relation::Thread(t) => Self::Thread(Thread {
event_id: t.event_id,
in_reply_to: t.in_reply_to,
@ -178,7 +176,6 @@ impl Annotation {
/// A thread relation for an event.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg(feature = "unstable-msc3440")]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct Thread {
/// The ID of the root message in the thread.
@ -199,7 +196,6 @@ pub struct Thread {
pub is_falling_back: bool,
}
#[cfg(feature = "unstable-msc3440")]
impl Thread {
/// Convenience method to create a regular `Thread` with the given event ID and latest
/// message-like event ID.

View File

@ -4,10 +4,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::Annotation;
#[cfg(feature = "unstable-msc2676")]
use super::Replacement;
#[cfg(feature = "unstable-msc3440")]
use super::Thread;
use super::{InReplyTo, Reference, Relation};
#[cfg(feature = "unstable-msc3440")]
use super::{InReplyTo, Reference, Relation, Thread};
use crate::OwnedEventId;
impl<'de> Deserialize<'de> for Relation {
@ -17,7 +14,6 @@ impl<'de> Deserialize<'de> for Relation {
{
let ev = EventWithRelatesToJsonRepr::deserialize(deserializer)?;
#[cfg(feature = "unstable-msc3440")]
if let Some(
RelationJsonRepr::ThreadStable(ThreadStableJsonRepr { event_id, is_falling_back })
| RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr { event_id, is_falling_back }),
@ -40,7 +36,6 @@ impl<'de> Deserialize<'de> for Relation {
RelationJsonRepr::Replacement(Replacement { event_id }) => {
Relation::Replacement(Replacement { event_id })
}
#[cfg(feature = "unstable-msc3440")]
RelationJsonRepr::ThreadStable(_) | RelationJsonRepr::ThreadUnstable(_) => {
unreachable!()
}
@ -80,11 +75,10 @@ impl Serialize for Relation {
Relation::Reply { in_reply_to } => {
RelatesToJsonRepr { in_reply_to: Some(in_reply_to.clone()), ..Default::default() }
}
#[cfg(feature = "unstable-msc3440")]
Relation::Thread(Thread { event_id, in_reply_to, is_falling_back }) => {
RelatesToJsonRepr {
in_reply_to: Some(in_reply_to.clone()),
relation: Some(RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr {
relation: Some(RelationJsonRepr::ThreadStable(ThreadStableJsonRepr {
event_id: event_id.clone(),
is_falling_back: *is_falling_back,
})),
@ -123,7 +117,6 @@ impl RelatesToJsonRepr {
/// A thread relation without the reply fallback, with stable names.
#[derive(Clone, Deserialize, Serialize)]
#[cfg(feature = "unstable-msc3440")]
struct ThreadStableJsonRepr {
/// The ID of the root message in the thread.
pub event_id: OwnedEventId,
@ -136,7 +129,6 @@ struct ThreadStableJsonRepr {
/// A thread relation without the reply fallback, with unstable names.
#[derive(Clone, Deserialize, Serialize)]
#[cfg(feature = "unstable-msc3440")]
struct ThreadUnstableJsonRepr {
/// The ID of the root message in the thread.
pub event_id: OwnedEventId,
@ -170,12 +162,10 @@ enum RelationJsonRepr {
Replacement(Replacement),
/// An event that belongs to a thread, with stable names.
#[cfg(feature = "unstable-msc3440")]
#[serde(rename = "m.thread")]
ThreadStable(ThreadStableJsonRepr),
/// An event that belongs to a thread, with unstable names.
#[cfg(feature = "unstable-msc3440")]
#[serde(rename = "io.element.thread")]
ThreadUnstable(ThreadUnstableJsonRepr),

View File

@ -166,7 +166,6 @@ impl RoomMessageEventContent {
/// If `message` is a text, an emote or a notice message, it is modified to include the rich
/// reply fallback.
#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/rich_reply.md"))]
#[cfg(feature = "unstable-msc3440")]
pub fn reply(
message: MessageType,
original_message: &OriginalRoomMessageEvent,
@ -198,7 +197,7 @@ impl RoomMessageEventContent {
.as_ref()
.filter(|_| forward_thread == ForwardThread::Yes)
{
Relation::Thread(Thread::reply(event_id.clone(), original_message.event_id.clone()))
Relation::Thread(Thread::plain(event_id.clone(), original_message.event_id.clone()))
} else {
Relation::Reply {
in_reply_to: InReplyTo { event_id: original_message.event_id.clone() },
@ -217,17 +216,16 @@ impl RoomMessageEventContent {
/// If `message` is a text, an emote or a notice message, and this is a reply in the thread, it
/// is modified to include the rich reply fallback.
#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/rich_reply.md"))]
#[cfg(feature = "unstable-msc3440")]
pub fn for_thread(
message: MessageType,
previous_message: &OriginalRoomMessageEvent,
is_reply: ReplyInThread,
is_reply: ReplyWithinThread,
) -> Self {
let make_reply = |body, formatted: Option<FormattedBody>| {
reply::plain_and_formatted_reply_body(body, formatted.map(|f| f.body), previous_message)
};
let msgtype = if is_reply == ReplyInThread::Yes {
let msgtype = if is_reply == ReplyWithinThread::Yes {
// If this is a real reply, add the rich reply fallback.
match message {
MessageType::Text(TextMessageEventContent { body, formatted, .. }) => {
@ -261,7 +259,7 @@ impl RoomMessageEventContent {
relates_to: Some(Relation::Thread(Thread {
event_id: thread_root,
in_reply_to: InReplyTo { event_id: previous_message.event_id.clone() },
is_falling_back: is_reply == ReplyInThread::No,
is_falling_back: is_reply == ReplyWithinThread::No,
})),
}
}
@ -314,15 +312,15 @@ impl RoomMessageEventContent {
}
/// Whether or not to forward a [`Relation::Thread`] when sending a reply.
#[cfg(feature = "unstable-msc3440")]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[allow(clippy::exhaustive_enums)]
pub enum ForwardThread {
/// The thread relation in the original message is forwarded if it exists.
///
/// This should be set if your client doesn't support threads (see [MSC3440]).
/// This should be set if your client doesn't render threads (see the [info
/// box for clients which are acutely aware of threads]).
///
/// [MSC3440]: https://github.com/matrix-org/matrix-spec-proposals/pull/3440
/// [info box for clients which are acutely aware of threads]: https://spec.matrix.org/v1.4/client-server-api/#fallback-for-unthreaded-clients
Yes,
/// Create a reply in the main conversation even if the original message is in a thread.
@ -332,20 +330,21 @@ pub enum ForwardThread {
}
/// Whether or not the message is a reply inside a thread.
#[cfg(feature = "unstable-msc3440")]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[allow(clippy::exhaustive_enums)]
pub enum ReplyInThread {
pub enum ReplyWithinThread {
/// This is a reply.
///
/// Create a proper reply _in_ the thread.
/// Create a [reply within the thread].
///
/// [reply within the thread]: https://spec.matrix.org/v1.4/client-server-api/#replies-within-threads
Yes,
/// This is not a reply.
///
/// Create a regular message in the thread, with a reply fallback, according to [MSC3440].
/// Create a regular message in the thread, with a [fallback for unthreaded clients].
///
/// [MSC3440]: https://github.com/matrix-org/matrix-spec-proposals/pull/3440
/// [fallback for unthreaded clients]: https://spec.matrix.org/v1.4/client-server-api/#fallback-for-unthreaded-clients
No,
}
@ -520,7 +519,6 @@ pub enum Relation {
Replacement(Replacement),
/// An event that belongs to a thread.
#[cfg(feature = "unstable-msc3440")]
Thread(Thread),
#[doc(hidden)]
@ -564,7 +562,6 @@ impl Replacement {
/// The content of a thread relation.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg(feature = "unstable-msc3440")]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct Thread {
/// The ID of the root message in the thread.
@ -585,7 +582,6 @@ pub struct Thread {
pub is_falling_back: bool,
}
#[cfg(feature = "unstable-msc3440")]
impl Thread {
/// Convenience method to create a regular `Thread` with the given event ID and latest
/// message-like event ID.

View File

@ -4,10 +4,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::Replacement;
#[cfg(feature = "unstable-msc2676")]
use super::RoomMessageEventContent;
#[cfg(feature = "unstable-msc3440")]
use super::Thread;
use super::{InReplyTo, Relation};
#[cfg(any(feature = "unstable-msc2676", feature = "unstable-msc3440"))]
use super::{InReplyTo, Relation, Thread};
use crate::OwnedEventId;
impl<'de> Deserialize<'de> for Relation {
@ -17,7 +14,6 @@ impl<'de> Deserialize<'de> for Relation {
{
let ev = EventWithRelatesToJsonRepr::deserialize(deserializer)?;
#[cfg(feature = "unstable-msc3440")]
if let Some(
RelationJsonRepr::ThreadStable(ThreadStableJsonRepr { event_id, is_falling_back })
| RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr { event_id, is_falling_back }),
@ -44,7 +40,6 @@ impl<'de> Deserialize<'de> for Relation {
// FIXME: Maybe we should log this, though at this point we don't even have
// access to the rel_type of the unknown relation.
RelationJsonRepr::Unknown => Relation::_Custom,
#[cfg(feature = "unstable-msc3440")]
RelationJsonRepr::ThreadStable(_) | RelationJsonRepr::ThreadUnstable(_) => {
unreachable!()
}
@ -80,11 +75,10 @@ impl Serialize for Relation {
new_content: Some(new_content.clone()),
}
}
#[cfg(feature = "unstable-msc3440")]
Relation::Thread(Thread { event_id, in_reply_to, is_falling_back }) => {
EventWithRelatesToJsonRepr::new(RelatesToJsonRepr {
in_reply_to: Some(in_reply_to.clone()),
relation: Some(RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr {
relation: Some(RelationJsonRepr::ThreadStable(ThreadStableJsonRepr {
event_id: event_id.clone(),
is_falling_back: *is_falling_back,
})),
@ -144,13 +138,11 @@ enum RelationJsonRepr {
#[serde(rename = "m.replace")]
Replacement(ReplacementJsonRepr),
/// An event that belongs to a thread, with unstable names.
#[cfg(feature = "unstable-msc3440")]
/// An event that belongs to a thread, with stable names.
#[serde(rename = "m.thread")]
ThreadStable(ThreadStableJsonRepr),
/// An event that belongs to a thread, with unstable names.
#[cfg(feature = "unstable-msc3440")]
#[serde(rename = "io.element.thread")]
ThreadUnstable(ThreadUnstableJsonRepr),
@ -170,7 +162,6 @@ struct ReplacementJsonRepr {
/// A thread relation without the reply fallback, with stable names.
#[derive(Clone, Deserialize, Serialize)]
#[cfg(feature = "unstable-msc3440")]
struct ThreadStableJsonRepr {
/// The ID of the root message in the thread.
event_id: OwnedEventId,
@ -183,7 +174,6 @@ struct ThreadStableJsonRepr {
/// A thread relation without the reply fallback, with unstable names.
#[derive(Clone, Deserialize, Serialize)]
#[cfg(feature = "unstable-msc3440")]
struct ThreadUnstableJsonRepr {
/// The ID of the root message in the thread.
event_id: OwnedEventId,

View File

@ -149,7 +149,6 @@ fn replacement_deserialize() {
}
#[test]
#[cfg(feature = "unstable-msc3440")]
fn thread_plain_serialize() {
use ruma_common::events::room::message::Thread;
@ -172,12 +171,12 @@ fn thread_plain_serialize() {
"msgtype": "m.text",
"body": "<text msg>",
"m.relates_to": {
"rel_type": "io.element.thread",
"rel_type": "m.thread",
"event_id": "$1598361704261elfgc",
"m.in_reply_to": {
"event_id": "$latesteventid",
},
"io.element.show_reply": true,
"is_falling_back": true,
},
})
);
@ -190,19 +189,18 @@ fn thread_plain_serialize() {
"body": "<text msg>",
"org.matrix.msc1767.text": "<text msg>",
"m.relates_to": {
"rel_type": "io.element.thread",
"rel_type": "m.thread",
"event_id": "$1598361704261elfgc",
"m.in_reply_to": {
"event_id": "$latesteventid",
},
"io.element.show_reply": true,
"is_falling_back": true,
},
})
);
}
#[test]
#[cfg(feature = "unstable-msc3440")]
fn thread_reply_serialize() {
use ruma_common::events::room::message::Thread;
@ -225,7 +223,7 @@ fn thread_reply_serialize() {
"msgtype": "m.text",
"body": "<text msg>",
"m.relates_to": {
"rel_type": "io.element.thread",
"rel_type": "m.thread",
"event_id": "$1598361704261elfgc",
"m.in_reply_to": {
"event_id": "$repliedtoeventid",
@ -242,7 +240,7 @@ fn thread_reply_serialize() {
"body": "<text msg>",
"org.matrix.msc1767.text": "<text msg>",
"m.relates_to": {
"rel_type": "io.element.thread",
"rel_type": "m.thread",
"event_id": "$1598361704261elfgc",
"m.in_reply_to": {
"event_id": "$repliedtoeventid",
@ -253,7 +251,6 @@ fn thread_reply_serialize() {
}
#[test]
#[cfg(feature = "unstable-msc3440")]
fn thread_stable_deserialize() {
let json = json!({
"msgtype": "m.text",
@ -281,7 +278,6 @@ fn thread_stable_deserialize() {
}
#[test]
#[cfg(feature = "unstable-msc3440")]
fn thread_unstable_deserialize() {
let json = json!({
"msgtype": "m.text",

View File

@ -141,7 +141,6 @@ unstable-msc2967 = ["ruma-client-api?/unstable-msc2967"]
unstable-msc3245 = ["ruma-common/unstable-msc3245"]
unstable-msc3246 = ["ruma-common/unstable-msc3246"]
unstable-msc3381 = ["ruma-common/unstable-msc3381"]
unstable-msc3440 = ["ruma-common/unstable-msc3440"]
unstable-msc3488 = [
"ruma-client-api?/unstable-msc3488",
"ruma-common/unstable-msc3488",
@ -179,7 +178,6 @@ __ci = [
"unstable-msc3245",
"unstable-msc3246",
"unstable-msc3381",
"unstable-msc3440",
"unstable-msc3488",
"unstable-msc3551",
"unstable-msc3552",