From 999e2ff514b15c850c027cbf8f4d955d6ad01733 Mon Sep 17 00:00:00 2001 From: Penar Musaraj Date: Thu, 30 Jan 2020 13:52:48 -0500 Subject: [PATCH] UX: Show vertical topic timeline while composing (#8813) Keeps topic timeline visible if space permits when composing, and adjusts its height dynamically. --- .../components/topic-navigation.js.es6 | 38 +++++++++++-------- .../components/topic-timeline.js.es6 | 13 +++++++ .../discourse/widgets/topic-timeline.js.es6 | 15 +++++++- 3 files changed, 50 insertions(+), 16 deletions(-) diff --git a/app/assets/javascripts/discourse/components/topic-navigation.js.es6 b/app/assets/javascripts/discourse/components/topic-navigation.js.es6 index 3324814bf66..7ff9ec0a230 100644 --- a/app/assets/javascripts/discourse/components/topic-navigation.js.es6 +++ b/app/assets/javascripts/discourse/components/topic-navigation.js.es6 @@ -1,6 +1,5 @@ import EmberObject from "@ember/object"; -import { scheduleOnce } from "@ember/runloop"; -import { later } from "@ember/runloop"; +import { debounce, later } from "@ember/runloop"; import Component from "@ember/component"; import { observes } from "discourse-common/utils/decorators"; import showModal from "discourse/lib/show-modal"; @@ -10,6 +9,8 @@ import PanEvents, { SWIPE_VELOCITY_THRESHOLD } from "discourse/mixins/pan-events"; +const MIN_WIDTH_TIMELINE = 924; + export default Component.extend(PanEvents, { composerOpen: null, info: null, @@ -36,14 +37,20 @@ export default Component.extend(PanEvents, { let renderTimeline = !this.site.mobileView; if (renderTimeline) { - const width = $(window).width(); - let height = $(window).height(); + const width = window.innerWidth, + composer = document.getElementById("reply-control"), + timelineContainer = document.querySelectorAll( + ".timeline-container" + )[0], + headerHeight = + document.querySelectorAll(".d-header")[0].offsetHeight || 0; - if (this.composerOpen) { - height -= $("#reply-control").height(); + if (timelineContainer && composer) { + renderTimeline = + width > MIN_WIDTH_TIMELINE && + window.innerHeight - composer.offsetHeight - headerHeight > + timelineContainer.offsetHeight; } - - renderTimeline = width > 924 && height > 520; } info.setProperties({ @@ -54,7 +61,7 @@ export default Component.extend(PanEvents, { }, _checkSize() { - scheduleOnce("afterRender", this, this._performCheckSize); + debounce(this, this._performCheckSize, 300); }, // we need to store this so topic progress has something to init with @@ -89,8 +96,7 @@ export default Component.extend(PanEvents, { composerOpened() { this.set("composerOpen", true); - // we need to do the check after animation is done - later(() => this._checkSize(), 500); + this._checkSize(); }, composerClosed() { @@ -191,8 +197,9 @@ export default Component.extend(PanEvents, { $(window).on("resize.discourse-topic-navigation", () => this._checkSize() ); - this.appEvents.on("composer:will-open", this, this.composerOpened); - this.appEvents.on("composer:will-close", this, this.composerClosed); + this.appEvents.on("composer:opened", this, this.composerOpened); + this.appEvents.on("composer:resized", this, this.composerOpened); + this.appEvents.on("composer:closed", this, this.composerClosed); $("#reply-control").on("div-resized.discourse-topic-navigation", () => this._checkSize() ); @@ -213,8 +220,9 @@ export default Component.extend(PanEvents, { if (!this.site.mobileView) { $(window).off("resize.discourse-topic-navigation"); - this.appEvents.off("composer:will-open", this, this.composerOpened); - this.appEvents.off("composer:will-close", this, this.composerClosed); + this.appEvents.off("composer:opened", this, this.composerOpened); + this.appEvents.off("composer:resized", this, this.composerOpened); + this.appEvents.off("composer:closed", this, this.composerClosed); $("#reply-control").off("div-resized.discourse-topic-navigation"); } } diff --git a/app/assets/javascripts/discourse/components/topic-timeline.js.es6 b/app/assets/javascripts/discourse/components/topic-timeline.js.es6 index 233155f2f37..b71779e35c9 100644 --- a/app/assets/javascripts/discourse/components/topic-timeline.js.es6 +++ b/app/assets/javascripts/discourse/components/topic-timeline.js.es6 @@ -103,5 +103,18 @@ export default MountWidget.extend(Docking, { this.dispatch("topic:current-post-scrolled", "timeline-scrollarea"); 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); + } } }); diff --git a/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6 b/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6 index 72157d7910c..1455e5cc098 100644 --- a/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6 +++ b/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6 @@ -10,9 +10,22 @@ import renderTopicFeaturedLink from "discourse/lib/render-topic-featured-link"; const SCROLLER_HEIGHT = 50; const LAST_READ_HEIGHT = 20; +const MIN_SCROLLAREA_HEIGHT = 170; +const MAX_SCROLLAREA_HEIGHT = 300; 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() {