events: Allow to add mentions automatically when generating reply

This commit is contained in:
Kévin Commaille 2023-08-21 17:13:07 +02:00 committed by Kévin Commaille
parent 3fe6ba7f52
commit b2b4c81645
3 changed files with 52 additions and 15 deletions

View File

@ -37,7 +37,9 @@ Breaking changes:
MSC2176 / MSC3821 / MSC3820, for the following types:
- `RedactedRoomRedactionEventContent`,
- `RedactedRoomPowerLevelsEventContent`,
- `RedactedRoomMemberEventContent`
- `RedactedRoomMemberEventContent`
- `RoomMessageEventContent::make_reply_to()` and `make_for_thread()` have an extra parameter to
support the recommended behavior for intentional mentions in replies according to Matrix 1.7
Improvements:

View File

@ -150,6 +150,7 @@ impl RoomMessageEventContent {
mut self,
original_message: &OriginalRoomMessageEvent,
forward_thread: ForwardThread,
add_mentions: AddMentions,
) -> Self {
let empty_formatted_body = || FormattedBody::html(String::new());
@ -205,6 +206,17 @@ impl RoomMessageEventContent {
};
self.relates_to = Some(relates_to);
if add_mentions == AddMentions::Yes {
// Copy the mentioned users.
let mut user_ids = match &original_message.content.mentions {
Some(m) => m.user_ids.clone(),
None => Default::default(),
};
// Add the sender.
user_ids.insert(original_message.sender.clone());
self.mentions = Some(Mentions { user_ids, ..Default::default() });
}
self
}
@ -227,9 +239,10 @@ impl RoomMessageEventContent {
mut self,
previous_message: &OriginalRoomMessageEvent,
is_reply: ReplyWithinThread,
add_mentions: AddMentions,
) -> Self {
if is_reply == ReplyWithinThread::Yes {
self = self.make_reply_to(previous_message, ForwardThread::No);
self = self.make_reply_to(previous_message, ForwardThread::No, add_mentions);
}
let thread_root = if let Some(Relation::Thread(Thread { event_id, .. })) =
@ -323,7 +336,7 @@ impl RoomMessageEventContent {
// Add reply fallback if needed.
if let Some(original_message) = replied_to_message {
self = self.make_reply_to(original_message, ForwardThread::No);
self = self.make_reply_to(original_message, ForwardThread::No, AddMentions::No);
}
self.relates_to = Some(relates_to);
@ -473,6 +486,24 @@ pub enum ForwardThread {
No,
}
/// Whether or not to add intentional [`Mentions`] when sending a reply.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[allow(clippy::exhaustive_enums)]
pub enum AddMentions {
/// Add automatic intentional mentions to the reply.
///
/// Set this if your client supports intentional mentions.
///
/// The sender of the original event will be added to the mentions of this message, along with
/// every user mentioned in the original event.
Yes,
/// Do not add intentional mentions to the reply.
///
/// Set this if your client does not support intentional mentions.
No,
}
/// Whether or not the message is a reply inside a thread.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[allow(clippy::exhaustive_enums)]

View File

@ -7,10 +7,11 @@ use ruma_common::{
key::verification::VerificationMethod,
room::{
message::{
AudioMessageEventContent, EmoteMessageEventContent, FileMessageEventContent,
ForwardThread, ImageMessageEventContent, KeyVerificationRequestEventContent,
MessageType, OriginalRoomMessageEvent, OriginalSyncRoomMessageEvent, Relation,
RoomMessageEventContent, TextMessageEventContent, VideoMessageEventContent,
AddMentions, AudioMessageEventContent, EmoteMessageEventContent,
FileMessageEventContent, ForwardThread, ImageMessageEventContent,
KeyVerificationRequestEventContent, MessageType, OriginalRoomMessageEvent,
OriginalSyncRoomMessageEvent, Relation, RoomMessageEventContent,
TextMessageEventContent, VideoMessageEventContent,
},
EncryptedFileInit, JsonWebKeyInit, MediaSource,
},
@ -265,8 +266,11 @@ fn escape_tags_in_plain_reply_body() {
sender: owned_user_id!("@user:example.org"),
unsigned: MessageLikeUnsigned::default(),
};
let second_message = RoomMessageEventContent::text_plain("Usage: rm <path>")
.make_reply_to(&first_message, ForwardThread::Yes);
let second_message = RoomMessageEventContent::text_plain("Usage: rm <path>").make_reply_to(
&first_message,
ForwardThread::Yes,
AddMentions::No,
);
assert_matches!(
first_message.content.msgtype,
@ -324,7 +328,7 @@ fn reply_sanitize() {
"This is the _second_ message",
"This is the <em>second</em> message",
)
.make_reply_to(&first_message, ForwardThread::Yes),
.make_reply_to(&first_message, ForwardThread::Yes, AddMentions::No),
event_id: owned_event_id!("$143273582443PhrSn:example.org"),
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(10_000)),
room_id: owned_room_id!("!testroomid:example.org"),
@ -335,7 +339,7 @@ fn reply_sanitize() {
"This is **my** reply",
"This is <strong>my</strong> reply",
)
.make_reply_to(&second_message, ForwardThread::Yes);
.make_reply_to(&second_message, ForwardThread::Yes, AddMentions::No);
assert_matches!(
first_message.content.msgtype,
@ -844,7 +848,7 @@ fn set_mentions() {
let user_id = owned_user_id!("@you:localhost");
content = content.set_mentions(Mentions::with_user_ids(vec![user_id.clone()]));
let mentions = content.mentions.unwrap();
assert_eq!(mentions.user_ids.as_slice(), &[user_id]);
assert_eq!(mentions.user_ids, [user_id].into());
}
#[test]
@ -878,14 +882,14 @@ fn make_replacement_set_mentions() {
assert_matches!(content.mentions, None);
assert_matches!(content.relates_to, Some(Relation::Replacement(replacement)));
let mentions = replacement.new_content.mentions.unwrap();
assert_eq!(mentions.user_ids.as_slice(), &[alice.clone()]);
assert_eq!(mentions.user_ids, [alice.clone()].into());
content = content_clone.set_mentions(Mentions::with_user_ids(vec![alice.clone(), bob.clone()]));
let mentions = content.mentions.unwrap();
assert_eq!(mentions.user_ids.as_slice(), &[bob.clone()]);
assert_eq!(mentions.user_ids, [bob.clone()].into());
assert_matches!(content.relates_to, Some(Relation::Replacement(replacement)));
let mentions = replacement.new_content.mentions.unwrap();
assert_eq!(mentions.user_ids.as_slice(), &[alice, bob]);
assert_eq!(mentions.user_ids, [alice, bob].into());
}
#[test]