mirror of
https://github.com/discourse/discourse.git
synced 2025-05-24 14:12:10 +08:00
FIX: Do not count thread messages for channel unreads (#21126)
We currently don't have a nice UI to show unread messages for the thread, and it will take some time to create one. For now, this commit makes it so new messages inside a thread do not count towards a chat channel's unread counts, and new messages sent in a thread do not update a user's `last_read_message_id` for a channel. In addition, this PR refactors the `Chat::ChannelFetcher` to use the `Chat::ChannelUnreadsQuery` query class for consistency, and made said class able to return zeroed-out records for channels the user is not a member of. Finally, a small bug is fixed here where if a user's `last_read_message_id` for a channel was a thread's OM ID, then the thread OM would not show in the main channel stream for them until another reply to the channel was posted.
This commit is contained in:
@ -111,9 +111,11 @@ module Chat
|
|||||||
|
|
||||||
return render_json_error(chat_message_creator.error) if chat_message_creator.failed?
|
return render_json_error(chat_message_creator.error) if chat_message_creator.failed?
|
||||||
|
|
||||||
|
if !chat_message_creator.chat_message.thread_id.present?
|
||||||
@user_chat_channel_membership.update!(
|
@user_chat_channel_membership.update!(
|
||||||
last_read_message_id: chat_message_creator.chat_message.id,
|
last_read_message_id: chat_message_creator.chat_message.id,
|
||||||
)
|
)
|
||||||
|
end
|
||||||
|
|
||||||
if @chat_channel.direct_message_channel?
|
if @chat_channel.direct_message_channel?
|
||||||
# If any of the channel users is ignoring, muting, or preventing DMs from
|
# If any of the channel users is ignoring, muting, or preventing DMs from
|
||||||
@ -141,7 +143,13 @@ module Chat
|
|||||||
Chat::Publisher.publish_user_tracking_state(
|
Chat::Publisher.publish_user_tracking_state(
|
||||||
current_user,
|
current_user,
|
||||||
@chat_channel.id,
|
@chat_channel.id,
|
||||||
chat_message_creator.chat_message.id,
|
(
|
||||||
|
if chat_message_creator.chat_message.thread_id.present?
|
||||||
|
@user_chat_channel_membership.last_read_message_id
|
||||||
|
else
|
||||||
|
chat_message_creator.chat_message.id
|
||||||
|
end
|
||||||
|
),
|
||||||
)
|
)
|
||||||
render json: success_json
|
render json: success_json
|
||||||
end
|
end
|
||||||
@ -263,11 +271,8 @@ module Chat
|
|||||||
|
|
||||||
can_load_more_past = past_messages.count == PAST_MESSAGE_LIMIT
|
can_load_more_past = past_messages.count == PAST_MESSAGE_LIMIT
|
||||||
can_load_more_future = future_messages.count == FUTURE_MESSAGE_LIMIT
|
can_load_more_future = future_messages.count == FUTURE_MESSAGE_LIMIT
|
||||||
messages = [
|
looked_up_message = !include_thread_messages? && @message.thread_reply? ? [] : [@message]
|
||||||
past_messages.reverse,
|
messages = [past_messages.reverse, looked_up_message, future_messages].reduce([], :concat)
|
||||||
(!include_thread_messages? && @message.in_thread?) ? [] : [@message],
|
|
||||||
future_messages,
|
|
||||||
].reduce([], :concat)
|
|
||||||
chat_view =
|
chat_view =
|
||||||
Chat::View.new(
|
Chat::View.new(
|
||||||
chat_channel: @chat_channel,
|
chat_channel: @chat_channel,
|
||||||
|
@ -1,19 +1,31 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Chat
|
module Chat
|
||||||
|
##
|
||||||
|
# Handles counting unread messages and mentions for a list of channels.
|
||||||
|
# This is used for unread indicators in the chat UI. By default only the
|
||||||
|
# channels that the user is a member of will be counted and returned in
|
||||||
|
# the result.
|
||||||
class ChannelUnreadsQuery
|
class ChannelUnreadsQuery
|
||||||
def self.call(channel_ids:, user_id:)
|
##
|
||||||
|
# @param channel_ids [Array<Integer>] The IDs of the channels to count.
|
||||||
|
# @param user_id [Integer] The ID of the user to count for.
|
||||||
|
# @param include_no_membership_channels [Boolean] Whether to include channels
|
||||||
|
# that the user is not a member of. These counts will always be 0.
|
||||||
|
def self.call(channel_ids:, user_id:, include_no_membership_channels: false)
|
||||||
sql = <<~SQL
|
sql = <<~SQL
|
||||||
SELECT (
|
SELECT (
|
||||||
SELECT COUNT(*) AS unread_count
|
SELECT COUNT(*) AS unread_count
|
||||||
FROM chat_messages
|
FROM chat_messages
|
||||||
INNER JOIN chat_channels ON chat_channels.id = chat_messages.chat_channel_id
|
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_channels.id
|
INNER JOIN user_chat_channel_memberships ON user_chat_channel_memberships.chat_channel_id = chat_channels.id
|
||||||
|
LEFT JOIN chat_threads ON chat_threads.id = chat_messages.thread_id
|
||||||
WHERE chat_channels.id = memberships.chat_channel_id
|
WHERE chat_channels.id = memberships.chat_channel_id
|
||||||
AND chat_messages.user_id != :user_id
|
AND chat_messages.user_id != :user_id
|
||||||
AND user_chat_channel_memberships.user_id = :user_id
|
AND user_chat_channel_memberships.user_id = :user_id
|
||||||
AND chat_messages.id > COALESCE(user_chat_channel_memberships.last_read_message_id, 0)
|
AND chat_messages.id > COALESCE(user_chat_channel_memberships.last_read_message_id, 0)
|
||||||
AND chat_messages.deleted_at IS NULL
|
AND chat_messages.deleted_at IS NULL
|
||||||
|
AND (chat_messages.thread_id IS NULL OR chat_messages.id = chat_threads.original_message_id)
|
||||||
) AS unread_count,
|
) AS unread_count,
|
||||||
(
|
(
|
||||||
SELECT COUNT(*) AS mention_count
|
SELECT COUNT(*) AS mention_count
|
||||||
@ -32,6 +44,16 @@ module Chat
|
|||||||
GROUP BY memberships.chat_channel_id
|
GROUP BY memberships.chat_channel_id
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
|
sql += <<~SQL if include_no_membership_channels
|
||||||
|
UNION ALL
|
||||||
|
SELECT 0 AS unread_count, 0 AS mention_count, chat_channels.id AS channel_id
|
||||||
|
FROM chat_channels
|
||||||
|
LEFT JOIN user_chat_channel_memberships ON user_chat_channel_memberships.chat_channel_id = chat_channels.id
|
||||||
|
AND user_chat_channel_memberships.user_id = :user_id
|
||||||
|
WHERE chat_channels.id IN (:channel_ids) AND user_chat_channel_memberships.id IS NULL
|
||||||
|
GROUP BY chat_channels.id
|
||||||
|
SQL
|
||||||
|
|
||||||
DB.query(
|
DB.query(
|
||||||
sql,
|
sql,
|
||||||
channel_ids: channel_ids,
|
channel_ids: channel_ids,
|
||||||
|
@ -30,7 +30,9 @@ module Chat
|
|||||||
(
|
(
|
||||||
SELECT chat_messages.chat_channel_id, MAX(chat_messages.id) AS newest_message_id
|
SELECT chat_messages.chat_channel_id, MAX(chat_messages.id) AS newest_message_id
|
||||||
FROM chat_messages
|
FROM chat_messages
|
||||||
|
LEFT JOIN chat_threads ON chat_threads.id = chat_messages.thread_id
|
||||||
WHERE chat_messages.deleted_at IS NULL
|
WHERE chat_messages.deleted_at IS NULL
|
||||||
|
AND (chat_messages.thread_id IS NULL or chat_messages.id = chat_threads.original_message_id)
|
||||||
GROUP BY chat_messages.chat_channel_id
|
GROUP BY chat_messages.chat_channel_id
|
||||||
) AS subquery
|
) AS subquery
|
||||||
WHERE user_chat_channel_memberships.chat_channel_id = subquery.chat_channel_id AND
|
WHERE user_chat_channel_memberships.chat_channel_id = subquery.chat_channel_id AND
|
||||||
|
@ -24,7 +24,8 @@ export default class ChatChannelThreadPaneSubscriptionsManager extends ChatPaneB
|
|||||||
);
|
);
|
||||||
this.messagesManager.addMessages([message]);
|
this.messagesManager.addMessages([message]);
|
||||||
|
|
||||||
// TODO (martin) All the scrolling and new message indicator shenanigans.
|
// TODO (martin) All the scrolling and new message indicator shenanigans,
|
||||||
|
// as well as handling marking the thread as read.
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: noop, there is nothing to do when a thread is created
|
// NOTE: noop, there is nothing to do when a thread is created
|
||||||
|
@ -191,43 +191,25 @@ module Chat
|
|||||||
def self.decorate_memberships_with_tracking_data(guardian, channels, memberships)
|
def self.decorate_memberships_with_tracking_data(guardian, channels, memberships)
|
||||||
unread_counts_per_channel = unread_counts(channels, guardian.user.id)
|
unread_counts_per_channel = unread_counts(channels, guardian.user.id)
|
||||||
|
|
||||||
mention_notifications =
|
|
||||||
Notification.unread.where(
|
|
||||||
user_id: guardian.user.id,
|
|
||||||
notification_type: Notification.types[:chat_mention],
|
|
||||||
)
|
|
||||||
mention_notification_data = mention_notifications.map { |m| JSON.parse(m.data) }
|
|
||||||
|
|
||||||
channels.each do |channel|
|
channels.each do |channel|
|
||||||
membership = memberships.find { |m| m.chat_channel_id == channel.id }
|
membership = memberships.find { |m| m.chat_channel_id == channel.id }
|
||||||
|
|
||||||
if membership
|
if membership
|
||||||
membership.unread_mentions =
|
channel_unread_counts =
|
||||||
mention_notification_data.count do |data|
|
unread_counts_per_channel.find { |uc| uc.channel_id == channel.id }
|
||||||
data["chat_channel_id"] == channel.id &&
|
|
||||||
data["chat_message_id"] > (membership.last_read_message_id || 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
membership.unread_count = unread_counts_per_channel[channel.id] if !membership.muted
|
membership.unread_mentions = channel_unread_counts.mention_count
|
||||||
|
membership.unread_count = channel_unread_counts.unread_count if !membership.muted
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.unread_counts(channels, user_id)
|
def self.unread_counts(channels, user_id)
|
||||||
unread_counts = DB.query_array(<<~SQL, channel_ids: channels.map(&:id), user_id: user_id).to_h
|
Chat::ChannelUnreadsQuery.call(
|
||||||
SELECT cc.id, COUNT(*) as count
|
channel_ids: channels.map(&:id),
|
||||||
FROM chat_messages cm
|
user_id: user_id,
|
||||||
JOIN chat_channels cc ON cc.id = cm.chat_channel_id
|
include_no_membership_channels: true,
|
||||||
JOIN user_chat_channel_memberships uccm ON uccm.chat_channel_id = cc.id
|
)
|
||||||
WHERE cc.id IN (:channel_ids)
|
|
||||||
AND cm.user_id != :user_id
|
|
||||||
AND uccm.user_id = :user_id
|
|
||||||
AND cm.id > COALESCE(uccm.last_read_message_id, 0)
|
|
||||||
AND cm.deleted_at IS NULL
|
|
||||||
GROUP BY cc.id
|
|
||||||
SQL
|
|
||||||
unread_counts.default = 0
|
|
||||||
unread_counts
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find_with_access_check(channel_id_or_name, guardian)
|
def self.find_with_access_check(channel_id_or_name, guardian)
|
||||||
|
@ -59,14 +59,18 @@ describe Chat::ChannelFetcher do
|
|||||||
|
|
||||||
it "returns the correct count" do
|
it "returns the correct count" do
|
||||||
unread_counts = described_class.unread_counts([category_channel], user1)
|
unread_counts = described_class.unread_counts([category_channel], user1)
|
||||||
expect(unread_counts[category_channel.id]).to eq(2)
|
expect(
|
||||||
|
unread_counts.find { |uc| uc.channel_id == category_channel.id }.unread_count,
|
||||||
|
).to eq(2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with no unread messages" do
|
context "with no unread messages" do
|
||||||
it "returns the correct count" do
|
it "returns the correct count" do
|
||||||
unread_counts = described_class.unread_counts([category_channel], user1)
|
unread_counts = described_class.unread_counts([category_channel], user1)
|
||||||
expect(unread_counts[category_channel.id]).to eq(0)
|
expect(
|
||||||
|
unread_counts.find { |uc| uc.channel_id == category_channel.id }.unread_count,
|
||||||
|
).to eq(0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -79,7 +83,9 @@ describe Chat::ChannelFetcher do
|
|||||||
|
|
||||||
it "returns the correct count" do
|
it "returns the correct count" do
|
||||||
unread_counts = described_class.unread_counts([category_channel], user1)
|
unread_counts = described_class.unread_counts([category_channel], user1)
|
||||||
expect(unread_counts[category_channel.id]).to eq(0)
|
expect(
|
||||||
|
unread_counts.find { |uc| uc.channel_id == category_channel.id }.unread_count,
|
||||||
|
).to eq(0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -92,7 +98,9 @@ describe Chat::ChannelFetcher do
|
|||||||
|
|
||||||
it "returns the correct count" do
|
it "returns the correct count" do
|
||||||
unread_counts = described_class.unread_counts([category_channel], user1)
|
unread_counts = described_class.unread_counts([category_channel], user1)
|
||||||
expect(unread_counts[category_channel.id]).to eq(0)
|
expect(
|
||||||
|
unread_counts.find { |uc| uc.channel_id == category_channel.id }.unread_count,
|
||||||
|
).to eq(0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -21,14 +21,35 @@ describe Chat::ChannelUnreadsQuery do
|
|||||||
).to eq({ mention_count: 0, unread_count: 1, channel_id: channel_1.id })
|
).to eq({ mention_count: 0, unread_count: 1, channel_id: channel_1.id })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "for unread messages in a thread" do
|
||||||
|
fab!(:thread_om) { Fabricate(:chat_message, chat_channel: channel_1) }
|
||||||
|
fab!(:thread) { Fabricate(:chat_thread, channel: channel_1, original_message: thread_om) }
|
||||||
|
|
||||||
|
it "does include the original message in the unread count" do
|
||||||
|
expect(
|
||||||
|
described_class.call(channel_ids: [channel_1.id], user_id: current_user.id).first.to_h,
|
||||||
|
).to eq({ mention_count: 0, unread_count: 2, channel_id: channel_1.id })
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not include other thread messages in the unread count" do
|
||||||
|
Fabricate(:chat_message, chat_channel: channel_1, thread: thread)
|
||||||
|
Fabricate(:chat_message, chat_channel: channel_1, thread: thread)
|
||||||
|
expect(
|
||||||
|
described_class.call(channel_ids: [channel_1.id], user_id: current_user.id).first.to_h,
|
||||||
|
).to eq({ mention_count: 0, unread_count: 2, channel_id: channel_1.id })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "for multiple channels" do
|
context "for multiple channels" do
|
||||||
fab!(:channel_2) { Fabricate(:category_channel) }
|
fab!(:channel_2) { Fabricate(:category_channel) }
|
||||||
|
|
||||||
it "returns accurate counts" do
|
before do
|
||||||
channel_2.add(current_user)
|
channel_2.add(current_user)
|
||||||
Fabricate(:chat_message, chat_channel: channel_2)
|
Fabricate(:chat_message, chat_channel: channel_2)
|
||||||
Fabricate(:chat_message, chat_channel: channel_2)
|
Fabricate(:chat_message, chat_channel: channel_2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns accurate counts" do
|
||||||
expect(
|
expect(
|
||||||
described_class.call(
|
described_class.call(
|
||||||
channel_ids: [channel_1.id, channel_2.id],
|
channel_ids: [channel_1.id, channel_2.id],
|
||||||
@ -41,6 +62,41 @@ describe Chat::ChannelUnreadsQuery do
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "for channels where the user has no membership" do
|
||||||
|
before do
|
||||||
|
current_user
|
||||||
|
.user_chat_channel_memberships
|
||||||
|
.where(chat_channel_id: channel_2.id)
|
||||||
|
.destroy_all
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not return counts for the channels" do
|
||||||
|
expect(
|
||||||
|
described_class.call(
|
||||||
|
channel_ids: [channel_1.id, channel_2.id],
|
||||||
|
user_id: current_user.id,
|
||||||
|
).map(&:to_h),
|
||||||
|
).to match_array([{ mention_count: 0, unread_count: 1, channel_id: channel_1.id }])
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when include_no_membership_channels is true" do
|
||||||
|
it "does return zeroed counts for the channels" do
|
||||||
|
expect(
|
||||||
|
described_class.call(
|
||||||
|
channel_ids: [channel_1.id, channel_2.id],
|
||||||
|
user_id: current_user.id,
|
||||||
|
include_no_membership_channels: true,
|
||||||
|
).map(&:to_h),
|
||||||
|
).to match_array(
|
||||||
|
[
|
||||||
|
{ mention_count: 0, unread_count: 1, channel_id: channel_1.id },
|
||||||
|
{ mention_count: 0, unread_count: 0, channel_id: channel_2.id },
|
||||||
|
],
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -347,13 +347,19 @@ RSpec.describe Chat::ChatController do
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "sends a message for regular user when staff-only is disabled and they are following channel" do
|
context "when the regular user is following the channel" do
|
||||||
sign_in(user)
|
fab!(:message_1) { Fabricate(:chat_message, chat_channel: chat_channel) }
|
||||||
|
fab!(:membership) do
|
||||||
Chat::UserChatChannelMembership.create(
|
Chat::UserChatChannelMembership.create(
|
||||||
user: user,
|
user: user,
|
||||||
chat_channel: chat_channel,
|
chat_channel: chat_channel,
|
||||||
following: true,
|
following: true,
|
||||||
|
last_read_message_id: message_1.id,
|
||||||
)
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sends a message for regular user when staff-only is disabled and they are following channel" do
|
||||||
|
sign_in(user)
|
||||||
|
|
||||||
expect { post "/chat/#{chat_channel.id}.json", params: { message: message } }.to change {
|
expect { post "/chat/#{chat_channel.id}.json", params: { message: message } }.to change {
|
||||||
Chat::Message.count
|
Chat::Message.count
|
||||||
@ -361,6 +367,53 @@ RSpec.describe Chat::ChatController do
|
|||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
expect(Chat::Message.last.message).to eq(message)
|
expect(Chat::Message.last.message).to eq(message)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "updates the last_read_message_id for the user who sent the message" do
|
||||||
|
sign_in(user)
|
||||||
|
post "/chat/#{chat_channel.id}.json", params: { message: message }
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
expect(membership.reload.last_read_message_id).to eq(Chat::Message.last.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "publishes user tracking state using the new chat message as the last_read_message_id" do
|
||||||
|
sign_in(user)
|
||||||
|
messages =
|
||||||
|
MessageBus.track_publish(
|
||||||
|
Chat::Publisher.user_tracking_state_message_bus_channel(user.id),
|
||||||
|
) { post "/chat/#{chat_channel.id}.json", params: { message: message } }
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
expect(messages.first.data["last_read_message_id"]).to eq(Chat::Message.last.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when sending a message in a thread" do
|
||||||
|
fab!(:thread) do
|
||||||
|
Fabricate(:chat_thread, channel: chat_channel, original_message: message_1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not update the last_read_message_id for the user who sent the message" do
|
||||||
|
sign_in(user)
|
||||||
|
post "/chat/#{chat_channel.id}.json", params: { message: message, thread_id: thread.id }
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
expect(membership.reload.last_read_message_id).to eq(message_1.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "publishes user tracking state using the old membership last_read_message_id" do
|
||||||
|
sign_in(user)
|
||||||
|
messages =
|
||||||
|
MessageBus.track_publish(
|
||||||
|
Chat::Publisher.user_tracking_state_message_bus_channel(user.id),
|
||||||
|
) do
|
||||||
|
post "/chat/#{chat_channel.id}.json",
|
||||||
|
params: {
|
||||||
|
message: message,
|
||||||
|
thread_id: thread.id,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
expect(messages.first.data["last_read_message_id"]).to eq(message_1.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "for direct message" do
|
describe "for direct message" do
|
||||||
|
@ -154,6 +154,23 @@ RSpec.describe Chat::MarkAllUserChannelsRead do
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "for threads" do
|
||||||
|
fab!(:thread) { Fabricate(:chat_thread, channel: channel_1, original_message: message_2) }
|
||||||
|
|
||||||
|
it "does not use thread replies for last_read_message_id" do
|
||||||
|
Fabricate(:chat_message, chat_channel: channel_1, user: other_user, thread: thread)
|
||||||
|
result
|
||||||
|
expect(membership_1.reload.last_read_message_id).to eq(message_2.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does use thread original messages for last_read_message_id" do
|
||||||
|
new_om = Fabricate(:chat_message, chat_channel: channel_1, user: other_user)
|
||||||
|
thread.update!(original_message: new_om, original_message_user: other_user)
|
||||||
|
result
|
||||||
|
expect(membership_1.reload.last_read_message_id).to eq(new_om.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -85,5 +85,17 @@ describe "Channel thread message echoing", type: :system, js: true do
|
|||||||
channel_page.message_by_id_selector(thread.replies.last.id),
|
channel_page.message_by_id_selector(thread.replies.last.id),
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "does show the thread original_message if it is the last message in the channel" do
|
||||||
|
new_thread = Fabricate(:chat_thread, channel: channel)
|
||||||
|
current_user
|
||||||
|
.user_chat_channel_memberships
|
||||||
|
.find_by(chat_channel: channel)
|
||||||
|
.update!(last_read_message_id: new_thread.original_message_id)
|
||||||
|
chat_page.visit_channel(channel)
|
||||||
|
expect(channel_page).to have_css(
|
||||||
|
channel_page.message_by_id_selector(new_thread.original_message_id),
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -143,6 +143,22 @@ describe "Single thread in side panel", type: :system, js: true do
|
|||||||
expect(open_thread).to have_message(thread.id, text: "this is a test message")
|
expect(open_thread).to have_message(thread.id, text: "this is a test message")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "does not mark the channel unread if another user sends a message in the thread" do
|
||||||
|
other_user = Fabricate(:user)
|
||||||
|
chat_system_user_bootstrap(user: other_user, channel: channel)
|
||||||
|
Chat::MessageCreator.create(
|
||||||
|
chat_channel: channel,
|
||||||
|
user: other_user,
|
||||||
|
content: "Hello world!",
|
||||||
|
thread_id: thread.id,
|
||||||
|
)
|
||||||
|
sign_in(current_user)
|
||||||
|
chat_page.visit_channel(channel)
|
||||||
|
expect(page).not_to have_css(
|
||||||
|
".sidebar-section-link.channel-#{channel.id} .sidebar-section-link-suffix.unread",
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when using mobile" do
|
context "when using mobile" do
|
||||||
|
Reference in New Issue
Block a user