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:
parent
11a9f15fed
commit
999e2ff514
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue