FEATURE: chat drawer navigation improvement (#27419)

This change replaces the chat drawer tabs with new drawer routes for channels, direct messages and threads.

The main objective is to improve navigation within drawer, now that we have separation of chat sections in drawer.
This commit is contained in:
David Battersby 2024-06-13 13:17:12 +04:00 committed by GitHub
parent 3ae2e039c3
commit 47540fb4e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 146 additions and 54 deletions

View File

@ -1,5 +1,4 @@
import Component from "@glimmer/component";
import { fn } from "@ember/helper";
import { service } from "@ember/service";
import { eq } from "truth-helpers";
import DButton from "discourse/components/d-button";
@ -14,6 +13,7 @@ import {
export default class ChatFooter extends Component {
@service router;
@service chat;
@service chatHistory;
@service siteSettings;
@service currentUser;
@service chatChannelsManager;
@ -30,6 +30,11 @@ export default class ChatFooter extends Component {
return this.chat.userCanAccessDirectMessages;
}
get currentRouteName() {
const routeName = this.chatHistory.currentRoute?.name;
return routeName === "chat" ? "chat.channels" : routeName;
}
get shouldRenderFooter() {
return (
this.chatStateManager.hasPreloadedChannels &&
@ -41,7 +46,7 @@ export default class ChatFooter extends Component {
{{#if this.shouldRenderFooter}}
<nav class="c-footer">
<DButton
@action={{fn @onClickTab "channels"}}
@route="chat.channels"
@icon="comments"
@translatedLabel={{i18n "chat.channel_list.title"}}
aria-label={{i18n "chat.channel_list.aria_label"}}
@ -49,7 +54,7 @@ export default class ChatFooter extends Component {
class={{concatClass
"btn-transparent"
"c-footer__item"
(if (eq @activeTab "channels") "--active")
(if (eq this.currentRouteName "chat.channels") "--active")
}}
>
<UnreadChannelsIndicator />
@ -57,7 +62,7 @@ export default class ChatFooter extends Component {
{{#if this.directMessagesEnabled}}
<DButton
@action={{fn @onClickTab "direct-messages"}}
@route="chat.direct-messages"
@icon="users"
@translatedLabel={{i18n "chat.direct_messages.title"}}
aria-label={{i18n "chat.direct_messages.aria_label"}}
@ -65,7 +70,7 @@ export default class ChatFooter extends Component {
class={{concatClass
"btn-flat"
"c-footer__item"
(if (eq @activeTab "direct-messages") "--active")
(if (eq this.currentRouteName "chat.direct-messages") "--active")
}}
>
<UnreadDirectMessagesIndicator />
@ -74,7 +79,7 @@ export default class ChatFooter extends Component {
{{#if this.includeThreads}}
<DButton
@action={{fn @onClickTab "threads"}}
@route="chat.threads"
@icon="discourse-threads"
@translatedLabel={{i18n "chat.my_threads.title"}}
aria-label={{i18n "chat.my_threads.aria_label"}}
@ -82,7 +87,7 @@ export default class ChatFooter extends Component {
class={{concatClass
"btn-flat"
"c-footer__item"
(if (eq @activeTab "threads") "--active")
(if (eq this.currentRouteName "chat.threads") "--active")
}}
>
<UnreadThreadsIndicator />

View File

@ -12,6 +12,14 @@ export default class ChatDrawerRoutesChannel extends Component {
@service chatStateManager;
@service chatChannelsManager;
get backBtnRoute() {
if (this.chat.activeChannel?.isDirectMessageChannel) {
return "chat.direct-messages";
} else {
return "chat.channels";
}
}
@action
fetchChannel() {
if (!this.args.params?.channelId) {
@ -27,7 +35,7 @@ export default class ChatDrawerRoutesChannel extends Component {
<template>
<Navbar @onClick={{this.chat.toggleDrawer}} as |navbar|>
<navbar.BackButton />
<navbar.BackButton @route={{this.backBtnRoute}} />
<navbar.ChannelTitle @channel={{this.chat.activeChannel}} />
<navbar.Actions as |a|>
<a.ThreadsListButton @channel={{this.chat.activeChannel}} />

View File

@ -1,26 +1,14 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { eq } from "truth-helpers";
import i18n from "discourse-common/helpers/i18n";
import ChannelsListDirect from "discourse/plugins/chat/discourse/components/channels-list-direct";
import ChannelsListPublic from "discourse/plugins/chat/discourse/components/channels-list-public";
import Navbar from "discourse/plugins/chat/discourse/components/chat/navbar";
import ChatFooter from "discourse/plugins/chat/discourse/components/chat-footer";
import UserThreads from "discourse/plugins/chat/discourse/components/user-threads";
export default class ChatDrawerRoutesChannels extends Component {
@service chat;
@service chatStateManager;
@tracked activeTab = "channels";
@action
onClickTab(tab) {
this.activeTab = tab;
}
<template>
<Navbar @onClick={{this.chat.toggleDrawer}} as |navbar|>
<navbar.Title @title={{i18n "chat.heading"}} />
@ -33,19 +21,10 @@ export default class ChatDrawerRoutesChannels extends Component {
{{#if this.chatStateManager.isDrawerExpanded}}
<div class="chat-drawer-content">
{{#if (eq this.activeTab "channels")}}
<ChannelsListPublic />
{{else if (eq this.activeTab "direct-messages")}}
<ChannelsListDirect />
{{else if (eq this.activeTab "threads")}}
<UserThreads />
{{/if}}
<ChannelsListPublic />
</div>
<ChatFooter
@activeTab={{this.activeTab}}
@onClickTab={{this.onClickTab}}
/>
<ChatFooter />
{{/if}}
</template>
}

View File

@ -0,0 +1,30 @@
import Component from "@glimmer/component";
import { service } from "@ember/service";
import i18n from "discourse-common/helpers/i18n";
import ChannelsListDirect from "discourse/plugins/chat/discourse/components/channels-list-direct";
import Navbar from "discourse/plugins/chat/discourse/components/chat/navbar";
import ChatFooter from "discourse/plugins/chat/discourse/components/chat-footer";
export default class ChatDrawerRoutesChannels extends Component {
@service chat;
@service chatStateManager;
<template>
<Navbar @onClick={{this.chat.toggleDrawer}} as |navbar|>
<navbar.Title @title={{i18n "chat.heading"}} />
<navbar.Actions as |a|>
<a.ToggleDrawerButton />
<a.FullPageButton />
<a.CloseDrawerButton />
</navbar.Actions>
</Navbar>
{{#if this.chatStateManager.isDrawerExpanded}}
<div class="chat-drawer-content">
<ChannelsListDirect />
</div>
<ChatFooter />
{{/if}}
</template>
}

View File

@ -1,23 +1,17 @@
import Component from "@glimmer/component";
import { service } from "@ember/service";
import i18n from "discourse-common/helpers/i18n";
import I18n from "discourse-i18n";
import Navbar from "discourse/plugins/chat/discourse/components/chat/navbar";
import ChatFooter from "discourse/plugins/chat/discourse/components/chat-footer";
import UserThreads from "discourse/plugins/chat/discourse/components/user-threads";
export default class ChatDrawerRoutesThreads extends Component {
@service chat;
@service chatStateManager;
backButtonTitle = I18n.t("chat.return_to_list");
<template>
<Navbar @onClick={{this.chat.toggleDrawer}} as |navbar|>
<navbar.BackButton @title={{this.backButtonTitle}} />
<navbar.Title
@title={{i18n "chat.my_threads.title"}}
@icon="discourse-threads"
/>
<navbar.Title @title={{i18n "chat.heading"}} />
<navbar.Actions as |action|>
<action.ThreadsListButton />
<action.ToggleDrawerButton />
@ -31,5 +25,7 @@ export default class ChatDrawerRoutesThreads extends Component {
<UserThreads />
</div>
{{/if}}
<ChatFooter />
</template>
}

View File

@ -1,5 +1,4 @@
import Controller from "@ember/controller";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { FOOTER_NAV_ROUTES } from "discourse/plugins/chat/discourse/lib/chat-constants";
@ -24,10 +23,6 @@ export default class ChatController extends Controller {
return this.siteSettings.navigation_menu === "sidebar";
}
get activeTab() {
return this.router.currentRouteName.replace(/^chat\./, "");
}
get shouldUseChatFooter() {
return (
this.site.mobileView &&
@ -51,9 +46,4 @@ export default class ChatController extends Controller {
return modifierClasses.join(" ");
}
@action
onClickTab(tab) {
return this.router.transitionTo(`chat.${tab}`);
}
}

View File

@ -4,12 +4,14 @@ import ChatDrawerRoutesChannel from "discourse/plugins/chat/discourse/components
import ChatDrawerRoutesChannelThread from "discourse/plugins/chat/discourse/components/chat/drawer-routes/channel-thread";
import ChatDrawerRoutesChannelThreads from "discourse/plugins/chat/discourse/components/chat/drawer-routes/channel-threads";
import ChatDrawerRoutesChannels from "discourse/plugins/chat/discourse/components/chat/drawer-routes/channels";
import ChatDrawerRoutesDirectMessages from "discourse/plugins/chat/discourse/components/chat/drawer-routes/direct-messages";
import ChatDrawerRoutesMembers from "discourse/plugins/chat/discourse/components/chat/drawer-routes/members";
import ChatDrawerRoutesSettings from "discourse/plugins/chat/discourse/components/chat/drawer-routes/settings";
import ChatDrawerRoutesThreads from "discourse/plugins/chat/discourse/components/chat/drawer-routes/threads";
const ROUTES = {
"chat.index": { name: ChatDrawerRoutesChannels },
"chat.channels": { name: ChatDrawerRoutesChannels },
"chat.channel": { name: ChatDrawerRoutesChannel },
"chat.channel.index": { name: ChatDrawerRoutesChannel },
"chat.channel.thread": {
@ -48,6 +50,9 @@ const ROUTES = {
};
},
},
"chat.direct-messages": {
name: ChatDrawerRoutesDirectMessages,
},
"chat.threads": {
name: ChatDrawerRoutesThreads,
},

View File

@ -21,10 +21,7 @@
>
{{outlet}}
{{#if this.shouldUseChatFooter}}
<ChatFooter
@activeTab={{this.activeTab}}
@onClickTab={{this.onClickTab}}
/>
<ChatFooter />
{{/if}}
</div>
</div>

View File

@ -17,6 +17,15 @@
.c-unread-indicator.-urgent {
margin-left: 1rem;
}
&.--active {
.full-page-chat & {
.d-icon,
.d-button-label {
color: var(--quaternary);
}
}
}
}
}

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.describe "Drawer", type: :system do
fab!(:current_user) { Fabricate(:admin) }
fab!(:current_user) { Fabricate(:user) }
let(:chat_page) { PageObjects::Pages::Chat.new }
let(:channel_page) { PageObjects::Pages::ChatChannel.new }
let(:drawer_page) { PageObjects::Pages::ChatDrawer.new }
@ -225,4 +225,61 @@ RSpec.describe "Drawer", type: :system do
end
end
end
describe "with chat footer" do
it "opens channels list by default" do
visit("/")
chat_page.open_from_header
expect(drawer_page).to have_open_channels
end
it "shows footer nav when 2 or more tabs are accessible" do
visit("/")
chat_page.open_from_header
expect(page).to have_css(".chat-drawer .c-footer")
expect(page).to have_css(".chat-drawer .c-footer__item", count: 2)
end
it "hides footer nav when only channels are accessible" do
SiteSetting.direct_message_enabled_groups = Group::AUTO_GROUPS[:staff]
visit("/")
chat_page.open_from_header
expect(page).to have_no_css(".chat-drawer .c-footer")
end
context "when clicking footer nav items" do
fab!(:channel) { Fabricate(:chat_channel, threading_enabled: true) }
before do
SiteSetting.chat_threads_enabled = true
channel.add(current_user)
end
it "shows active state" do
visit("/")
chat_page.open_from_header
drawer_page.click_direct_messages
expect(page).to have_css("#c-footer-direct-messages.--active")
end
it "redirects to correct route" do
visit("/")
chat_page.open_from_header
drawer_page.click_direct_messages
expect(drawer_page).to have_open_direct_messages
drawer_page.click_channels
expect(drawer_page).to have_open_channels
drawer_page.click_user_threads
expect(drawer_page).to have_open_user_threads
end
end
end
end

View File

@ -63,6 +63,10 @@ module PageObjects
has_no_css?(".chat-channel-row.--threads .c-unread-indicator")
end
def click_channels
find("#c-footer-channels").click
end
def click_direct_messages
find("#c-footer-direct-messages").click
end
@ -96,6 +100,18 @@ module PageObjects
has_css?("#{VISIBLE_DRAWER} .c-channel-members")
end
def has_open_channels?
has_css?("#{VISIBLE_DRAWER} .public-channels")
end
def has_open_direct_messages?
has_css?("#{VISIBLE_DRAWER} .direct-message-channels")
end
def has_open_user_threads?
has_css?("#{VISIBLE_DRAWER} .c-user-threads")
end
def has_open_thread_list?
has_css?("#{VISIBLE_DRAWER} .chat-thread-list")
end