FEATURE: Chat thread header indicator improvements (#21807)

This changes the thread header positioning of the
unread indicator to match the designs based on the route:

1. When the channel is open, show the indicator of # unread
   threads with the icon
2. When the threads list is open, show no indicator since
   you are on the list and can see which threads are unread
3. When a single thread is open, show the unread threads
   indicator along with a left < back button, with a label
   to show that this goes back to ongoing discussions

Drawer changes to come in another PR.
This commit is contained in:
Martin Brennan 2023-05-30 10:10:07 +02:00 committed by GitHub
parent c2493a8f1c
commit 6ec6cfccf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 88 additions and 26 deletions

View File

@ -1,6 +1,6 @@
<div class="chat-drawer-header__right-actions">
<div class="chat-drawer-header__top-line">
{{#if this.chat.activeChannel.threadingEnabled}}
{{#if this.showThreadsListButton}}
<Chat::Thread::ThreadsListButton @channel={{this.chat.activeChannel}} />
{{/if}}

View File

@ -3,5 +3,8 @@ import { inject as service } from "@ember/service";
export default class ChatDrawerHeaderRightActions extends Component {
@service chat;
@service chatStateManager;
get showThreadsListButton() {
return this.chat.activeChannel?.threadingEnabled;
}
}

View File

@ -40,7 +40,7 @@
/>
{{/if}}
{{#if @channel.threadingEnabled}}
{{#if this.showThreadsListButton}}
<Chat::Thread::ThreadsListButton @channel={{@channel}} />
{{/if}}
</div>

View File

@ -4,8 +4,17 @@ import Component from "@glimmer/component";
export default class ChatFullPageHeader extends Component {
@service site;
@service chatStateManager;
@service router;
get displayed() {
return this.args.displayed ?? true;
}
get showThreadsListButton() {
return (
this.args.channel.threadingEnabled &&
this.router.currentRoute.name !== "chat.channel.threads" &&
this.router.currentRoute.name !== "chat.channel.thread"
);
}
}

View File

@ -1,5 +1,9 @@
{{#if this.showUnreadIndicator}}
<div class="chat-thread-header-unread-indicator">
<div
class="chat-thread-header-unread-indicator"
aria-label={{i18n "chat.unread_threads_count" count=this.unreadCountLabel}}
title={{i18n "chat.unread_threads_count" count=this.unreadCountLabel}}
>
<div class="chat-thread-header-unread-indicator__number-wrap">
<div
class="chat-thread-header-unread-indicator__number"

View File

@ -1,12 +1,19 @@
import Component from "@glimmer/component";
import { inject as service } from "@ember/service";
export default class ChatThreadHeaderUnreadIndicator extends Component {
@service currentUser;
get currentUserInDnD() {
return this.currentUser.isInDoNotDisturb();
}
get unreadCount() {
return this.args.channel.unreadThreadCount;
}
get showUnreadIndicator() {
return this.unreadCount > 0;
return !this.currentUserInDnD && this.unreadCount > 0;
}
get unreadCountLabel() {

View File

@ -1,4 +1,18 @@
<div class="chat-thread-header">
<div class="chat-thread-header__left-buttons">
{{#if @thread}}
<LinkTo
class="chat-thread__back-to-list btn-flat btn btn-icon no-text"
@route="chat.channel.threads"
@models={{@channel.routeModels}}
title={{i18n "chat.return_to_threads_list"}}
>
<Chat::Thread::HeaderUnreadIndicator @channel={{@channel}} />
{{d-icon "chevron-left"}}
</LinkTo>
{{/if}}
</div>
<span class="chat-thread-header__label overflow-ellipsis">
{{replace-emoji this.label}}
</span>

View File

@ -9,7 +9,5 @@
>
{{d-icon "discourse-threads"}}
{{#unless this.currentUserInDnD}}
<Chat::Thread::HeaderUnreadIndicator @channel={{@channel}} />
{{/unless}}
<Chat::Thread::HeaderUnreadIndicator @channel={{@channel}} />
</LinkTo>

View File

@ -1,10 +1,3 @@
import { inject as service } from "@ember/service";
import Component from "@glimmer/component";
export default class ChatThreadsListButton extends Component {
@service currentUser;
get currentUserInDnD() {
return this.currentUser.isInDoNotDisturb();
}
}
export default class ChatThreadsListButton extends Component {}

View File

@ -2,8 +2,8 @@
position: relative;
display: flex;
align-items: center;
border: 1px solid var(--blend-primary-secondary-5);
border-radius: 5px;
padding: 0.5rem 0;
@include chat-channel-header-button;
@ -11,6 +11,12 @@
.d-icon {
color: var(--tertiary-med-or-tertiary);
}
&:hover {
.d-icon {
color: var(--tertiary-med-or-tertiary);
}
}
}
.d-icon {

View File

@ -6,10 +6,21 @@
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
padding-inline: 1rem;
padding-inline: 0.5rem;
.chat-thread__back-to-list {
padding: 0.5rem 0;
margin-right: 0.5rem;
}
&__buttons {
display: flex;
margin-left: auto;
}
&__left-buttons {
display: flex;
flex-direction: row;
align-items: center;
}
}

View File

@ -10,7 +10,7 @@
.chat-thread-list-item {
@include thread-list-item;
cursor: pointer;
margin: 0.5rem 0.25rem 0.25rem;
margin: 0.25rem;
& + .chat-thread-list-item {
margin-top: 0;

View File

@ -251,6 +251,9 @@ en:
select: "Select"
return_to_list: "Return to channels list"
return_to_threads_list: "Return to ongoing discussions"
unread_threads_count:
one: "You have %{count} unread discussion"
other: "You have %{count} unread discussions"
scroll_to_bottom: "Scroll to bottom"
scroll_to_new_messages: "See new messages"
sound:

View File

@ -24,6 +24,21 @@ module PageObjects
header.find(".chat-thread__close").click
end
def back_to_list
header.find(".chat-thread__back-to-list").click
end
def has_no_unread_list_indicator?
has_no_css?(".chat-thread__back-to-list .chat-thread-header-unread-indicator")
end
def has_unread_list_indicator?(count:)
has_css?(
".chat-thread__back-to-list .chat-thread-header-unread-indicator .chat-thread-header-unread-indicator__number-wrap",
text: count.to_s,
)
end
def has_no_loading_skeleton?
has_no_css?(".chat-thread__messages .chat-skeleton")
end

View File

@ -39,28 +39,27 @@ describe "Thread tracking state | full page", type: :system, js: true do
chat_page.visit_channel(channel)
channel_page.open_thread_list
thread_list_page.item_by_id(thread.id).click
expect(channel_page).to have_no_unread_thread_indicator
channel_page.open_thread_list
expect(thread_page).to have_no_unread_list_indicator
thread_page.back_to_list
expect(thread_list_page).to have_no_unread_item(thread.id)
end
it "shows unread indicators for the header icon and the list when a new unread arrives" do
it "shows unread indicators for the header of the list when a new unread arrives" do
message_1.trash!
chat_page.visit_channel(channel)
channel_page.open_thread_list
expect(channel_page).to have_no_unread_thread_indicator
expect(thread_list_page).to have_no_unread_item(thread.id)
Fabricate(:chat_message, chat_channel: channel, thread: thread)
expect(channel_page).to have_unread_thread_indicator(count: 1)
expect(thread_list_page).to have_unread_item(thread.id)
end
it "does not change the unread indicator for the header icon when the user is not a member of the thread" do
thread.remove(current_user)
chat_page.visit_channel(channel)
channel_page.open_thread_list
expect(channel_page).to have_no_unread_thread_indicator
Fabricate(:chat_message, chat_channel: channel, thread: thread)
expect(channel_page).to have_no_unread_thread_indicator
channel_page.open_thread_list
expect(thread_list_page).to have_no_unread_item(thread.id)
end
end