FEATURE: add mention count to threads (#29739)
Previously we only counted mentions that were made within channels, however for threads this was never implemented. This change adds a mention count to the ThreadUnreadsQuery, which is used for channel thread lists and the user thread list. We are also expanding channel mentions count to include mentions within threads. The goal is to have a more consistent urgent badge across chat, in places such as channel lists and the chat header.
This commit is contained in:
parent
cd6d2ffaa4
commit
5ce4af1aa6
|
@ -46,7 +46,6 @@ module Chat
|
||||||
AND notifications.notification_type = :notification_type_mention
|
AND notifications.notification_type = :notification_type_mention
|
||||||
AND (data::json->>'chat_message_id')::bigint > COALESCE(user_chat_channel_memberships.last_read_message_id, 0)
|
AND (data::json->>'chat_message_id')::bigint > COALESCE(user_chat_channel_memberships.last_read_message_id, 0)
|
||||||
AND (data::json->>'chat_channel_id')::bigint = memberships.chat_channel_id
|
AND (data::json->>'chat_channel_id')::bigint = memberships.chat_channel_id
|
||||||
AND (chat_messages.thread_id IS NULL OR chat_messages.id = chat_threads.original_message_id)
|
|
||||||
) AS mention_count,
|
) AS mention_count,
|
||||||
(
|
(
|
||||||
SELECT COUNT(*) AS watched_threads_unread_count
|
SELECT COUNT(*) AS watched_threads_unread_count
|
||||||
|
|
|
@ -59,7 +59,22 @@ module Chat
|
||||||
AND user_chat_channel_memberships.muted = false
|
AND user_chat_channel_memberships.muted = false
|
||||||
AND user_chat_channel_memberships.user_id = :user_id
|
AND user_chat_channel_memberships.user_id = :user_id
|
||||||
) AS unread_count,
|
) AS unread_count,
|
||||||
0 as mention_count,
|
(
|
||||||
|
SELECT COUNT(*) AS mention_count
|
||||||
|
FROM notifications
|
||||||
|
INNER JOIN chat_messages ON chat_messages.id = (data::json->>'chat_message_id')::bigint
|
||||||
|
INNER JOIN chat_channels ON chat_channels.id = chat_messages.chat_channel_id
|
||||||
|
INNER JOIN user_chat_channel_memberships ON user_chat_channel_memberships.chat_channel_id = chat_messages.chat_channel_id
|
||||||
|
LEFT JOIN chat_threads ON chat_threads.id = chat_messages.thread_id
|
||||||
|
WHERE NOT read
|
||||||
|
AND notifications.user_id = :user_id
|
||||||
|
AND notifications.notification_type = :notification_type_mention
|
||||||
|
AND user_chat_channel_memberships.user_id = :user_id
|
||||||
|
AND chat_channels.threading_enabled
|
||||||
|
AND chat_messages.deleted_at IS NULL
|
||||||
|
AND chat_messages.thread_id = memberships.thread_id
|
||||||
|
AND NOT user_chat_channel_memberships.muted
|
||||||
|
) AS mention_count,
|
||||||
(
|
(
|
||||||
SELECT COUNT(*) AS watched_threads_unread_count
|
SELECT COUNT(*) AS watched_threads_unread_count
|
||||||
FROM chat_messages
|
FROM chat_messages
|
||||||
|
@ -122,6 +137,7 @@ module Chat
|
||||||
limit: MAX_THREADS,
|
limit: MAX_THREADS,
|
||||||
tracking_level: ::Chat::UserChatThreadMembership.notification_levels[:tracking],
|
tracking_level: ::Chat::UserChatThreadMembership.notification_levels[:tracking],
|
||||||
watching_level: ::Chat::UserChatThreadMembership.notification_levels[:watching],
|
watching_level: ::Chat::UserChatThreadMembership.notification_levels[:watching],
|
||||||
|
notification_type_mention: ::Notification.types[:chat_mention],
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,6 +11,7 @@ export default class ChatChannelUnreadIndicator extends Component {
|
||||||
get showUnreadIndicator() {
|
get showUnreadIndicator() {
|
||||||
return (
|
return (
|
||||||
this.args.channel.tracking.unreadCount > 0 ||
|
this.args.channel.tracking.unreadCount > 0 ||
|
||||||
|
this.args.channel.tracking.mentionCount > 0 ||
|
||||||
this.args.channel.unreadThreadsCountSinceLastViewed > 0
|
this.args.channel.unreadThreadsCountSinceLastViewed > 0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,10 @@ export default class ChatThreadUnreadIndicator extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
get urgentCount() {
|
get urgentCount() {
|
||||||
return this.args.thread.tracking.watchedThreadsUnreadCount;
|
return (
|
||||||
|
this.args.thread.tracking.mentionCount +
|
||||||
|
this.args.thread.tracking.watchedThreadsUnreadCount
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get showUnreadIndicator() {
|
get showUnreadIndicator() {
|
||||||
|
|
|
@ -225,14 +225,14 @@ describe Chat::ChannelUnreadsQuery do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not include other thread messages in the mention count" do
|
it "includes thread messages with mentions in the channel mention count" do
|
||||||
thread_message_1 = Fabricate(:chat_message, chat_channel: channel_1, thread: thread)
|
thread_message_1 = Fabricate(:chat_message, chat_channel: channel_1, thread: thread)
|
||||||
thread_message_2 = Fabricate(:chat_message, chat_channel: channel_1, thread: thread)
|
thread_message_2 = Fabricate(:chat_message, chat_channel: channel_1, thread: thread)
|
||||||
create_mention(thread_message_1, channel_1)
|
create_mention(thread_message_1, channel_1)
|
||||||
create_mention(thread_message_2, channel_1)
|
create_mention(thread_message_2, channel_1)
|
||||||
expect(query.first).to eq(
|
expect(query.first).to eq(
|
||||||
{
|
{
|
||||||
mention_count: 0,
|
mention_count: 2,
|
||||||
unread_count: 1,
|
unread_count: 1,
|
||||||
watched_threads_unread_count: 0,
|
watched_threads_unread_count: 0,
|
||||||
channel_id: channel_1.id,
|
channel_id: channel_1.id,
|
||||||
|
|
|
@ -36,6 +36,24 @@ describe Chat::ThreadUnreadsQuery do
|
||||||
thread_4.add(current_user)
|
thread_4.add(current_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_mention(message, channel, thread)
|
||||||
|
notification =
|
||||||
|
Notification.create!(
|
||||||
|
notification_type: Notification.types[:chat_mention],
|
||||||
|
user_id: current_user.id,
|
||||||
|
data: {
|
||||||
|
chat_message_id: message.id,
|
||||||
|
chat_channel_id: channel.id,
|
||||||
|
thread_id: thread.id,
|
||||||
|
}.to_json,
|
||||||
|
)
|
||||||
|
Chat::UserMention.create!(
|
||||||
|
notifications: [notification],
|
||||||
|
user: current_user,
|
||||||
|
chat_message: message,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
context "with unread messages across multiple threads" do
|
context "with unread messages across multiple threads" do
|
||||||
fab!(:message_1) { Fabricate(:chat_message, chat_channel: channel_1, thread: thread_1) }
|
fab!(:message_1) { Fabricate(:chat_message, chat_channel: channel_1, thread: thread_1) }
|
||||||
fab!(:message_2) { Fabricate(:chat_message, chat_channel: channel_2, thread: thread_3) }
|
fab!(:message_2) { Fabricate(:chat_message, chat_channel: channel_2, thread: thread_3) }
|
||||||
|
@ -188,6 +206,87 @@ describe Chat::ThreadUnreadsQuery do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "with mentions" do
|
||||||
|
let!(:message) { create_mention(message_1, channel_1, thread_1) }
|
||||||
|
|
||||||
|
it "counts both unread messages and mentions separately" do
|
||||||
|
expect(query.map(&:to_h)).to eq(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
channel_id: channel_1.id,
|
||||||
|
thread_id: thread_1.id,
|
||||||
|
mention_count: 1,
|
||||||
|
unread_count: 1,
|
||||||
|
watched_threads_unread_count: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
channel_id: channel_1.id,
|
||||||
|
thread_id: thread_2.id,
|
||||||
|
mention_count: 0,
|
||||||
|
unread_count: 0,
|
||||||
|
watched_threads_unread_count: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
channel_id: channel_2.id,
|
||||||
|
thread_id: thread_3.id,
|
||||||
|
mention_count: 0,
|
||||||
|
unread_count: 1,
|
||||||
|
watched_threads_unread_count: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
channel_id: channel_2.id,
|
||||||
|
thread_id: thread_4.id,
|
||||||
|
mention_count: 0,
|
||||||
|
unread_count: 1,
|
||||||
|
watched_threads_unread_count: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not count mentions in muted channels" do
|
||||||
|
channel_1.membership_for(current_user).update!(muted: true)
|
||||||
|
|
||||||
|
expect(query.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_1.id }).to eq(
|
||||||
|
{
|
||||||
|
thread_id: thread_1.id,
|
||||||
|
channel_id: channel_1.id,
|
||||||
|
unread_count: 0,
|
||||||
|
mention_count: 0,
|
||||||
|
watched_threads_unread_count: 0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not count mentions in threads when channel has threading_enabled = false" do
|
||||||
|
channel_1.update!(threading_enabled: false)
|
||||||
|
|
||||||
|
expect(query.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_1.id }).to eq(
|
||||||
|
{
|
||||||
|
thread_id: thread_1.id,
|
||||||
|
channel_id: channel_1.id,
|
||||||
|
unread_count: 0,
|
||||||
|
mention_count: 0,
|
||||||
|
watched_threads_unread_count: 0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not count mentions in threads when the message is deleted" do
|
||||||
|
message_1.trash!
|
||||||
|
|
||||||
|
expect(query.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_1.id }).to eq(
|
||||||
|
{
|
||||||
|
thread_id: thread_1.id,
|
||||||
|
channel_id: channel_1.id,
|
||||||
|
unread_count: 0,
|
||||||
|
mention_count: 0,
|
||||||
|
watched_threads_unread_count: 0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when only the thread_ids are provided" do
|
context "when only the thread_ids are provided" do
|
||||||
|
@ -254,6 +353,20 @@ describe Chat::ThreadUnreadsQuery do
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "counts mentions but not unreads" do
|
||||||
|
create_mention(message_1, channel_1, thread_1)
|
||||||
|
|
||||||
|
expect(query.map(&:to_h)).to include(
|
||||||
|
{
|
||||||
|
channel_id: channel_1.id,
|
||||||
|
mention_count: 1,
|
||||||
|
thread_id: thread_1.id,
|
||||||
|
unread_count: 0,
|
||||||
|
watched_threads_unread_count: 0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the user is not a member of a thread" do
|
context "when the user is not a member of a thread" do
|
||||||
|
|
Loading…
Reference in New Issue