mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
This commit follows up b6c5a2da08
by serializing the user's thread memberships in these cases:
1. When we do the initial channel fetch with messages, we get
all threads and all the user's thread memberships for those
messages.
2. When the thread list is fetched, we get all the user's memberships
in that list.
3. When the single thread is fetched, either from opening it from
the list, an OM indicator, or just from doing .find() on the
manager when a new MessageBus message comes in
This will let us track the lastReadMessageId on the client, and
will also let us fix an issue where the unread indicator in the
channel header was incrementing for every thread that got a
new message, regardless of whether the user was a member.
95 lines
2.8 KiB
Ruby
95 lines
2.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Chat
|
|
# Gets a list of threads for a channel to be shown in an index.
|
|
# In future pagination and filtering will be added -- for now
|
|
# we just want to return N threads ordered by the latest
|
|
# message that the user has sent in a thread.
|
|
#
|
|
# @example
|
|
# Chat::LookupChannelThreads.call(channel_id: 2, guardian: guardian)
|
|
#
|
|
class LookupChannelThreads
|
|
include Service::Base
|
|
|
|
# @!method call(channel_id:, guardian:)
|
|
# @param [Integer] channel_id
|
|
# @param [Guardian] guardian
|
|
# @return [Service::Base::Context]
|
|
|
|
policy :threaded_discussions_enabled
|
|
contract
|
|
model :channel
|
|
policy :threading_enabled_for_channel
|
|
policy :can_view_channel
|
|
model :threads
|
|
step :fetch_tracking
|
|
step :fetch_memberships
|
|
|
|
# @!visibility private
|
|
class Contract
|
|
attribute :channel_id, :integer
|
|
validates :channel_id, presence: true
|
|
end
|
|
|
|
private
|
|
|
|
def threaded_discussions_enabled
|
|
SiteSetting.enable_experimental_chat_threaded_discussions
|
|
end
|
|
|
|
def fetch_channel(contract:, **)
|
|
Chat::Channel.find_by(id: contract.channel_id)
|
|
end
|
|
|
|
def threading_enabled_for_channel(channel:, **)
|
|
channel.threading_enabled
|
|
end
|
|
|
|
def can_view_channel(guardian:, channel:, **)
|
|
guardian.can_preview_chat_channel?(channel)
|
|
end
|
|
|
|
def fetch_threads(guardian:, channel:, **)
|
|
Chat::Thread
|
|
.includes(
|
|
:channel,
|
|
original_message_user: :user_status,
|
|
original_message: :chat_webhook_event,
|
|
)
|
|
.select("chat_threads.*, MAX(chat_messages.created_at) AS last_posted_at")
|
|
.joins(
|
|
"LEFT JOIN chat_messages ON chat_threads.id = chat_messages.thread_id AND chat_messages.chat_channel_id = #{channel.id}",
|
|
)
|
|
.joins(
|
|
"LEFT JOIN chat_messages original_messages ON chat_threads.original_message_id = original_messages.id",
|
|
)
|
|
.where("chat_messages.user_id = ? OR chat_messages.user_id IS NULL", guardian.user.id)
|
|
.where(channel_id: channel.id)
|
|
.where(
|
|
"original_messages.deleted_at IS NULL AND chat_messages.deleted_at IS NULL AND original_messages.id IS NOT NULL",
|
|
)
|
|
.group("chat_threads.id")
|
|
.order("last_posted_at DESC NULLS LAST")
|
|
.limit(50)
|
|
end
|
|
|
|
def fetch_tracking(guardian:, threads:, **)
|
|
context.tracking =
|
|
::Chat::TrackingStateReportQuery.call(
|
|
guardian: guardian,
|
|
thread_ids: threads.map(&:id),
|
|
include_threads: true,
|
|
).thread_tracking
|
|
end
|
|
|
|
def fetch_memberships(guardian:, threads:, **)
|
|
context.memberships =
|
|
::Chat::UserChatThreadMembership.where(
|
|
thread_id: threads.map(&:id),
|
|
user_id: guardian.user.id,
|
|
)
|
|
end
|
|
end
|
|
end
|