FIX: sort chat channels by mentions, unread and channel title (#25565)

This change will sort channels by activity on mobile, with preference to those with urgent or unread messages.

Channels with mentions will appear first, followed by channels with unread messages, then finally everything else sorted by the channel title (alphabetically).
This commit is contained in:
David Battersby 2024-02-12 18:19:16 +08:00 committed by GitHub
parent 1403217ca4
commit aac28b9048
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 75 additions and 13 deletions

View File

@ -19,6 +19,7 @@ export default class ChatChannelsManager extends Service {
@service chatApi; @service chatApi;
@service currentUser; @service currentUser;
@service router; @service router;
@service site;
@tracked _cached = new TrackedObject(); @tracked _cached = new TrackedObject();
async find(id, options = { fetchIfNotFound: true }) { async find(id, options = { fetchIfNotFound: true }) {
@ -111,12 +112,16 @@ export default class ChatChannelsManager extends Service {
@cached @cached
get publicMessageChannels() { get publicMessageChannels() {
return this.channels const channels = this.channels.filter(
.filter(
(channel) => (channel) =>
channel.isCategoryChannel && channel.currentUserMembership.following channel.isCategoryChannel && channel.currentUserMembership.following
) );
.sort((a, b) => a?.slug?.localeCompare?.(b?.slug));
if (this.site.mobileView) {
return this.#sortChannelsByActivity(channels);
} else {
return channels.sort((a, b) => a?.title?.localeCompare?.(b?.title));
}
} }
@cached @cached
@ -154,6 +159,32 @@ export default class ChatChannelsManager extends Service {
return this._cached[id]; 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) { #sortDirectMessageChannels(channels) {
return channels.sort((a, b) => { return channels.sort((a, b) => {
if (!a.lastMessage.id) { if (!a.lastMessage.id) {

View File

@ -50,24 +50,55 @@ RSpec.describe "List channels | mobile", type: :system, mobile: true do
end end
context "when multiple category channels are present" do context "when multiple category channels are present" do
fab!(:channel_1) { Fabricate(:category_channel, name: "b channel") } fab!(:channel_1) { Fabricate(:category_channel, name: "a channel") }
fab!(:channel_2) { 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 before do
channel_1.add(current_user) channel_1.add(current_user)
channel_2.add(current_user) channel_2.add(current_user)
channel_3.add(current_user)
channel_4.add(current_user)
end end
it "sorts them alphabetically" do it "sorts them by mentions, unread, then alphabetical order" do
visit("/chat") Jobs.run_immediately!
page.find("#c-footer-channels").click
expect(page.find("#public-channels a:nth-child(1)")["data-chat-channel-id"]).to eq( Fabricate(
channel_2.id.to_s, :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( expect(page.find("#public-channels a:nth-child(2)")["data-chat-channel-id"]).to eq(
channel_1.id.to_s, 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
end end