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;
// 100dvh with fallback for old browsers
--100dvh: 100vh;
@supports (height: 100dvh) {
--100dvh: 100dvh;
// 1dvh with fallback for old browsers
--1dvh: 1vh;
@supports (height: 1dvh) {
--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 & {
top: calc(var(--header-offset) + var(--footer-nav-height));
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
(and this.showMobileDirectMessageButton this.canCreateDirectMessageChannel)
}}
{{#if this.showMobileDirectMessageButton}}
<LinkTo
@route="chat.draft-channel"
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"}}
</LinkTo>
@ -62,6 +60,7 @@
/>
{{/each}}
{{/if}}
</div>
{{/if}}

View File

@ -26,7 +26,7 @@ export default class ChannelsList extends Component {
}
get showMobileDirectMessageButton() {
return this.site.mobileView && this.showDirectMessageChannels;
return this.site.mobileView && this.canCreateDirectMessageChannel;
}
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">
{{#if this.site.mobileView}}
<LinkTo
@ -75,18 +66,23 @@
</div>
</div>
{{else if this.channelsCollection.length}}
<div class="chat-browse-view__content_wrapper">
<div class="chat-browse-view__content">
<div class="chat-browse-view__cards">
{{#each this.channelsCollection as |channel|}}
<ChatChannelCard @channel={{channel}} />
{{/each}}
<LoadMore
@selector=".chat-channel-card"
@action={{this.channelsCollection.loadMore}}
>
<div class="chat-browse-view__content_wrapper">
<div class="chat-browse-view__content">
<div class="chat-browse-view__cards">
{{#each this.channelsCollection as |channel|}}
<ChatChannelCard @channel={{channel}} />
{{/each}}
</div>
</div>
{{#unless this.channelsCollection.loading}}
<OnVisibilityAction @action={{action "onScroll"}} />
{{/unless}}
</div>
</div>
<ConditionalLoadingSpinner
@condition={{this.channelsCollection.loading}}
/>
</LoadMore>
{{/if}}
</div>

View File

@ -1,45 +1,41 @@
{{#if this.chatProgressBarContainer}}
{{#in-element this.chatProgressBarContainer}}
<DProgressBar @key="members-view" @isLoading={{this.members.loading}} />
{{/in-element}}
{{/if}}
{{#if (gt this.channel.membershipsCount 0)}}
<div class="channel-members-view-wrapper">
<div
class={{concat
"channel-members-view__search-input-container"
(if this.isSearchFocused " is-focused")
}}
>
<Input
class={{this.inputSelector}}
placeholder={{i18n "chat.members_view.filter_placeholder"}}
{{on "input" (action "onFilterMembers" value="target.value")}}
{{on "focusin" (action (mut this.isSearchFocused) true)}}
{{on "focusout" (action (mut this.isSearchFocused) false)}}
/>
{{d-icon "search"}}
</div>
<LoadMore
@selector=".channel-members-view__list-item"
@action={{this.loadMore}}
>
<div class="channel-members-view-wrapper">
<div
class={{concat
"channel-members-view__search-input-container"
(if this.isSearchFocused " is-focused")
}}
>
<Input
class={{this.inputSelector}}
placeholder={{i18n "chat.members_view.filter_placeholder"}}
{{on "input" (action "onFilterMembers" value="target.value")}}
{{on "focusin" (action (mut this.isSearchFocused) true)}}
{{on "focusout" (action (mut this.isSearchFocused) false)}}
/>
{{d-icon "search"}}
</div>
<div
class="channel-members-view__list-container"
{{on "scroll" (action "loadMore")}}
>
<div role="list" class="channel-members-view__list">
{{#each this.members as |membership|}}
<div class="channel-members-view__list-item">
<ChatUserInfo @user={{membership.user}} />
</div>
{{else}}
{{#unless this.isFetchingMembers}}
{{i18n "chat.channel.no_memberships_found"}}
{{/unless}}
{{/each}}
<div class="channel-members-view__list-container">
<div role="list" class="channel-members-view__list">
{{#each this.members as |membership|}}
<div class="channel-members-view__list-item">
<ChatUserInfo @user={{membership.user}} />
</div>
{{else}}
{{#unless this.isFetchingMembers}}
{{i18n "chat.channel.no_memberships_found"}}
{{/unless}}
{{/each}}
</div>
</div>
</div>
</div>
<ConditionalLoadingSpinner @condition={{this.members.loading}} />
</LoadMore>
{{else}}
<div class="channel-members-view-wrapper">
{{i18n "chat.channel.no_memberships"}}

View File

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

View File

@ -14,6 +14,22 @@ export default class ChatDraftChannelScreen extends Component {
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
onChangeSelectedUsers(users) {
this._fetchPreviewedChannel(users);

View File

@ -5,7 +5,11 @@
{{/if}}
{{#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
class="filter-area {{if this.isFilterFocused 'is-focused'}}"
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
onFilterInput(term) {
this.set("term", term);

View File

@ -428,8 +428,7 @@ body.has-full-page-chat {
}
}
.chat-messages-scroll,
.chat-channel {
.chat-messages-scroll {
box-sizing: border-box;
height: 100%;
}
@ -574,30 +573,13 @@ html.has-full-page-chat {
height: 100%;
width: 100%;
&.keyboard-visible body #main-outlet .full-page-chat {
padding-bottom: 0.2rem;
}
body {
height: 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 {
display: flex;
flex-direction: column;
max-height: calc(
var(--chat-vh, 1vh) * 100 - var(--header-offset, 0px) -
var(--composer-height, 0px)
);
.full-page-chat {
height: 100%;
@ -620,32 +602,12 @@ html.has-full-page-chat {
// these need to apply to desktop too, because iPads
&.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,
.chat-channel,
#main-outlet {
// allows containers to shrink to fit
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] {
visibility: hidden;

View File

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

View File

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

View File

@ -7,6 +7,19 @@
grid-area: main;
width: 100%;
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-thread-list-btn {

View File

@ -251,4 +251,5 @@ a.chat-drawer-header__title {
height: 100%;
min-height: 1px;
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 {
overflow-y: auto;
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);
}
}
}