UX: remove last reply from My Threads preview + restyle (#25568)
On mobile, when viewing the My Threads area, each thread will show: - The avatar of the last responder in the thread, overlaid with the chat thread symbol to visually distinguish this area from DMs. - Either the thread title, where applicable, or the first message of the thread, truncated to fit on one line. - The channel where the thread originated. - The last message sent in the thread, truncated to fit on one line. - When the last message was sent in the thread. --------- Co-authored-by: David Battersby <info@davidbattersby.com>
This commit is contained in:
parent
0e3a8b15f5
commit
cfd72fa65c
|
@ -19,6 +19,10 @@ export default class ChatChannelIcon extends Component {
|
|||
return htmlSafe(`color: #${this.args.channel.chatable.color}`);
|
||||
}
|
||||
|
||||
get isThreadsList() {
|
||||
return this.args.thread ?? false;
|
||||
}
|
||||
|
||||
<template>
|
||||
{{#if @channel.isDirectMessageChannel}}
|
||||
<div class="chat-channel-icon">
|
||||
|
@ -44,6 +48,19 @@ export default class ChatChannelIcon extends Component {
|
|||
{{/if}}
|
||||
</span>
|
||||
</div>
|
||||
{{else if this.isThreadsList}}
|
||||
<div class="chat-channel-icon">
|
||||
<div class="chat-channel-icon --avatar">
|
||||
<ChatUserAvatar
|
||||
@user={{@thread.originalMessage.user}}
|
||||
@interactive={{true}}
|
||||
@showPresence={{false}}
|
||||
/>
|
||||
<div class="avatar-flair --threads">
|
||||
{{icon "discourse-threads"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
}
|
||||
|
|
|
@ -24,14 +24,14 @@ export default class ChatThreadHeader extends Component {
|
|||
route = "chat.channel.threads";
|
||||
title = I18n.t("chat.return_to_threads_list");
|
||||
models = this.channel?.routeModels;
|
||||
} else if (!this.currentUser.isInDoNotDisturb() && this.unreadCount > 0) {
|
||||
route = "chat.channel.threads";
|
||||
title = I18n.t("chat.return_to_threads_list");
|
||||
models = this.channel?.routeModels;
|
||||
} else if (prevPage === "chat.threads") {
|
||||
route = "chat.threads";
|
||||
title = I18n.t("chat.my_threads.title");
|
||||
models = [];
|
||||
} else if (!this.currentUser.isInDoNotDisturb() && this.unreadCount > 0) {
|
||||
route = "chat.channel.threads";
|
||||
title = I18n.t("chat.return_to_threads_list");
|
||||
models = this.channel?.routeModels;
|
||||
} else {
|
||||
route = "chat.channel.index";
|
||||
title = I18n.t("chat.return_to_channel");
|
||||
|
@ -53,6 +53,12 @@ export default class ChatThreadHeader extends Component {
|
|||
return this.channel?.threadsManager?.unreadThreadCount;
|
||||
}
|
||||
|
||||
get showThreadUnreadIndicator() {
|
||||
return (
|
||||
this.backLink.route === "chat.channel.threads" && this.unreadCount > 0
|
||||
);
|
||||
}
|
||||
|
||||
<template>
|
||||
<Navbar @showFullTitle={{@showFullTitle}} as |navbar|>
|
||||
{{#if (and this.channel.threadingEnabled @thread)}}
|
||||
|
@ -61,7 +67,9 @@ export default class ChatThreadHeader extends Component {
|
|||
@routeModels={{this.backLink.models}}
|
||||
@title={{this.backLink.title}}
|
||||
>
|
||||
{{#if this.showThreadUnreadIndicator}}
|
||||
<ChatThreadHeaderUnreadIndicator @channel={{this.channel}} />
|
||||
{{/if}}
|
||||
{{icon "chevron-left"}}
|
||||
</navbar.BackButton>
|
||||
{{/if}}
|
||||
|
|
|
@ -3,15 +3,18 @@ import { cached } from "@glimmer/tracking";
|
|||
import { service } from "@ember/service";
|
||||
import i18n from "discourse-common/helpers/i18n";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
import ChannelIcon from "discourse/plugins/chat/discourse/components/channel-icon";
|
||||
import ChannelTitle from "discourse/plugins/chat/discourse/components/channel-title";
|
||||
import List from "discourse/plugins/chat/discourse/components/chat/list";
|
||||
import ThreadIndicator from "discourse/plugins/chat/discourse/components/chat-message-thread-indicator";
|
||||
import ThreadTitle from "discourse/plugins/chat/discourse/components/thread-title";
|
||||
import ThreadPreview from "discourse/plugins/chat/discourse/components/user-threads/preview";
|
||||
|
||||
export default class UserThreads extends Component {
|
||||
@service chat;
|
||||
@service chatApi;
|
||||
@service chatChannelsManager;
|
||||
@service site;
|
||||
|
||||
@cached
|
||||
get threadsCollection() {
|
||||
|
@ -41,14 +44,23 @@ export default class UserThreads extends Component {
|
|||
>
|
||||
<list.Item as |thread|>
|
||||
<div class="c-user-thread" data-id={{thread.id}}>
|
||||
<ThreadTitle @thread={{thread}} />
|
||||
{{#if this.site.mobileView}}
|
||||
<ChannelIcon @thread={{thread}} />
|
||||
{{/if}}
|
||||
|
||||
<ChannelTitle @channel={{thread.channel}} />
|
||||
<ThreadTitle @thread={{thread}} />
|
||||
|
||||
{{#if this.site.mobileView}}
|
||||
<ThreadPreview @preview={{thread.preview}} />
|
||||
{{else}}
|
||||
<ThreadIndicator
|
||||
@message={{thread.originalMessage}}
|
||||
@interactiveUser={{false}}
|
||||
@interactiveThread={{false}}
|
||||
tabindex="-1"
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
</list.Item>
|
||||
<list.EmptyState>
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import Component from "@glimmer/component";
|
||||
import formatDate from "discourse/helpers/format-date";
|
||||
|
||||
export default class ThreadPreview extends Component {
|
||||
get lastReplyDate() {
|
||||
return formatDate(this.args.preview.lastReplyCreatedAt, { leaveAgo: true });
|
||||
}
|
||||
|
||||
<template>
|
||||
<span class="chat-message-thread-indicator__last-reply-timestamp">
|
||||
{{this.lastReplyDate}}
|
||||
</span>
|
||||
<div class="c-user-thread__excerpt">
|
||||
<div class="c-user-thread__excerpt-poster">
|
||||
{{@preview.lastReplyUser.username}}
|
||||
</div>
|
||||
<span>:</span>
|
||||
<span class="c-user-thread__excerpt-text">
|
||||
{{@preview.lastReplyExcerpt}}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
}
|
|
@ -1,9 +1,67 @@
|
|||
.chat-user-threads {
|
||||
.chat__thread-title {
|
||||
justify-content: space-between;
|
||||
.c-user-thread {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"avatar category timestamp"
|
||||
"avatar title indicator"
|
||||
"avatar excerpt excerpt";
|
||||
grid-template-columns: auto 1fr auto;
|
||||
grid-column-gap: 0.75em;
|
||||
margin-inline: 0;
|
||||
padding: 0.5rem 1.5rem;
|
||||
|
||||
.chat-channel-icon {
|
||||
grid-area: avatar;
|
||||
position: relative;
|
||||
|
||||
.avatar {
|
||||
margin-top: 4px;
|
||||
width: var(--channel-list-avatar-size);
|
||||
height: var(--channel-list-avatar-size);
|
||||
}
|
||||
}
|
||||
|
||||
.c-user-thread {
|
||||
margin-inline: 1.5rem;
|
||||
.avatar-flair.--threads {
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
right: -3px;
|
||||
background: var(--primary-low);
|
||||
border-radius: 50%;
|
||||
padding: 0.2em;
|
||||
line-height: var(--line-height-small);
|
||||
border: 2px solid var(--secondary-very-high);
|
||||
color: var(--primary-high);
|
||||
}
|
||||
|
||||
.chat__thread-title-container {
|
||||
@include ellipsis;
|
||||
grid-area: title;
|
||||
.chat__thread-title {
|
||||
&__name {
|
||||
@include ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat-channel-title {
|
||||
grid-area: category;
|
||||
}
|
||||
|
||||
.chat-message-thread-indicator__last-reply-timestamp {
|
||||
grid-area: timestamp;
|
||||
font-size: var(--font-down-2-rem);
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.c-user-thread__excerpt {
|
||||
@include ellipsis;
|
||||
grid-area: excerpt;
|
||||
display: flex;
|
||||
color: var(--primary-high);
|
||||
}
|
||||
|
||||
.c-user-thread__excerpt-text {
|
||||
margin-left: 0.25em;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -244,4 +244,22 @@ RSpec.describe "User threads", type: :system do
|
|||
expect(user_threads_page).to have_threads
|
||||
end
|
||||
end
|
||||
|
||||
context "when in mobile", mobile: true do
|
||||
before do
|
||||
chat_thread_chain_bootstrap(channel: channel_1, users: [current_user, Fabricate(:user)])
|
||||
end
|
||||
|
||||
it "has the expected UI elements" do
|
||||
chat_page.visit_user_threads
|
||||
|
||||
expect(user_threads_page).to have_threads(count: 1)
|
||||
expect(user_threads_page).to have_css(".chat-user-avatar")
|
||||
expect(user_threads_page).to have_css(".chat__thread-title__name")
|
||||
expect(user_threads_page).to have_css(".chat-channel-name")
|
||||
expect(user_threads_page).to have_css(".c-user-thread__excerpt")
|
||||
expect(user_threads_page).to have_css(".c-user-thread__excerpt-poster")
|
||||
expect(user_threads_page).to have_css(".c-user-thread .relative-date")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue