mirror of
https://github.com/discourse/discourse.git
synced 2025-06-05 11:04:42 +08:00
FIX: Incorrect unread count shown in channel when message deleted (#21410)
When we were deleting messages in chat, we would find all of the UserChatChannelMembership records that had a matching last_read_message_id and set that column to NULL. This became an issue when multiple users had that deleted message set to their last_read_message_id. When we called ChannelUnreadsQuery to get the unread count for each of the user's channels, we were COALESCing the last_read_message_id and returning 0 if it was NULL, which meant that the unread count for the channel would be the total count of the messages not sent by the user in that channel. This was particularly noticeable for DM channels since we show the count with the indicator in the header. This issue would disappear as soon as the user opened the problem channel, because we would then set the last_read_message_id to an actual ID. To circumvent this, instead of NULLifying the last_read_message_id in most cases, it makes more sense to just set it to the most recent non-deleted chat message ID for the channel. The only time it will be set to NULL now is when there are no more other messages in the channel.
This commit is contained in:
@ -0,0 +1,49 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe Chat::Action::ResetUserLastReadChannelMessage do
|
||||
fab!(:channel_1) { Fabricate(:chat_channel) }
|
||||
fab!(:channel_2) { Fabricate(:chat_channel) }
|
||||
fab!(:message_1) { Fabricate(:chat_message, chat_channel: channel_1, created_at: 1.hour.ago) }
|
||||
fab!(:message_2) { Fabricate(:chat_message, chat_channel: channel_1, created_at: 2.seconds.ago) }
|
||||
fab!(:message_3) { Fabricate(:chat_message, chat_channel: channel_1, created_at: 3.minutes.ago) }
|
||||
fab!(:message_4) { Fabricate(:chat_message, chat_channel: channel_2, created_at: 30.seconds.ago) }
|
||||
fab!(:message_5) { Fabricate(:chat_message, chat_channel: channel_2, created_at: 3.seconds.ago) }
|
||||
fab!(:message_6) { Fabricate(:chat_message, chat_channel: channel_2, created_at: 1.day.ago) }
|
||||
fab!(:membership_1) do
|
||||
Fabricate(
|
||||
:user_chat_channel_membership,
|
||||
chat_channel: channel_1,
|
||||
last_read_message_id: message_3.id,
|
||||
)
|
||||
end
|
||||
fab!(:membership_2) do
|
||||
Fabricate(
|
||||
:user_chat_channel_membership,
|
||||
chat_channel: channel_2,
|
||||
last_read_message_id: message_6.id,
|
||||
)
|
||||
end
|
||||
|
||||
context "when there are non-deleted messages left in the channel" do
|
||||
before do
|
||||
message_3.trash!
|
||||
message_6.trash!
|
||||
end
|
||||
|
||||
it "sets the matching membership last_read_message_ids to the most recently created message ID" do
|
||||
described_class.call([message_3.id, message_6.id], [channel_1.id, channel_2.id])
|
||||
expect(membership_1.reload.last_read_message_id).to eq(message_2.id)
|
||||
expect(membership_2.reload.last_read_message_id).to eq(message_5.id)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there are no more non-deleted messages left in the channel" do
|
||||
before { [message_1, message_2, message_4, message_5].each(&:trash!) }
|
||||
|
||||
it "sets the matching membership last_read_message_ids to NULL" do
|
||||
described_class.call([message_3.id, message_6.id], [channel_1.id, channel_2.id])
|
||||
expect(membership_1.reload.last_read_message_id).to be_nil
|
||||
expect(membership_2.reload.last_read_message_id).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
@ -21,6 +21,26 @@ RSpec.describe Chat::MessageDestroyer do
|
||||
expect(membership.reload.last_read_message_id).to be_nil
|
||||
end
|
||||
|
||||
it "resets last_read_message_id to the most recent non-deleted message if there is one from memberships" do
|
||||
message_2 = Fabricate(:chat_message, chat_channel: message_1.chat_channel)
|
||||
message_3 = Fabricate(:chat_message, chat_channel: message_1.chat_channel)
|
||||
message_4 = Fabricate(:chat_message, chat_channel: message_1.chat_channel)
|
||||
message_3.trash!
|
||||
membership =
|
||||
Chat::UserChatChannelMembership.create!(
|
||||
user: user_1,
|
||||
chat_channel: message_1.chat_channel,
|
||||
last_read_message: message_4,
|
||||
following: true,
|
||||
desktop_notification_level: 2,
|
||||
mobile_notification_level: 2,
|
||||
)
|
||||
|
||||
described_class.new.destroy_in_batches(Chat::Message.where(id: message_4.id))
|
||||
|
||||
expect(membership.reload.last_read_message_id).to eq(message_2.id)
|
||||
end
|
||||
|
||||
it "deletes flags associated to deleted chat messages" do
|
||||
guardian = Guardian.new(Discourse.system_user)
|
||||
Chat::ReviewQueue.new.flag_message(message_1, guardian, ReviewableScore.types[:off_topic])
|
||||
|
@ -65,7 +65,8 @@ RSpec.describe Chat::TrashMessage do
|
||||
)
|
||||
end
|
||||
|
||||
it "updates the tracking for users whose last_read_message_id was the trashed message" do
|
||||
it "updates the tracking to the last non-deleted channel message for users whose last_read_message_id was the trashed message" do
|
||||
other_message = Fabricate(:chat_message, chat_channel: message.chat_channel)
|
||||
membership_1 =
|
||||
Fabricate(
|
||||
:user_chat_channel_membership,
|
||||
@ -82,12 +83,30 @@ RSpec.describe Chat::TrashMessage do
|
||||
Fabricate(
|
||||
:user_chat_channel_membership,
|
||||
chat_channel: message.chat_channel,
|
||||
last_read_message: Fabricate(:chat_message, chat_channel: message.chat_channel),
|
||||
last_read_message: other_message,
|
||||
)
|
||||
result
|
||||
expect(membership_1.reload.last_read_message_id).to eq(other_message.id)
|
||||
expect(membership_2.reload.last_read_message_id).to eq(other_message.id)
|
||||
expect(membership_3.reload.last_read_message_id).to eq(other_message.id)
|
||||
end
|
||||
|
||||
it "updates the tracking to nil when there are no other messages left in the channnel" do
|
||||
membership_1 =
|
||||
Fabricate(
|
||||
:user_chat_channel_membership,
|
||||
chat_channel: message.chat_channel,
|
||||
last_read_message: message,
|
||||
)
|
||||
membership_2 =
|
||||
Fabricate(
|
||||
:user_chat_channel_membership,
|
||||
chat_channel: message.chat_channel,
|
||||
last_read_message: message,
|
||||
)
|
||||
result
|
||||
expect(membership_1.reload.last_read_message_id).to be_nil
|
||||
expect(membership_2.reload.last_read_message_id).to be_nil
|
||||
expect(membership_3.reload.last_read_message_id).not_to be_nil
|
||||
end
|
||||
|
||||
context "when the message has a thread" do
|
||||
|
Reference in New Issue
Block a user