diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-channels-manager.js b/plugins/chat/assets/javascripts/discourse/services/chat-channels-manager.js index 67fb05dadc6..331896b484f 100644 --- a/plugins/chat/assets/javascripts/discourse/services/chat-channels-manager.js +++ b/plugins/chat/assets/javascripts/discourse/services/chat-channels-manager.js @@ -19,6 +19,7 @@ export default class ChatChannelsManager extends Service { @service chatApi; @service currentUser; @service router; + @service site; @tracked _cached = new TrackedObject(); async find(id, options = { fetchIfNotFound: true }) { @@ -111,12 +112,16 @@ export default class ChatChannelsManager extends Service { @cached get publicMessageChannels() { - return this.channels - .filter( - (channel) => - channel.isCategoryChannel && channel.currentUserMembership.following - ) - .sort((a, b) => a?.slug?.localeCompare?.(b?.slug)); + const channels = this.channels.filter( + (channel) => + channel.isCategoryChannel && channel.currentUserMembership.following + ); + + if (this.site.mobileView) { + return this.#sortChannelsByActivity(channels); + } else { + return channels.sort((a, b) => a?.title?.localeCompare?.(b?.title)); + } } @cached @@ -154,6 +159,32 @@ export default class ChatChannelsManager extends Service { return this._cached[id]; } + #sortChannelsByActivity(channels) { + return channels.sort((a, b) => { + // if both channels have mention count, sort by aplhabetical order + // otherwise prioritize channel with mention count + if (a.tracking.mentionCount > 0 && b.tracking.mentionCount > 0) { + return a.title?.localeCompare?.(b.title); + } + + if (a.tracking.mentionCount > 0 || b.tracking.mentionCount > 0) { + return a.tracking.mentionCount > b.tracking.mentionCount ? -1 : 1; + } + + // if both channels have unread count, sort by aplhabetical order + // otherwise prioritize channel with unread count + if (a.tracking.unreadCount > 0 && b.tracking.unreadCount > 0) { + return a.title?.localeCompare?.(b.title); + } + + if (a.tracking.unreadCount > 0 || b.tracking.unreadCount > 0) { + return a.tracking.unreadCount > b.tracking.unreadCount ? -1 : 1; + } + + return a.title?.localeCompare?.(b.title); + }); + } + #sortDirectMessageChannels(channels) { return channels.sort((a, b) => { if (!a.lastMessage.id) { diff --git a/plugins/chat/spec/system/list_channels/mobile_spec.rb b/plugins/chat/spec/system/list_channels/mobile_spec.rb index 2932f847d09..793213e2ef8 100644 --- a/plugins/chat/spec/system/list_channels/mobile_spec.rb +++ b/plugins/chat/spec/system/list_channels/mobile_spec.rb @@ -50,24 +50,55 @@ RSpec.describe "List channels | mobile", type: :system, mobile: true do end context "when multiple category channels are present" do - fab!(:channel_1) { Fabricate(:category_channel, name: "b channel") } - fab!(:channel_2) { Fabricate(:category_channel, name: "a channel") } + fab!(:channel_1) { Fabricate(:category_channel, name: "a channel") } + fab!(:channel_2) { Fabricate(:category_channel, name: "b channel") } + fab!(:channel_3) { Fabricate(:category_channel, name: "c channel") } + fab!(:channel_4) { Fabricate(:category_channel, name: "d channel") } before do channel_1.add(current_user) channel_2.add(current_user) + channel_3.add(current_user) + channel_4.add(current_user) end - it "sorts them alphabetically" do - visit("/chat") - page.find("#c-footer-channels").click + it "sorts them by mentions, unread, then alphabetical order" do + Jobs.run_immediately! - expect(page.find("#public-channels a:nth-child(1)")["data-chat-channel-id"]).to eq( - channel_2.id.to_s, + Fabricate( + :chat_message, + chat_channel: channel_1, + created_at: 10.minutes.ago, + use_service: true, ) + Fabricate( + :chat_message, + chat_channel: channel_2, + created_at: 5.minutes.ago, + use_service: true, + ) + Fabricate( + :chat_message_with_service, + chat_channel: channel_4, + message: "Hey @#{current_user.username}", + user: Fabricate(:user), + ) + + Fabricate(:chat_message, chat_channel: channel_3, user: current_user, use_service: true) + + visit("/chat/channels") + + # channel with mentions should be first + expect(page.find("#public-channels a:nth-child(1)")["data-chat-channel-id"]).to eq( + channel_4.id.to_s, + ) + # channels with unread messages are next, sorted by title expect(page.find("#public-channels a:nth-child(2)")["data-chat-channel-id"]).to eq( channel_1.id.to_s, ) + expect(page.find("#public-channels a:nth-child(3)")["data-chat-channel-id"]).to eq( + channel_2.id.to_s, + ) end end