DEV: Minor topic timeline refactor (#15357)

This commit is contained in:
Penar Musaraj 2021-12-28 12:01:20 -05:00 committed by GitHub
parent e09742aa69
commit 312c417366
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 75 deletions

View File

@ -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;

View File

@ -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;
}
}
},
});

View File

@ -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;
}

View File

@ -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(

View File

@ -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() {

View File

@ -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;