UX: Show vertical topic timeline while composing (#8813)

Keeps topic timeline visible if space permits when composing, and adjusts its height dynamically.
This commit is contained in:
Penar Musaraj 2020-01-30 13:52:48 -05:00 committed by GitHub
parent 11a9f15fed
commit 999e2ff514
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 16 deletions

View File

@ -1,6 +1,5 @@
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { scheduleOnce } from "@ember/runloop"; import { debounce, later } from "@ember/runloop";
import { later } from "@ember/runloop";
import Component from "@ember/component"; import Component from "@ember/component";
import { observes } from "discourse-common/utils/decorators"; import { observes } from "discourse-common/utils/decorators";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
@ -10,6 +9,8 @@ import PanEvents, {
SWIPE_VELOCITY_THRESHOLD SWIPE_VELOCITY_THRESHOLD
} from "discourse/mixins/pan-events"; } from "discourse/mixins/pan-events";
const MIN_WIDTH_TIMELINE = 924;
export default Component.extend(PanEvents, { export default Component.extend(PanEvents, {
composerOpen: null, composerOpen: null,
info: null, info: null,
@ -36,14 +37,20 @@ export default Component.extend(PanEvents, {
let renderTimeline = !this.site.mobileView; let renderTimeline = !this.site.mobileView;
if (renderTimeline) { if (renderTimeline) {
const width = $(window).width(); const width = window.innerWidth,
let height = $(window).height(); composer = document.getElementById("reply-control"),
timelineContainer = document.querySelectorAll(
".timeline-container"
)[0],
headerHeight =
document.querySelectorAll(".d-header")[0].offsetHeight || 0;
if (this.composerOpen) { if (timelineContainer && composer) {
height -= $("#reply-control").height(); renderTimeline =
width > MIN_WIDTH_TIMELINE &&
window.innerHeight - composer.offsetHeight - headerHeight >
timelineContainer.offsetHeight;
} }
renderTimeline = width > 924 && height > 520;
} }
info.setProperties({ info.setProperties({
@ -54,7 +61,7 @@ export default Component.extend(PanEvents, {
}, },
_checkSize() { _checkSize() {
scheduleOnce("afterRender", this, this._performCheckSize); debounce(this, this._performCheckSize, 300);
}, },
// we need to store this so topic progress has something to init with // we need to store this so topic progress has something to init with
@ -89,8 +96,7 @@ export default Component.extend(PanEvents, {
composerOpened() { composerOpened() {
this.set("composerOpen", true); this.set("composerOpen", true);
// we need to do the check after animation is done this._checkSize();
later(() => this._checkSize(), 500);
}, },
composerClosed() { composerClosed() {
@ -191,8 +197,9 @@ export default Component.extend(PanEvents, {
$(window).on("resize.discourse-topic-navigation", () => $(window).on("resize.discourse-topic-navigation", () =>
this._checkSize() this._checkSize()
); );
this.appEvents.on("composer:will-open", this, this.composerOpened); this.appEvents.on("composer:opened", this, this.composerOpened);
this.appEvents.on("composer:will-close", this, this.composerClosed); this.appEvents.on("composer:resized", this, this.composerOpened);
this.appEvents.on("composer:closed", this, this.composerClosed);
$("#reply-control").on("div-resized.discourse-topic-navigation", () => $("#reply-control").on("div-resized.discourse-topic-navigation", () =>
this._checkSize() this._checkSize()
); );
@ -213,8 +220,9 @@ export default Component.extend(PanEvents, {
if (!this.site.mobileView) { if (!this.site.mobileView) {
$(window).off("resize.discourse-topic-navigation"); $(window).off("resize.discourse-topic-navigation");
this.appEvents.off("composer:will-open", this, this.composerOpened); this.appEvents.off("composer:opened", this, this.composerOpened);
this.appEvents.off("composer:will-close", this, this.composerClosed); this.appEvents.off("composer:resized", this, this.composerOpened);
this.appEvents.off("composer:closed", this, this.composerClosed);
$("#reply-control").off("div-resized.discourse-topic-navigation"); $("#reply-control").off("div-resized.discourse-topic-navigation");
} }
} }

View File

@ -103,5 +103,18 @@ export default MountWidget.extend(Docking, {
this.dispatch("topic:current-post-scrolled", "timeline-scrollarea"); this.dispatch("topic:current-post-scrolled", "timeline-scrollarea");
this.dispatch("topic:toggle-actions", "topic-admin-menu-button"); this.dispatch("topic:toggle-actions", "topic-admin-menu-button");
if (!this.site.mobileView) {
this.appEvents.on("composer:opened", this, this.queueRerender);
this.appEvents.on("composer:resized", this, this.queueRerender);
this.appEvents.on("composer:closed", this, this.queueRerender);
}
},
willDestroyElement() {
if (!this.site.mobileView) {
this.appEvents.off("composer:opened", this, this.queueRerender);
this.appEvents.off("composer:resized", this, this.queueRerender);
this.appEvents.off("composer:closed", this, this.queueRerender);
}
} }
}); });

View File

@ -10,9 +10,22 @@ import renderTopicFeaturedLink from "discourse/lib/render-topic-featured-link";
const SCROLLER_HEIGHT = 50; const SCROLLER_HEIGHT = 50;
const LAST_READ_HEIGHT = 20; const LAST_READ_HEIGHT = 20;
const MIN_SCROLLAREA_HEIGHT = 170;
const MAX_SCROLLAREA_HEIGHT = 300;
function scrollareaHeight() { function scrollareaHeight() {
return $(window).height() < 425 ? 150 : 300; const composerHeight =
document.getElementById("reply-control").offsetHeight || 0,
headerHeight = document.querySelectorAll(".d-header")[0].offsetHeight || 0;
// scrollarea takes up about half of the timeline's height
const availableHeight =
(window.innerHeight - composerHeight - headerHeight) / 2;
return Math.max(
MIN_SCROLLAREA_HEIGHT,
Math.min(availableHeight, MAX_SCROLLAREA_HEIGHT)
);
} }
function scrollareaRemaining() { function scrollareaRemaining() {