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 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) {

View File

@ -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