mirror of
https://github.com/discourse/discourse.git
synced 2026-08-17 16:35:03 -05:00
FEATURE: Create and update thread memberships (#21501)
When the user sends a message in a thread, we want to
create a membership for them in the background (default
to notification level of Watching) so we can track whether
they have read the thread.
Then, for now since we don't have granular message reading/
scrolling in the thread panel, we just update the thread
last_read_message_id for the user to the latest reply in the
thread when they open the thread panel. This at least will
mark the thread as read.
In future PRs we want to show the blue dot indicator in various
places in the UI for unread threads which will also require
some MessageBus functionality.
This takes into account the same issue fixed for channels
in ae3231e140
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe Chat::Action::ResetUserLastReadThreadMessage do
|
||||
fab!(:thread_1) { Fabricate(:chat_thread) }
|
||||
fab!(:thread_2) { Fabricate(:chat_thread) }
|
||||
fab!(:message_1) do
|
||||
Fabricate(
|
||||
:chat_message,
|
||||
chat_channel: thread_1.channel,
|
||||
thread: thread_1,
|
||||
created_at: 1.hour.ago,
|
||||
)
|
||||
end
|
||||
fab!(:message_2) do
|
||||
Fabricate(
|
||||
:chat_message,
|
||||
chat_channel: thread_1.channel,
|
||||
thread: thread_1,
|
||||
created_at: 2.seconds.ago,
|
||||
)
|
||||
end
|
||||
fab!(:message_3) do
|
||||
Fabricate(
|
||||
:chat_message,
|
||||
chat_channel: thread_1.channel,
|
||||
thread: thread_1,
|
||||
created_at: 3.minutes.ago,
|
||||
)
|
||||
end
|
||||
fab!(:message_4) do
|
||||
Fabricate(
|
||||
:chat_message,
|
||||
chat_channel: thread_2.channel,
|
||||
thread: thread_2,
|
||||
created_at: 30.seconds.ago,
|
||||
)
|
||||
end
|
||||
fab!(:message_5) do
|
||||
Fabricate(
|
||||
:chat_message,
|
||||
chat_channel: thread_2.channel,
|
||||
thread: thread_2,
|
||||
created_at: 3.seconds.ago,
|
||||
)
|
||||
end
|
||||
fab!(:message_6) do
|
||||
Fabricate(
|
||||
:chat_message,
|
||||
chat_channel: thread_2.channel,
|
||||
thread: thread_2,
|
||||
created_at: 1.day.ago,
|
||||
)
|
||||
end
|
||||
fab!(:membership_1) do
|
||||
Fabricate(:user_chat_thread_membership, thread: thread_1, last_read_message_id: message_3.id)
|
||||
end
|
||||
fab!(:membership_2) do
|
||||
Fabricate(:user_chat_thread_membership, thread: thread_2, last_read_message_id: message_6.id)
|
||||
end
|
||||
|
||||
context "when there are non-deleted messages left in the thread" 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], [thread_1.id, thread_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 thread (excluding the original message)" 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], [thread_1.id, thread_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
|
||||
@@ -119,6 +119,35 @@ RSpec.describe Chat::TrashMessage do
|
||||
result
|
||||
expect(thread.replies_count_cache).to eq(4)
|
||||
end
|
||||
|
||||
it "updates the tracking to the last non-deleted thread message for users whose last_read_message_id was the trashed message" do
|
||||
other_message =
|
||||
Fabricate(:chat_message, chat_channel: message.chat_channel, thread: thread)
|
||||
membership_1 =
|
||||
Fabricate(:user_chat_thread_membership, thread: thread, last_read_message: message)
|
||||
membership_2 =
|
||||
Fabricate(:user_chat_thread_membership, thread: thread, last_read_message: message)
|
||||
membership_3 =
|
||||
Fabricate(
|
||||
:user_chat_thread_membership,
|
||||
thread: thread,
|
||||
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 thread" do
|
||||
membership_1 =
|
||||
Fabricate(:user_chat_thread_membership, thread: thread, last_read_message: message)
|
||||
membership_2 =
|
||||
Fabricate(:user_chat_thread_membership, thread: thread, 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
|
||||
end
|
||||
end
|
||||
|
||||
context "when message is already deleted" do
|
||||
|
||||
@@ -12,6 +12,8 @@ RSpec.describe Chat::UpdateUserThreadLastRead do
|
||||
fab!(:current_user) { Fabricate(:user) }
|
||||
fab!(:channel) { Fabricate(:chat_channel) }
|
||||
fab!(:thread) { Fabricate(:chat_thread, channel: channel) }
|
||||
fab!(:thread_reply_1) { Fabricate(:chat_message, chat_channel: channel, thread: thread) }
|
||||
fab!(:thread_reply_2) { Fabricate(:chat_message, chat_channel: channel, thread: thread) }
|
||||
|
||||
let(:guardian) { Guardian.new(current_user) }
|
||||
let(:params) { { guardian: guardian, channel_id: channel.id, thread_id: thread.id } }
|
||||
@@ -85,6 +87,17 @@ RSpec.describe Chat::UpdateUserThreadLastRead do
|
||||
it "publishes new last read to clients" do
|
||||
expect(messages.map(&:channel)).to include("/chat/user-tracking-state/#{current_user.id}")
|
||||
end
|
||||
|
||||
context "when the user is a member of the thread" do
|
||||
fab!(:membership) do
|
||||
Fabricate(:user_chat_thread_membership, user: current_user, thread: thread)
|
||||
end
|
||||
|
||||
it "updates the last_read_message_id of the thread" do
|
||||
result
|
||||
expect(membership.reload.last_read_message_id).to eq(thread.replies.last.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user