events: Allow to add mentions automatically when generating reply
This commit is contained in:
parent
3fe6ba7f52
commit
b2b4c81645
@ -38,6 +38,8 @@ Breaking changes:
|
|||||||
- `RedactedRoomRedactionEventContent`,
|
- `RedactedRoomRedactionEventContent`,
|
||||||
- `RedactedRoomPowerLevelsEventContent`,
|
- `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:
|
Improvements:
|
||||||
|
|
||||||
|
@ -150,6 +150,7 @@ impl RoomMessageEventContent {
|
|||||||
mut self,
|
mut self,
|
||||||
original_message: &OriginalRoomMessageEvent,
|
original_message: &OriginalRoomMessageEvent,
|
||||||
forward_thread: ForwardThread,
|
forward_thread: ForwardThread,
|
||||||
|
add_mentions: AddMentions,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let empty_formatted_body = || FormattedBody::html(String::new());
|
let empty_formatted_body = || FormattedBody::html(String::new());
|
||||||
|
|
||||||
@ -205,6 +206,17 @@ impl RoomMessageEventContent {
|
|||||||
};
|
};
|
||||||
self.relates_to = Some(relates_to);
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,9 +239,10 @@ impl RoomMessageEventContent {
|
|||||||
mut self,
|
mut self,
|
||||||
previous_message: &OriginalRoomMessageEvent,
|
previous_message: &OriginalRoomMessageEvent,
|
||||||
is_reply: ReplyWithinThread,
|
is_reply: ReplyWithinThread,
|
||||||
|
add_mentions: AddMentions,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
if is_reply == ReplyWithinThread::Yes {
|
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, .. })) =
|
let thread_root = if let Some(Relation::Thread(Thread { event_id, .. })) =
|
||||||
@ -323,7 +336,7 @@ impl RoomMessageEventContent {
|
|||||||
|
|
||||||
// Add reply fallback if needed.
|
// Add reply fallback if needed.
|
||||||
if let Some(original_message) = replied_to_message {
|
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);
|
self.relates_to = Some(relates_to);
|
||||||
@ -473,6 +486,24 @@ pub enum ForwardThread {
|
|||||||
No,
|
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.
|
/// Whether or not the message is a reply inside a thread.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
#[allow(clippy::exhaustive_enums)]
|
#[allow(clippy::exhaustive_enums)]
|
||||||
|
@ -7,10 +7,11 @@ use ruma_common::{
|
|||||||
key::verification::VerificationMethod,
|
key::verification::VerificationMethod,
|
||||||
room::{
|
room::{
|
||||||
message::{
|
message::{
|
||||||
AudioMessageEventContent, EmoteMessageEventContent, FileMessageEventContent,
|
AddMentions, AudioMessageEventContent, EmoteMessageEventContent,
|
||||||
ForwardThread, ImageMessageEventContent, KeyVerificationRequestEventContent,
|
FileMessageEventContent, ForwardThread, ImageMessageEventContent,
|
||||||
MessageType, OriginalRoomMessageEvent, OriginalSyncRoomMessageEvent, Relation,
|
KeyVerificationRequestEventContent, MessageType, OriginalRoomMessageEvent,
|
||||||
RoomMessageEventContent, TextMessageEventContent, VideoMessageEventContent,
|
OriginalSyncRoomMessageEvent, Relation, RoomMessageEventContent,
|
||||||
|
TextMessageEventContent, VideoMessageEventContent,
|
||||||
},
|
},
|
||||||
EncryptedFileInit, JsonWebKeyInit, MediaSource,
|
EncryptedFileInit, JsonWebKeyInit, MediaSource,
|
||||||
},
|
},
|
||||||
@ -265,8 +266,11 @@ fn escape_tags_in_plain_reply_body() {
|
|||||||
sender: owned_user_id!("@user:example.org"),
|
sender: owned_user_id!("@user:example.org"),
|
||||||
unsigned: MessageLikeUnsigned::default(),
|
unsigned: MessageLikeUnsigned::default(),
|
||||||
};
|
};
|
||||||
let second_message = RoomMessageEventContent::text_plain("Usage: rm <path>")
|
let second_message = RoomMessageEventContent::text_plain("Usage: rm <path>").make_reply_to(
|
||||||
.make_reply_to(&first_message, ForwardThread::Yes);
|
&first_message,
|
||||||
|
ForwardThread::Yes,
|
||||||
|
AddMentions::No,
|
||||||
|
);
|
||||||
|
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
first_message.content.msgtype,
|
first_message.content.msgtype,
|
||||||
@ -324,7 +328,7 @@ fn reply_sanitize() {
|
|||||||
"This is the _second_ message",
|
"This is the _second_ message",
|
||||||
"This is the <em>second</em> 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"),
|
event_id: owned_event_id!("$143273582443PhrSn:example.org"),
|
||||||
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(10_000)),
|
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(10_000)),
|
||||||
room_id: owned_room_id!("!testroomid:example.org"),
|
room_id: owned_room_id!("!testroomid:example.org"),
|
||||||
@ -335,7 +339,7 @@ fn reply_sanitize() {
|
|||||||
"This is **my** reply",
|
"This is **my** reply",
|
||||||
"This is <strong>my</strong> 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!(
|
assert_matches!(
|
||||||
first_message.content.msgtype,
|
first_message.content.msgtype,
|
||||||
@ -844,7 +848,7 @@ fn set_mentions() {
|
|||||||
let user_id = owned_user_id!("@you:localhost");
|
let user_id = owned_user_id!("@you:localhost");
|
||||||
content = content.set_mentions(Mentions::with_user_ids(vec![user_id.clone()]));
|
content = content.set_mentions(Mentions::with_user_ids(vec![user_id.clone()]));
|
||||||
let mentions = content.mentions.unwrap();
|
let mentions = content.mentions.unwrap();
|
||||||
assert_eq!(mentions.user_ids.as_slice(), &[user_id]);
|
assert_eq!(mentions.user_ids, [user_id].into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -878,14 +882,14 @@ fn make_replacement_set_mentions() {
|
|||||||
assert_matches!(content.mentions, None);
|
assert_matches!(content.mentions, None);
|
||||||
assert_matches!(content.relates_to, Some(Relation::Replacement(replacement)));
|
assert_matches!(content.relates_to, Some(Relation::Replacement(replacement)));
|
||||||
let mentions = replacement.new_content.mentions.unwrap();
|
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()]));
|
content = content_clone.set_mentions(Mentions::with_user_ids(vec![alice.clone(), bob.clone()]));
|
||||||
let mentions = content.mentions.unwrap();
|
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)));
|
assert_matches!(content.relates_to, Some(Relation::Replacement(replacement)));
|
||||||
let mentions = replacement.new_content.mentions.unwrap();
|
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]
|
#[test]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user