FIX: Make long thread titles readable (#25456)

When reaching the top of a thread, the full thread title will be displayed if it was too long to fit.
It works in mobile, drawer mode, and fullscreen.
---------

Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
This commit is contained in:
Jan Cernik 2024-01-30 10:18:00 -03:00 committed by GitHub
parent 283fe48243
commit ab326d10d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 203 additions and 87 deletions

View File

@ -150,6 +150,7 @@ export default class ChatThread extends Component {
this.isScrolling = false;
this.resetIdle();
this.atBottom = state.atBottom;
this.args.setFullTitle?.(state.atTop);
if (state.atBottom) {
this.fetchMoreMessages({ direction: FUTURE });

View File

@ -1,4 +1,5 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { array } from "@ember/helper";
import { action } from "@ember/object";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
@ -15,6 +16,12 @@ export default class ChatDrawerRoutesChannelThread extends Component {
@service chatChannelsManager;
@service chatHistory;
@tracked showThreadFullTitle = false;
get showfullTitle() {
return this.chatStateManager.isDrawerExpanded && this.showThreadFullTitle;
}
get backButton() {
const link = {
models: this.chat.activeChannel?.routeModels,
@ -65,8 +72,17 @@ export default class ChatDrawerRoutesChannelThread extends Component {
}
}
@action
setFullTitle(value) {
this.showThreadFullTitle = value;
}
<template>
<Navbar @onClick={{this.chat.toggleDrawer}} as |navbar|>
<Navbar
@onClick={{this.chat.toggleDrawer}}
@showFullTitle={{this.showfullTitle}}
as |navbar|
>
<navbar.BackButton
@title={{this.backButton.title}}
@route={{this.backButton.route}}
@ -92,6 +108,7 @@ export default class ChatDrawerRoutesChannelThread extends Component {
<ChatThread
@thread={{thread}}
@targetMessageId={{@params.messageId}}
@setFullTitle={{this.setFullTitle}}
/>
{{/if}}
{{/each}}

View File

@ -17,10 +17,7 @@ export default class ChatDrawerRoutesThreads extends Component {
<navbar.Title
@title={{i18n "chat.my_threads.title"}}
@icon="discourse-threads"
as |title|
>
<title.SubTitle @title={{this.chat.activeChannel.title}} />
</navbar.Title>
/>
<navbar.Actions as |action|>
<action.ThreadsListButton />
<action.ToggleDrawerButton />

View File

@ -1,29 +1,51 @@
import Component from "@glimmer/component";
import { hash } from "@ember/helper";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import concatClass from "discourse/helpers/concat-class";
import noop from "discourse/helpers/noop";
import ChatOnResize from "../../../modifiers/chat/on-resize";
import Actions from "./actions";
import BackButton from "./back-button";
import ChannelTitle from "./channel-title";
import Title from "./title";
const ChatNavbar = <template>
{{! template-lint-disable no-invalid-interactive }}
<div
class={{concatClass "c-navbar-container" (if @onClick "-clickable")}}
{{on "click" (if @onClick @onClick (noop))}}
>
<nav class="c-navbar">
{{yield
(hash
BackButton=BackButton
ChannelTitle=ChannelTitle
Title=Title
Actions=Actions
)
}}
</nav>
</div>
</template>;
export default class ChatNavbar extends Component {
@action
handleResize(entries) {
for (let entry of entries) {
const height = entry.target.clientHeight;
export default ChatNavbar;
requestAnimationFrame(() => {
document.documentElement.style.setProperty(
"--chat-header-expanded-offset",
`${height}px`
);
});
}
}
<template>
{{! template-lint-disable no-invalid-interactive }}
<div
class={{concatClass
"c-navbar-container"
(if @onClick "-clickable")
(if @showFullTitle "-full-title")
}}
{{on "click" (if @onClick @onClick (noop))}}
{{ChatOnResize this.handleResize}}
>
<nav class="c-navbar">
{{yield
(hash
BackButton=BackButton
ChannelTitle=ChannelTitle
Title=Title
Actions=Actions
)
}}
</nav>
</div>
</template>
}

View File

@ -1,16 +1,22 @@
import { hash } from "@ember/helper";
import concatClass from "discourse/helpers/concat-class";
import icon from "discourse-common/helpers/d-icon";
import SubTitle from "./sub-title";
const ChatNavbarTitle = <template>
<div title={{@title}} class="c-navbar__title">
<div
title={{@title}}
class={{concatClass "c-navbar__title" (if @showFullTitle "full-title")}}
>
{{#if (has-block)}}
{{if @icon (icon @icon)}}
{{@title}}
<span class="c-navbar__title-text">{{if @icon (icon @icon)}}
{{@title}}</span>
{{yield (hash SubTitle=SubTitle)}}
{{else}}
{{if @icon (icon @icon)}}
{{@title}}
<span class="c-navbar__title-text">{{if
@icon
(icon @icon)
}}{{@title}}</span>
{{/if}}
</div>
</template>;

View File

@ -1,19 +1,33 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { array } from "@ember/helper";
import { action } from "@ember/object";
import ThreadHeader from "discourse/plugins/chat/discourse/components/chat/thread/header";
import Thread from "discourse/plugins/chat/discourse/components/chat-thread";
const ChatRoutesChannelThread = <template>
<div class="c-routes-channel-thread">
{{#each (array @thread) as |thread|}}
<ThreadHeader @thread={{thread}} />
export default class ChatRoutesChannelThread extends Component {
@tracked showfullTitle = false;
<Thread
@thread={{thread}}
@targetMessageId={{@targetMessageId}}
@includeHeader={{true}}
/>
{{/each}}
</div>
</template>;
@action
setFullTitle(value) {
this.showfullTitle = value;
}
export default ChatRoutesChannelThread;
<template>
<div class="c-routes-channel-thread">
{{#each (array @thread) as |thread|}}
<ThreadHeader
@thread={{thread}}
@showFullTitle={{this.showfullTitle}}
/>
<Thread
@thread={{thread}}
@targetMessageId={{@targetMessageId}}
@includeHeader={{true}}
@setFullTitle={{this.setFullTitle}}
/>
{{/each}}
</div>
</template>
}

View File

@ -53,7 +53,7 @@ export default class ChatThreadHeader extends Component {
}
<template>
<Navbar as |navbar|>
<Navbar @showFullTitle={{@showFullTitle}} as |navbar|>
{{#if @thread}}
<navbar.BackButton
@route={{this.backLink.route}}

View File

@ -3,7 +3,8 @@
--full-page-border-radius: 12px;
--full-page-sidebar-width: 275px;
--channel-list-avatar-size: 30px;
--chat-header-offset: 46px;
--chat-header-offset: 45px;
--chat-header-expanded-offset: 0px;
}
// Very specific hack to ensure the contextual menu (copy/paste/...) is

View File

@ -7,7 +7,7 @@
overflow: hidden;
grid-area: main;
min-width: 250px;
@include chat-height;
@include chat-height(var(--chat-header-offset, 0px));
.chat-messages-scroll {
flex-grow: 1;

View File

@ -1,16 +1,15 @@
@mixin chat-height($inset: 0px) {
// desktop and mobile
// 46px is the height of the navbar
// -1px is for the bottom border of the chat navbar
height: calc(
var(--chat-vh, 1vh) * 100 - var(--header-offset, 0px) -
var(--composer-height, 0px) - var(--chat-header-offset, 0px)
var(--composer-height, 0px) - 1px - $inset
);
// mobile with keyboard opened
.keyboard-visible & {
height: calc(
var(--chat-vh, 1vh) * 100 - var(--header-offset, 0px) -
var(--chat-header-offset, 0px)
var(--chat-vh, 1vh) * 100 - var(--header-offset, 0px) - 1px - $inset
);
}
@ -18,7 +17,7 @@
.footer-nav-ipad & {
height: calc(
var(--chat-vh, 1vh) * 100 - var(--header-offset, 0px) -
var(--chat-header-offset, 0px) - var(--composer-height, 0px)
var(--composer-height, 0px) - 1px - $inset
);
}
}

View File

@ -1,59 +1,94 @@
.c-navbar {
.c-navbar-container {
position: relative;
border-bottom: 1px solid var(--primary-low);
background: var(--secondary);
box-sizing: border-box;
display: flex;
align-items: center;
width: 100%;
gap: 0.25rem;
z-index: z("composer", "content") - 1;
padding: 0 1rem;
&-container {
border-bottom: 1px solid var(--primary-low);
background: var(--secondary);
height: var(--chat-header-offset);
min-height: var(--chat-header-offset);
box-sizing: border-box;
display: flex;
z-index: z("composer", "content") - 1;
padding-inline: 1rem;
&.-clickable {
cursor: pointer;
}
&.-clickable {
cursor: pointer;
&.-full-title {
.c-navbar__title {
min-height: var(--chat-header-offset);
}
.c-navbar__title,
.c-navbar__title-text {
height: auto;
overflow: visible;
white-space: normal;
text-overflow: unset;
}
}
}
.c-navbar {
display: flex;
align-items: flex-start;
width: 100%;
gap: 0.25rem;
position: relative;
.single-select-header {
padding: 0.3675rem 0.584rem;
}
}
.c-navbar__channel-title {
.c-navbar__back-button {
height: var(--chat-header-offset);
}
.c-navbar__channel-title {
@include ellipsis();
font-weight: 700;
height: var(--chat-header-offset);
display: flex;
align-items: center;
}
.c-navbar__title {
display: flex;
align-items: center;
@include ellipsis();
height: var(--chat-header-offset);
&-text {
@include ellipsis();
font-weight: 700;
}
max-width: 100%;
vertical-align: middle;
padding-block: 5px;
.c-navbar__title {
@include ellipsis();
font-weight: 700;
.chat-drawer & {
padding-left: 1rem;
> .d-icon {
margin-right: 5px;
}
}
.c-navbar__back-button ~ .c-navbar__title {
padding-left: 0;
.chat-drawer & {
padding-left: 1rem;
}
.c-navbar__sub-title {
line-height: var(--line-height-small);
font-size: var(--font-down-1-rem);
font-weight: normal;
.d-icon {
vertical-align: middle;
}
}
.c-navbar__threads-list-button {
gap: 0.25rem;
.c-navbar__sub-title {
line-height: var(--line-height-small);
font-size: var(--font-down-1-rem);
font-weight: normal;
}
&.has-unreads {
.d-icon-discourse-threads {
color: var(--tertiary-med-or-tertiary);
}
.c-navbar__threads-list-button {
gap: 0.25rem;
&.has-unreads {
.d-icon-discourse-threads {
color: var(--tertiary-med-or-tertiary);
}
}
}
@ -63,4 +98,12 @@
margin-left: auto;
display: flex;
align-items: center;
> .btn {
height: var(--chat-header-offset);
}
}
.c-navbar__back-button ~ .c-navbar__title {
padding-left: 0;
}

View File

@ -2,7 +2,7 @@
display: flex;
flex-direction: column;
position: relative;
@include chat-height;
@include chat-height(var(--chat-header-expanded-offset, 0px));
&__body {
overflow-y: scroll;
@ -12,5 +12,6 @@
overscroll-behavior: contain;
display: flex;
flex-direction: column-reverse;
transition: padding-top 0.2s ease-in-out;
}
}

View File

@ -2,7 +2,9 @@
display: flex;
flex-direction: column;
position: relative;
@include chat-height(env(safe-area-inset-bottom));
@include chat-height(
calc(var(--chat-header-offset) + env(safe-area-inset-bottom))
);
&__items {
overflow-y: scroll;

View File

@ -10,6 +10,19 @@
&__back-button {
align-self: stretch;
}
&.-full-title {
.c-navbar {
&__actions,
&__back-button {
height: calc(var(--chat-header-offset) - 2px) !important;
}
&__title {
padding-block: calc(1rem + 2px);
}
}
left: 0.25rem;
width: calc(100% - 0.5rem);
}
.c-navbar__title {
.c-routes-direct-messages &,