DEV: Minor topic timeline refactor (#15357)
This commit is contained in:
parent
e09742aa69
commit
312c417366
|
@ -172,7 +172,7 @@ const SiteHeaderComponent = MountWidget.extend(
|
|||
}
|
||||
},
|
||||
|
||||
dockCheck(info) {
|
||||
dockCheck() {
|
||||
const header = document.querySelector("header.d-header");
|
||||
|
||||
if (this.docAt === null) {
|
||||
|
@ -182,9 +182,7 @@ const SiteHeaderComponent = MountWidget.extend(
|
|||
this.docAt = header.offsetTop;
|
||||
}
|
||||
|
||||
const offset = info.offset();
|
||||
const headerRect = header.getBoundingClientRect();
|
||||
const doc = document.documentElement;
|
||||
let headerOffset = headerRect.top + headerRect.height;
|
||||
|
||||
if (window.scrollY < 0) {
|
||||
|
@ -194,10 +192,10 @@ const SiteHeaderComponent = MountWidget.extend(
|
|||
const newValue = `${headerOffset}px`;
|
||||
if (newValue !== this.currentHeaderOffsetValue) {
|
||||
this.currentHeaderOffsetValue = newValue;
|
||||
doc.style.setProperty("--header-offset", newValue);
|
||||
document.documentElement.style.setProperty("--header-offset", newValue);
|
||||
}
|
||||
|
||||
if (offset >= this.docAt) {
|
||||
if (window.pageYOffset >= this.docAt) {
|
||||
if (!this.dockedHeader) {
|
||||
document.body.classList.add("docked");
|
||||
this.dockedHeader = true;
|
||||
|
|
|
@ -3,22 +3,13 @@ import MountWidget from "discourse/components/mount-widget";
|
|||
import { next } from "@ember/runloop";
|
||||
import { observes } from "discourse-common/utils/decorators";
|
||||
import optionalService from "discourse/lib/optional-service";
|
||||
import outletHeights from "discourse/lib/header-outlet-height";
|
||||
|
||||
const headerPadding = () => {
|
||||
let topPadding = parseInt($("#main-outlet").css("padding-top"), 10) + 3;
|
||||
const iPadNavHeight = $(".footer-nav-ipad .footer-nav").height();
|
||||
if (iPadNavHeight) {
|
||||
topPadding += iPadNavHeight;
|
||||
}
|
||||
return topPadding;
|
||||
};
|
||||
|
||||
export default MountWidget.extend(Docking, {
|
||||
adminTools: optionalService(),
|
||||
widget: "topic-timeline-container",
|
||||
dockBottom: null,
|
||||
dockAt: null,
|
||||
intersectionObserver: null,
|
||||
|
||||
buildArgs() {
|
||||
let attrs = {
|
||||
|
@ -39,8 +30,6 @@ export default MountWidget.extend(Docking, {
|
|||
if (this.fullscreen) {
|
||||
attrs.fullScreen = true;
|
||||
attrs.addShowClass = this.addShowClass;
|
||||
} else {
|
||||
attrs.top = this.dockAt || headerPadding();
|
||||
}
|
||||
|
||||
return attrs;
|
||||
|
@ -56,38 +45,26 @@ export default MountWidget.extend(Docking, {
|
|||
this.queueRerender();
|
||||
},
|
||||
|
||||
dockCheck(info) {
|
||||
const mainOffset = $("#main").offset();
|
||||
const offsetTop = mainOffset ? mainOffset.top : 0;
|
||||
const topicTop = $(".container.posts").offset().top - offsetTop;
|
||||
const topicBottom =
|
||||
$("#topic-bottom").offset().top - $("#main-outlet").offset().top;
|
||||
dockCheck() {
|
||||
const timeline = this.element.querySelector(".timeline-container");
|
||||
const timelineHeight = (timeline && timeline.offsetHeight) || 400;
|
||||
const footerHeight = $(".timeline-footer-controls").outerHeight(true) || 0;
|
||||
|
||||
const prev = this.dockAt;
|
||||
const posTop = headerPadding() + info.offset();
|
||||
const pos = posTop + timelineHeight - outletHeights();
|
||||
const posTop = this.headerOffset() + window.pageYOffset;
|
||||
const pos = posTop + timelineHeight;
|
||||
|
||||
this.dockBottom = false;
|
||||
if (posTop < topicTop) {
|
||||
this.dockAt = parseInt(topicTop, 10);
|
||||
} else if (pos > topicBottom + footerHeight) {
|
||||
this.dockAt = parseInt(
|
||||
topicBottom - timelineHeight + footerHeight + outletHeights(),
|
||||
10
|
||||
);
|
||||
if (posTop < this.topicTop) {
|
||||
this.dockAt = parseInt(this.topicTop, 10);
|
||||
} else if (pos > this.topicBottom) {
|
||||
this.dockAt = parseInt(this.topicBottom - timelineHeight, 10);
|
||||
this.dockBottom = true;
|
||||
if (this.dockAt < 0) {
|
||||
this.dockAt = 0;
|
||||
}
|
||||
} else {
|
||||
this.dockAt = null;
|
||||
this.fastDockAt = parseInt(
|
||||
topicBottom - timelineHeight + footerHeight - offsetTop,
|
||||
10
|
||||
);
|
||||
this.fastDockAt = parseInt(this.topicBottom - timelineHeight, 10);
|
||||
}
|
||||
|
||||
if (this.dockAt !== prev) {
|
||||
|
@ -95,6 +72,12 @@ export default MountWidget.extend(Docking, {
|
|||
}
|
||||
},
|
||||
|
||||
headerOffset() {
|
||||
return (
|
||||
parseInt(document.body.style.getPropertyValue("--header-offset"), 10) || 0
|
||||
);
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
|
@ -114,6 +97,28 @@ export default MountWidget.extend(Docking, {
|
|||
this.appEvents.on("composer:opened", this, this.queueRerender);
|
||||
this.appEvents.on("composer:resized", this, this.queueRerender);
|
||||
this.appEvents.on("composer:closed", this, this.queueRerender);
|
||||
if ("IntersectionObserver" in window) {
|
||||
this.intersectionObserver = new IntersectionObserver((entries) => {
|
||||
for (const entry of entries) {
|
||||
const bounds = entry.boundingClientRect;
|
||||
|
||||
if (entry.target.id === "topic-bottom") {
|
||||
this.set("topicBottom", bounds.y + window.scrollY);
|
||||
} else {
|
||||
this.set("topicTop", bounds.y + window.scrollY);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const elements = [
|
||||
document.querySelector(".container.posts"),
|
||||
document.querySelector("#topic-bottom"),
|
||||
];
|
||||
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
this.intersectionObserver.observe(elements[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -124,6 +129,10 @@ export default MountWidget.extend(Docking, {
|
|||
this.appEvents.off("composer:opened", this, this.queueRerender);
|
||||
this.appEvents.off("composer:resized", this, this.queueRerender);
|
||||
this.appEvents.off("composer:closed", this, this.queueRerender);
|
||||
if ("IntersectionObserver" in window) {
|
||||
this.intersectionObserver?.disconnect();
|
||||
this.intersectionObserver = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
export default function () {
|
||||
const outletSelector = [
|
||||
".above-site-header-outlet",
|
||||
".below-site-header-outlet",
|
||||
];
|
||||
// If these outlets have height they impact timeline and usercard positioning
|
||||
|
||||
let outletHeights = 0;
|
||||
|
||||
outletSelector.forEach(function (outletClass) {
|
||||
if (document.querySelector(outletClass)) {
|
||||
let outlets = document.querySelectorAll(outletClass);
|
||||
outlets.forEach((outlet) => {
|
||||
if (outlet.offsetHeight) {
|
||||
outletHeights += parseInt(outlet.offsetHeight, 10);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return outletHeights;
|
||||
}
|
|
@ -79,10 +79,8 @@ export default class StickyAvatars {
|
|||
_initIntersectionObserver() {
|
||||
schedule("afterRender", () => {
|
||||
const headerOffset =
|
||||
parseInt(
|
||||
getComputedStyle(document.body).getPropertyValue("--header-offset"),
|
||||
10
|
||||
) || 0;
|
||||
parseInt(document.body.style.getPropertyValue("--header-offset"), 10) ||
|
||||
0;
|
||||
const headerHeight = Math.max(headerOffset, 0);
|
||||
|
||||
this.intersectionObserver = new IntersectionObserver(
|
||||
|
|
|
@ -2,14 +2,6 @@ import Mixin from "@ember/object/mixin";
|
|||
import discourseDebounce from "discourse-common/lib/debounce";
|
||||
import { cancel, later } from "@ember/runloop";
|
||||
|
||||
const helper = {
|
||||
offset() {
|
||||
const main = document.querySelector("#main");
|
||||
const offsetTop = main ? main.offsetTop : 0;
|
||||
return window.pageYOffset - offsetTop;
|
||||
},
|
||||
};
|
||||
|
||||
export default Mixin.create({
|
||||
queueDockCheck: null,
|
||||
_initialTimer: null,
|
||||
|
@ -26,7 +18,7 @@ export default Mixin.create({
|
|||
if (this.isDestroyed || this.isDestroying) {
|
||||
return;
|
||||
}
|
||||
this.dockCheck(helper);
|
||||
this.dockCheck();
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
box-sizing: border-box;
|
||||
z-index: z("timeline");
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transition: margin-bottom 0.25s ease-in;
|
||||
&.timeline-docked-bottom {
|
||||
margin-bottom: -4em;
|
||||
@media screen and (prefers-reduced-motion: no-preference) {
|
||||
margin-bottom: -1.75em; // animate out footer button height
|
||||
transition: margin-bottom 0.5s ease-in;
|
||||
}
|
||||
.timeline-footer-controls {
|
||||
opacity: 0;
|
||||
|
@ -187,7 +187,9 @@
|
|||
|
||||
.timeline-footer-controls {
|
||||
margin-top: 1.5em;
|
||||
transition: opacity 0.2s ease-in;
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
transition: opacity 0.2s ease-in;
|
||||
}
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
max-width: 9em;
|
||||
|
|
Loading…
Reference in New Issue