FIX: limits max height to viewport on channel only (#21539)

Before this commit chat was applying a fixed height on everything under the `/chat` route. It's only really needed on the channel page with the composer at the bottom of the page.

This commits makes the following changes:
- moves height limitation from `#main-outlet-wrapper` to `.chat-channel`
- makes browse channel page and members list page full height and rely on main document scrollbar
- adds height computation for draft header and direct message creator block to ensure the height is correct when creating a draft channel
- makes chat index full height to rely on the browser scrollbar. As a result the <kbd> + </kbd> button used on mobile to create a direct message as been moved out of `<ChannelsList>` into the chat index template
- sidebar height was relying on chat setting a max height, as a result the height computation of sidebar has been changed to work correctly, especially with an opened keyboard on mobile or ipad
This commit is contained in:
Joffrey JAFFEUX 2023-05-15 11:46:33 +02:00 committed by GitHub
parent 9a2780397f
commit 5ce0697348
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 151 additions and 159 deletions

View File

@ -31,18 +31,21 @@
@include unselectable; @include unselectable;
// 100dvh with fallback for old browsers // 1dvh with fallback for old browsers
--100dvh: 100vh; --1dvh: 1vh;
@supports (height: 100dvh) { @supports (height: 1dvh) {
--100dvh: 100dvh; --1dvh: 1dvh;
} }
height: calc(var(--100dvh) - var(--header-offset, 0px)); height: calc(
var(--composer-vh, var(--1dvh)) * 100 - var(--header-offset, 0px)
);
.footer-nav-ipad & { .footer-nav-ipad & {
top: calc(var(--header-offset) + var(--footer-nav-height)); top: calc(var(--header-offset) + var(--footer-nav-height));
height: calc( height: calc(
var(--100dvh) - var(--header-offset, 0px) - var(--footer-nav-height, 0px) var(--composer-vh, var(--1dvh)) * 100 - var(--header-offset, 0px) -
var(--footer-nav-height, 0px)
); );
} }

View File

@ -1,10 +1,8 @@
{{#if {{#if this.showMobileDirectMessageButton}}
(and this.showMobileDirectMessageButton this.canCreateDirectMessageChannel)
}}
<LinkTo <LinkTo
@route="chat.draft-channel" @route="chat.draft-channel"
class="btn-flat open-draft-channel-page-btn keep-mobile-sidebar-open btn-floating" class="btn-flat open-draft-channel-page-btn keep-mobile-sidebar-open btn-floating"
title={{i18n this.createDirectMessageChannelLabel}} title={{i18n "chat.direct_messages.new"}}
> >
{{d-icon "plus"}} {{d-icon "plus"}}
</LinkTo> </LinkTo>
@ -62,6 +60,7 @@
/> />
{{/each}} {{/each}}
{{/if}} {{/if}}
</div> </div>
{{/if}} {{/if}}

View File

@ -26,7 +26,7 @@ export default class ChannelsList extends Component {
} }
get showMobileDirectMessageButton() { get showMobileDirectMessageButton() {
return this.site.mobileView && this.showDirectMessageChannels; return this.site.mobileView && this.canCreateDirectMessageChannel;
} }
get inSidebar() { get inSidebar() {

View File

@ -1,12 +1,3 @@
{{#if this.chatProgressBarContainer}}
{{#in-element this.chatProgressBarContainer}}
<DProgressBar
@key="browse-list"
@isLoading={{this.channelsCollection.loading}}
/>
{{/in-element}}
{{/if}}
<div class="chat-browse-view__header chat-full-page-header"> <div class="chat-browse-view__header chat-full-page-header">
{{#if this.site.mobileView}} {{#if this.site.mobileView}}
<LinkTo <LinkTo
@ -75,6 +66,10 @@
</div> </div>
</div> </div>
{{else if this.channelsCollection.length}} {{else if this.channelsCollection.length}}
<LoadMore
@selector=".chat-channel-card"
@action={{this.channelsCollection.loadMore}}
>
<div class="chat-browse-view__content_wrapper"> <div class="chat-browse-view__content_wrapper">
<div class="chat-browse-view__content"> <div class="chat-browse-view__content">
<div class="chat-browse-view__cards"> <div class="chat-browse-view__cards">
@ -82,11 +77,12 @@
<ChatChannelCard @channel={{channel}} /> <ChatChannelCard @channel={{channel}} />
{{/each}} {{/each}}
</div> </div>
</div>
</div>
{{#unless this.channelsCollection.loading}} <ConditionalLoadingSpinner
<OnVisibilityAction @action={{action "onScroll"}} /> @condition={{this.channelsCollection.loading}}
{{/unless}} />
</div> </LoadMore>
</div>
{{/if}} {{/if}}
</div> </div>

View File

@ -1,10 +1,8 @@
{{#if this.chatProgressBarContainer}}
{{#in-element this.chatProgressBarContainer}}
<DProgressBar @key="members-view" @isLoading={{this.members.loading}} />
{{/in-element}}
{{/if}}
{{#if (gt this.channel.membershipsCount 0)}} {{#if (gt this.channel.membershipsCount 0)}}
<LoadMore
@selector=".channel-members-view__list-item"
@action={{this.loadMore}}
>
<div class="channel-members-view-wrapper"> <div class="channel-members-view-wrapper">
<div <div
class={{concat class={{concat
@ -22,11 +20,7 @@
{{d-icon "search"}} {{d-icon "search"}}
</div> </div>
<div <div class="channel-members-view__list-container">
class="channel-members-view__list-container"
{{on "scroll" (action "loadMore")}}
>
<div role="list" class="channel-members-view__list"> <div role="list" class="channel-members-view__list">
{{#each this.members as |membership|}} {{#each this.members as |membership|}}
<div class="channel-members-view__list-item"> <div class="channel-members-view__list-item">
@ -40,6 +34,8 @@
</div> </div>
</div> </div>
</div> </div>
<ConditionalLoadingSpinner @condition={{this.members.loading}} />
</LoadMore>
{{else}} {{else}}
<div class="channel-members-view-wrapper"> <div class="channel-members-view-wrapper">
{{i18n "chat.channel.no_memberships"}} {{i18n "chat.channel.no_memberships"}}

View File

@ -1,6 +1,10 @@
<div class="chat-draft"> <div class="chat-draft">
{{#if this.site.mobileView}} {{#if this.site.mobileView}}
<header class="chat-draft-header"> <header
class="chat-draft-header"
{{did-insert this.setChatDraftHeaderHeight}}
{{will-destroy this.unsetChatDraftHeaderHeight}}
>
<FlatButton <FlatButton
@class="chat-draft-header__btn btn" @class="chat-draft-header__btn btn"
@icon="chevron-left" @icon="chevron-left"

View File

@ -14,6 +14,22 @@ export default class ChatDraftChannelScreen extends Component {
return this.router.transitionTo("chat.index"); return this.router.transitionTo("chat.index");
} }
@action
setChatDraftHeaderHeight(element) {
document.documentElement.style.setProperty(
"--chat-draft-header-height",
`${element.clientHeight}px`
);
}
@action
unsetChatDraftHeaderHeight() {
document.documentElement.style.setProperty(
"--chat-draft-header-height",
"0px"
);
}
@action @action
onChangeSelectedUsers(users) { onChangeSelectedUsers(users) {
this._fetchPreviewedChannel(users); this._fetchPreviewedChannel(users);

View File

@ -5,7 +5,11 @@
{{/if}} {{/if}}
{{#if (and this.channel.isDraft (not this.isLoading))}} {{#if (and this.channel.isDraft (not this.isLoading))}}
<div class="direct-message-creator"> <div
class="direct-message-creator"
{{did-insert this.setDirectMessageCreatorHeight}}
{{will-destroy this.unsetDirectMessageCreatorHeight}}
>
<div <div
class="filter-area {{if this.isFilterFocused 'is-focused'}}" class="filter-area {{if this.isFilterFocused 'is-focused'}}"
role="button" role="button"

View File

@ -126,6 +126,22 @@ export default Component.extend({
}); });
}, },
@action
setDirectMessageCreatorHeight(element) {
document.documentElement.style.setProperty(
"--chat-direct-message-creator-height",
`${element.clientHeight}px`
);
},
@action
unsetDirectMessageCreatorHeight() {
document.documentElement.style.setProperty(
"--chat-direct-message-creator-height",
"0px"
);
},
@action @action
onFilterInput(term) { onFilterInput(term) {
this.set("term", term); this.set("term", term);

View File

@ -428,8 +428,7 @@ body.has-full-page-chat {
} }
} }
.chat-messages-scroll, .chat-messages-scroll {
.chat-channel {
box-sizing: border-box; box-sizing: border-box;
height: 100%; height: 100%;
} }
@ -574,30 +573,13 @@ html.has-full-page-chat {
height: 100%; height: 100%;
width: 100%; width: 100%;
&.keyboard-visible body #main-outlet .full-page-chat {
padding-bottom: 0.2rem;
}
body { body {
height: 100%; height: 100%;
width: 100%; width: 100%;
&.footer-nav-ipad {
#main-outlet-wrapper {
grid-template-rows: calc(
var(--chat-vh, 1vh) * 100 - var(--header-offset, 0px) -
var(--footer-nav-height, 0px)
);
}
}
#main-outlet { #main-outlet {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
max-height: calc(
var(--chat-vh, 1vh) * 100 - var(--header-offset, 0px) -
var(--composer-height, 0px)
);
.full-page-chat { .full-page-chat {
height: 100%; height: 100%;
@ -620,32 +602,12 @@ html.has-full-page-chat {
// these need to apply to desktop too, because iPads // these need to apply to desktop too, because iPads
&.discourse-touch { &.discourse-touch {
// iPad web
#main-outlet-wrapper {
// restrict the row height, including when virtual keyboard is open
grid-template-rows: calc(
var(--chat-vh, 1vh) * 100 - var(--header-offset, 0px)
);
.sidebar-wrapper {
// prevents sidebar from overflowing behind the virtual keyboard
height: 100%;
}
}
.full-page-chat, .full-page-chat,
.chat-channel, .chat-channel,
#main-outlet { #main-outlet {
// allows containers to shrink to fit // allows containers to shrink to fit
min-height: 0; min-height: 0;
} }
#main-outlet {
// limits height for iPad
max-height: calc(
100vh - calc(var(--header-offset) + var(--composer-ipad-padding))
);
}
} }
[data-popper-reference-hidden] { [data-popper-reference-hidden] {
visibility: hidden; visibility: hidden;

View File

@ -1,16 +1,7 @@
.chat-browse-view { .chat-browse-view {
position: relative; position: relative;
height: calc(100vh - var(--header-offset) - var(--chat-header-offset));
padding-top: 1em;
padding-bottom: 41px;
box-sizing: border-box; box-sizing: border-box;
overflow-y: scroll; padding: 1rem;
@include chat-scrollbar();
@include breakpoint(mobile-large) {
padding-right: 1rem; //fix for different scroll behaviour on mobile where overflow-y:scroll acts like auto
}
&__header { &__header {
display: flex; display: flex;
@ -28,18 +19,14 @@
} }
&__content_wrapper { &__content_wrapper {
margin: 2rem 0 0 1rem;
box-sizing: border-box; box-sizing: border-box;
@include breakpoint(tablet) {
margin-top: 1rem; margin-top: 1rem;
} }
}
&__cards { &__cards {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
grid-gap: 2.5rem; grid-gap: 2rem;
@include breakpoint(tablet) { @include breakpoint(tablet) {
grid-template-columns: repeat(1, 1fr); grid-template-columns: repeat(1, 1fr);
@ -51,7 +38,6 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: end; align-items: end;
margin: 0 0 0 1rem;
@include breakpoint(tablet) { @include breakpoint(tablet) {
flex-direction: column; flex-direction: column;

View File

@ -101,10 +101,6 @@ input.channel-members-view__search-input {
flex-direction: column; flex-direction: column;
margin-top: 1em; margin-top: 1em;
box-sizing: border-box; box-sizing: border-box;
min-height: 1px;
overflow-y: auto;
height: 100%;
@include chat-scrollbar();
} }
.channel-members-view__list-item { .channel-members-view__list-item {

View File

@ -7,6 +7,19 @@
grid-area: main; grid-area: main;
width: 100%; width: 100%;
min-width: 250px; min-width: 250px;
height: calc(
var(--chat-vh, 1vh) * 100 - var(--header-offset, 0px) -
var(--composer-height, 0px) - var(--chat-draft-header-height, 0px) -
var(--chat-direct-message-creator-height, 0px)
);
.footer-nav-ipad & {
height: calc(
var(--chat-vh, 1vh) * 100 - var(--header-offset, 0px) -
var(--footer-nav-height, 0px) - var(--chat-draft-header-height, 0px) -
var(--chat-direct-message-creator-height, 0px)
);
}
.open-drawer-btn, .open-drawer-btn,
.open-thread-list-btn { .open-thread-list-btn {

View File

@ -251,4 +251,5 @@ a.chat-drawer-header__title {
height: 100%; height: 100%;
min-height: 1px; min-height: 1px;
padding-bottom: 0.25em; padding-bottom: 0.25em;
position: relative;
} }

View File

@ -1,3 +1,31 @@
.btn-floating.open-draft-channel-page-btn {
position: fixed;
background: var(--tertiary);
bottom: 2rem;
right: 2rem;
border-radius: 50%;
font-size: var(--font-up-4);
padding: 1rem;
transition: transform 0.25s ease, box-shadow 0.25s ease;
z-index: z("usercard");
box-shadow: 0px 5px 5px -1px rgba(0, 0, 0, 0.25);
.d-icon {
color: var(--primary-very-low);
}
&:active {
box-shadow: 0px 0px 5px -1px rgba(0, 0, 0, 0.25);
transform: scale(0.9);
}
&:focus {
@include default-focus;
border-color: var(--quaternary);
outline-color: var(--quaternary);
}
}
.channels-list { .channels-list {
overflow-y: auto; overflow-y: auto;
overscroll-behavior: contain; overscroll-behavior: contain;

View File

@ -76,32 +76,4 @@
} }
} }
} }
.btn-floating.open-draft-channel-page-btn {
position: absolute;
background: var(--tertiary);
bottom: 2.5rem;
right: 2.5rem;
border-radius: 50%;
font-size: var(--font-up-4);
padding: 1rem;
transition: transform 0.25s ease, box-shadow 0.25s ease;
z-index: z("usercard");
box-shadow: 0px 5px 5px -1px rgba(0, 0, 0, 0.25);
.d-icon {
color: var(--primary-very-low);
}
&:active {
box-shadow: 0px 0px 5px -1px rgba(0, 0, 0, 0.25);
transform: scale(0.9);
}
&:focus {
@include default-focus;
border-color: var(--quaternary);
outline-color: var(--quaternary);
}
}
} }