diff --git a/plugins/chat/app/controllers/chat/api/current_user_channels_controller.rb b/plugins/chat/app/controllers/chat/api/current_user_channels_controller.rb index 613af229090..02660ef5cc5 100644 --- a/plugins/chat/app/controllers/chat/api/current_user_channels_controller.rb +++ b/plugins/chat/app/controllers/chat/api/current_user_channels_controller.rb @@ -2,7 +2,16 @@ class Chat::Api::CurrentUserChannelsController < Chat::ApiController def index - structured = Chat::ChannelFetcher.structured(guardian) - render_serialized(structured, Chat::ChannelIndexSerializer, root: false) + with_service(Chat::ListUserChannels) do + on_success do + render_serialized( + result.structured, + Chat::ChannelIndexSerializer, + root: false, + post_allowed_category_ids: result.post_allowed_category_ids, + ) + end + on_failure { render(json: failed_json, status: 422) } + end end end diff --git a/plugins/chat/app/services/chat/list_channel_messages.rb b/plugins/chat/app/services/chat/list_channel_messages.rb index 0c9ed6a1594..36daf51e67c 100644 --- a/plugins/chat/app/services/chat/list_channel_messages.rb +++ b/plugins/chat/app/services/chat/list_channel_messages.rb @@ -29,6 +29,7 @@ module Chat step :fetch_thread_participants step :fetch_thread_memberships step :update_membership_last_viewed_at + step :update_user_last_channel class Contract attribute :channel_id, :integer @@ -170,5 +171,12 @@ module Chat context.membership&.update!(last_viewed_at: Time.zone.now) end end + + def update_user_last_channel(guardian:, channel:) + Scheduler::Defer.later "Chat::ListChannelMessages - defer update_user_last_channel" do + return if guardian.user.custom_fields[::Chat::LAST_CHAT_CHANNEL_ID] == channel.id + guardian.user.upsert_custom_fields(::Chat::LAST_CHAT_CHANNEL_ID => channel.id) + end + end end end diff --git a/plugins/chat/app/services/chat/list_user_channels.rb b/plugins/chat/app/services/chat/list_user_channels.rb new file mode 100644 index 00000000000..65a4eae7996 --- /dev/null +++ b/plugins/chat/app/services/chat/list_user_channels.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module Chat + # List of the channels a user is tracking + # + # @example + # Chat::ListUserChannels.call(guardian: guardian, **optional_params) + # + class ListUserChannels + include Service::Base + + # @!method call(guardian:) + # @param [Guardian] guardian + # @return [Service::Base::Context] + + model :structured + step :inject_unread_thread_overview + model :post_allowed_category_ids, optional: true + + private + + def fetch_structured(guardian:) + ::Chat::ChannelFetcher.structured(guardian) + end + + def inject_unread_thread_overview(structured:, guardian:) + structured[:unread_thread_overview] = ::Chat::TrackingStateReportQuery.call( + guardian: guardian, + channel_ids: structured[:public_channels].map(&:id), + include_threads: true, + include_read: false, + include_last_reply_details: true, + ).thread_unread_overview_by_channel + end + + def fetch_post_allowed_category_ids(guardian:, structured:) + ::Category + .post_create_allowed(guardian) + .where(id: structured[:public_channels].map { |c| c.chatable_id }) + .pluck(:id) + end + end +end diff --git a/plugins/chat/assets/javascripts/discourse/components/channels-list-public.gjs b/plugins/chat/assets/javascripts/discourse/components/channels-list-public.gjs index f89c2541848..842804615d3 100644 --- a/plugins/chat/assets/javascripts/discourse/components/channels-list-public.gjs +++ b/plugins/chat/assets/javascripts/discourse/components/channels-list-public.gjs @@ -13,6 +13,7 @@ import ChatChannelRow from "./chat-channel-row"; export default class ChannelsListPublic extends Component { @service chatChannelsManager; + @service chatStateManager; @service chatTrackingStateManager; @service site; @service siteSettings; @@ -23,7 +24,10 @@ export default class ChannelsListPublic extends Component { } get publicMessageChannelsEmpty() { - return this.chatChannelsManager.publicMessageChannels?.length === 0; + return ( + this.chatChannelsManager.publicMessageChannels?.length === 0 && + this.chatStateManager.hasPreloadedChannels + ); } get displayPublicChannels() { @@ -31,6 +35,10 @@ export default class ChannelsListPublic extends Component { return false; } + if (!this.chatStateManager.hasPreloadedChannels) { + return false; + } + if (this.publicMessageChannelsEmpty) { return ( this.currentUser?.staff || @@ -45,10 +53,8 @@ export default class ChannelsListPublic extends Component { return this.chatTrackingStateManager.hasUnreadThreads; } - get isThreadEnabledInAnyChannel() { - return this.currentUser?.chat_channels?.public_channels?.some( - (channel) => channel.threading_enabled - ); + get hasThreadedChannels() { + return this.chatChannelsManager.hasThreadedChannels; } @action @@ -57,7 +63,7 @@ export default class ChannelsListPublic extends Component { }