diff --git a/crates/ruma-common/CHANGELOG.md b/crates/ruma-common/CHANGELOG.md index e255e355..0d1ae4ce 100644 --- a/crates/ruma-common/CHANGELOG.md +++ b/crates/ruma-common/CHANGELOG.md @@ -19,6 +19,9 @@ Breaking changes: * Change `events::room` media types to use `Duration` where applicable * Move `prev_content` into `unsigned` * Rename `identifiers::Error` to `IdParseError` +* Fix the `RoomMessageEventContent::*_reply_plain` methods that now return a + message with a `formatted_body`, according to the spec. Therefore, they only + accept `OriginalRoomMessageEvent`s like their HTML counterparts. Improvements: diff --git a/crates/ruma-common/src/events/room/message.rs b/crates/ruma-common/src/events/room/message.rs index 43449c2d..38cf839f 100644 --- a/crates/ruma-common/src/events/room/message.rs +++ b/crates/ruma-common/src/events/room/message.rs @@ -42,8 +42,6 @@ pub mod feedback; mod relation_serde; mod reply; -pub use reply::ReplyBaseEvent; - /// The content of an `m.room.message` event. /// /// This event is used when sending messages in a room. @@ -105,28 +103,34 @@ impl RoomMessageEventContent { } /// Creates a plain text reply to a message. + /// + /// This constructor requires an [`OriginalRoomMessageEvent`] since it creates a permalink to + /// the previous message, for which the room ID is required. If you want to reply to an + /// [`OriginalSyncRoomMessageEvent`], you have to convert it first by calling + /// [`.into_full_event()`][crate::events::OriginalSyncMessageLikeEvent::into_full_event]. pub fn text_reply_plain( reply: impl fmt::Display, - original_message: &impl ReplyBaseEvent, + original_message: &OriginalRoomMessageEvent, ) -> Self { let quoted = reply::get_plain_quote_fallback(original_message); + let quoted_html = reply::get_html_quote_fallback(original_message); let body = format!("{}\n\n{}", quoted, reply); + let html_body = format!("{}\n\n{}", quoted_html, reply); Self { relates_to: Some(Relation::Reply { - in_reply_to: InReplyTo { event_id: original_message.event_id().to_owned() }, + in_reply_to: InReplyTo { event_id: original_message.event_id.to_owned() }, }), - ..Self::text_plain(body) + ..Self::text_html(body, html_body) } } /// Creates a html text reply to a message. /// - /// Different from `text_reply_plain`, this constructor requires specifically a - /// [`RoomMessageEvent`] since it creates a permalink to the previous message, for which the - /// room ID is required. If you want to reply to a [`SyncRoomMessageEvent`], you have to convert - /// it first by calling + /// This constructor requires an [`OriginalRoomMessageEvent`] since it creates a permalink to + /// the previous message, for which the room ID is required. If you want to reply to an + /// [`OriginalSyncRoomMessageEvent`], you have to convert it first by calling /// [`.into_full_event()`][crate::events::OriginalSyncMessageLikeEvent::into_full_event]. pub fn text_reply_html( reply: impl fmt::Display, @@ -148,27 +152,34 @@ impl RoomMessageEventContent { } /// Creates a plain text notice reply to a message. + /// + /// This constructor requires an [`OriginalRoomMessageEvent`] since it creates a permalink to + /// the previous message, for which the room ID is required. If you want to reply to an + /// [`OriginalSyncRoomMessageEvent`], you have to convert it first by calling + /// [`.into_full_event()`][crate::events::OriginalSyncMessageLikeEvent::into_full_event]. pub fn notice_reply_plain( reply: impl fmt::Display, - original_message: &impl ReplyBaseEvent, + original_message: &OriginalRoomMessageEvent, ) -> Self { let quoted = reply::get_plain_quote_fallback(original_message); + let quoted_html = reply::get_html_quote_fallback(original_message); let body = format!("{}\n\n{}", quoted, reply); + let html_body = format!("{}\n\n{}", quoted_html, reply); + Self { relates_to: Some(Relation::Reply { - in_reply_to: InReplyTo { event_id: original_message.event_id().to_owned() }, + in_reply_to: InReplyTo { event_id: original_message.event_id.to_owned() }, }), - ..Self::notice_plain(body) + ..Self::notice_html(body, html_body) } } /// Creates a html text notice reply to a message. /// - /// Different from `notice_reply_plain`, this constructor requires specifically a - /// [`RoomMessageEvent`] since it creates a permalink to the previous message, for which the - /// room ID is required. If you want to reply to a [`SyncRoomMessageEvent`], you have to convert - /// it first by calling + /// This constructor requires an [`OriginalRoomMessageEvent`] since it creates a permalink to + /// the previous message, for which the room ID is required. If you want to reply to an + /// [`OriginalSyncRoomMessageEvent`], you have to convert it first by calling /// [`.into_full_event()`][crate::events::OriginalSyncMessageLikeEvent::into_full_event]. pub fn notice_reply_html( reply: impl fmt::Display, diff --git a/crates/ruma-common/src/events/room/message/reply.rs b/crates/ruma-common/src/events/room/message/reply.rs index c6fcd30c..84f41885 100644 --- a/crates/ruma-common/src/events/room/message/reply.rs +++ b/crates/ruma-common/src/events/room/message/reply.rs @@ -1,59 +1,11 @@ use indoc::formatdoc; -use super::{ - FormattedBody, MessageType, OriginalRoomMessageEvent, OriginalSyncRoomMessageEvent, - RoomMessageEventContent, -}; -use crate::{EventId, UserId}; +use super::{FormattedBody, MessageType, OriginalRoomMessageEvent}; -/// An event that can be replied to. -/// -/// This trait only exists to allow the plain-text `reply` constructors on `MessageLikeEventContent` -/// to use either a [`RoomMessageEvent`] or a [`SyncRoomMessageEvent`] as the event being replied -/// to. -pub trait ReplyBaseEvent { - #[doc(hidden)] - fn event_id(&self) -> &EventId; +pub fn get_plain_quote_fallback(original_message: &OriginalRoomMessageEvent) -> String { + let sender = &original_message.sender; - #[doc(hidden)] - fn sender(&self) -> &UserId; - - #[doc(hidden)] - fn content(&self) -> &RoomMessageEventContent; -} - -impl ReplyBaseEvent for OriginalRoomMessageEvent { - fn event_id(&self) -> &EventId { - &self.event_id - } - - fn sender(&self) -> &UserId { - &self.sender - } - - fn content(&self) -> &RoomMessageEventContent { - &self.content - } -} - -impl ReplyBaseEvent for OriginalSyncRoomMessageEvent { - fn event_id(&self) -> &EventId { - &self.event_id - } - - fn sender(&self) -> &UserId { - &self.sender - } - - fn content(&self) -> &RoomMessageEventContent { - &self.content - } -} - -pub fn get_plain_quote_fallback(original_message: &impl ReplyBaseEvent) -> String { - let sender = original_message.sender(); - - match &original_message.content().msgtype { + match &original_message.content.msgtype { MessageType::Audio(_) => { format!("> <{}> sent an audio file.", sender) } @@ -301,10 +253,12 @@ fn formatted_or_plain_body<'a>(formatted: &'a Option, body: &'a s #[cfg(test)] mod tests { use crate::{ - event_id, events::MessageLikeUnsigned, room_id, user_id, MilliSecondsSinceUnixEpoch, + event_id, + events::{room::message::RoomMessageEventContent, MessageLikeUnsigned}, + room_id, user_id, MilliSecondsSinceUnixEpoch, }; - use super::{OriginalRoomMessageEvent, RoomMessageEventContent}; + use super::OriginalRoomMessageEvent; #[test] fn plain_quote_fallback_multiline() {