events: Add method to construct a replacement
This commit is contained in:
parent
764e96a254
commit
a3675e61bf
@ -218,6 +218,81 @@ impl RoomMessageEventContent {
|
||||
self
|
||||
}
|
||||
|
||||
/// Turns `self` into a [replacement] (or edit) for the message with the given event ID.
|
||||
///
|
||||
/// This takes the content and sets it in `m.new_content`, and modifies the `content` to include
|
||||
/// a fallback.
|
||||
///
|
||||
/// If the message that is replaced is a reply to another message, the latter should also be
|
||||
/// provided to be able to generate a rich reply fallback that takes the `body` /
|
||||
/// `formatted_body` (if any) in `self` for the main text and prepends a quoted version of
|
||||
/// `original_message`.
|
||||
#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/rich_reply.md"))]
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `self` has a `formatted_body` with a format other than HTML.
|
||||
///
|
||||
/// [replacement]: https://spec.matrix.org/v1.4/client-server-api/#event-replacements
|
||||
#[track_caller]
|
||||
pub fn make_replacement(
|
||||
mut self,
|
||||
original_message_id: OwnedEventId,
|
||||
replied_to_message: Option<&OriginalRoomMessageEvent>,
|
||||
) -> Self {
|
||||
// Prepare relates_to with the untouched msgtype.
|
||||
let relates_to = Relation::Replacement(Replacement {
|
||||
event_id: original_message_id,
|
||||
new_content: self.msgtype.clone(),
|
||||
});
|
||||
|
||||
let empty_formatted_body = || FormattedBody::html(String::new());
|
||||
|
||||
let (body, formatted) = {
|
||||
match &mut self.msgtype {
|
||||
MessageType::Emote(m) => {
|
||||
(&mut m.body, Some(m.formatted.get_or_insert_with(empty_formatted_body)))
|
||||
}
|
||||
MessageType::Notice(m) => {
|
||||
(&mut m.body, Some(m.formatted.get_or_insert_with(empty_formatted_body)))
|
||||
}
|
||||
MessageType::Text(m) => {
|
||||
(&mut m.body, Some(m.formatted.get_or_insert_with(empty_formatted_body)))
|
||||
}
|
||||
MessageType::Audio(m) => (&mut m.body, None),
|
||||
MessageType::File(m) => (&mut m.body, None),
|
||||
MessageType::Image(m) => (&mut m.body, None),
|
||||
MessageType::Location(m) => (&mut m.body, None),
|
||||
MessageType::ServerNotice(m) => (&mut m.body, None),
|
||||
MessageType::Video(m) => (&mut m.body, None),
|
||||
MessageType::VerificationRequest(m) => (&mut m.body, None),
|
||||
MessageType::_Custom(m) => (&mut m.body, None),
|
||||
}
|
||||
};
|
||||
|
||||
// Add replacement fallback.
|
||||
*body = format!("* {body}");
|
||||
|
||||
if let Some(f) = formatted {
|
||||
assert_eq!(
|
||||
f.format,
|
||||
MessageFormat::Html,
|
||||
"make_replacement can't handle non-HTML formatted messages"
|
||||
);
|
||||
|
||||
f.body = format!("* {}", f.body);
|
||||
}
|
||||
|
||||
// Add reply fallback if needed.
|
||||
if let Some(original_message) = replied_to_message {
|
||||
self = self.make_reply_to(original_message, ForwardThread::No);
|
||||
}
|
||||
|
||||
self.relates_to = Some(relates_to);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Returns a reference to the `msgtype` string.
|
||||
///
|
||||
/// If you want to access the message type-specific data rather than the message type itself,
|
||||
|
@ -9,7 +9,7 @@ use ruma_common::{
|
||||
room::{
|
||||
message::{
|
||||
AudioMessageEventContent, KeyVerificationRequestEventContent, MessageType,
|
||||
OriginalRoomMessageEvent, RoomMessageEventContent,
|
||||
OriginalRoomMessageEvent, RoomMessageEventContent, TextMessageEventContent,
|
||||
},
|
||||
MediaSource,
|
||||
},
|
||||
@ -437,7 +437,7 @@ fn content_deserialization_failure() {
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-sanitize")]
|
||||
fn reply_sanitize() {
|
||||
use ruma_common::events::room::message::{ForwardThread, TextMessageEventContent};
|
||||
use ruma_common::events::room::message::ForwardThread;
|
||||
|
||||
let first_message = OriginalRoomMessageEvent {
|
||||
content: RoomMessageEventContent::text_html(
|
||||
@ -530,3 +530,72 @@ fn reply_sanitize() {
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn make_replacement_no_reply() {
|
||||
let content = RoomMessageEventContent::text_html(
|
||||
"This is _an edited_ message.",
|
||||
"This is <em>an edited</em> message.",
|
||||
);
|
||||
let event_id = event_id!("$143273582443PhrSn:example.org").to_owned();
|
||||
|
||||
let content = content.make_replacement(event_id, None);
|
||||
|
||||
let (body, formatted) = assert_matches!(
|
||||
content.msgtype,
|
||||
MessageType::Text(TextMessageEventContent { body, formatted, .. }) => (body, formatted)
|
||||
);
|
||||
assert_eq!(body, "* This is _an edited_ message.");
|
||||
let formatted = formatted.unwrap();
|
||||
assert_eq!(formatted.body, "* This is <em>an edited</em> message.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn make_replacement_with_reply() {
|
||||
let replied_to_message = OriginalRoomMessageEvent {
|
||||
content: RoomMessageEventContent::text_html(
|
||||
"# This is the first message",
|
||||
"<h1>This is the first message</h1>",
|
||||
),
|
||||
event_id: event_id!("$143273582443PhrSn:example.org").to_owned(),
|
||||
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(10_000)),
|
||||
room_id: room_id!("!testroomid:example.org").to_owned(),
|
||||
sender: user_id!("@user:example.org").to_owned(),
|
||||
unsigned: MessageLikeUnsigned::default(),
|
||||
};
|
||||
|
||||
let content = RoomMessageEventContent::text_html(
|
||||
"This is _an edited_ reply.",
|
||||
"This is <em>an edited</em> reply.",
|
||||
);
|
||||
let event_id = event_id!("$143273582443PhrSn:example.org").to_owned();
|
||||
|
||||
let content = content.make_replacement(event_id, Some(&replied_to_message));
|
||||
|
||||
let (body, formatted) = assert_matches!(
|
||||
content.msgtype,
|
||||
MessageType::Text(TextMessageEventContent { body, formatted, .. }) => (body, formatted)
|
||||
);
|
||||
assert_eq!(
|
||||
body,
|
||||
"\
|
||||
> <@user:example.org> # This is the first message\n\
|
||||
* This is _an edited_ reply.\
|
||||
"
|
||||
);
|
||||
let formatted = formatted.unwrap();
|
||||
assert_eq!(
|
||||
formatted.body,
|
||||
"\
|
||||
<mx-reply>\
|
||||
<blockquote>\
|
||||
<a href=\"https://matrix.to/#/!testroomid:example.org/$143273582443PhrSn:example.org\">In reply to</a> \
|
||||
<a href=\"https://matrix.to/#/@user:example.org\">@user:example.org</a>\
|
||||
<br>\
|
||||
<h1>This is the first message</h1>\
|
||||
</blockquote>\
|
||||
</mx-reply>\
|
||||
* This is <em>an edited</em> reply.\
|
||||
"
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user