This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/app/components/topic-timeline.js

134 lines
3.9 KiB
JavaScript

import Docking from "discourse/mixins/docking";
import MountWidget from "discourse/components/mount-widget";
import { headerOffset } from "discourse/lib/offset-calculator";
import { next } from "@ember/runloop";
import { observes } from "discourse-common/utils/decorators";
import optionalService from "discourse/lib/optional-service";
export default MountWidget.extend(Docking, {
adminTools: optionalService(),
widget: "topic-timeline-container",
dockBottom: null,
dockAt: null,
intersectionObserver: null,
buildArgs() {
let attrs = {
topic: this.topic,
notificationLevel: this.notificationLevel,
topicTrackingState: this.topicTrackingState,
enteredIndex: this.enteredIndex,
dockAt: this.dockAt,
dockBottom: this.dockBottom,
mobileView: this.get("site.mobileView"),
};
let event = this.prevEvent;
if (event) {
attrs.enteredIndex = event.postIndex - 1;
}
if (this.fullscreen) {
attrs.fullScreen = true;
attrs.addShowClass = this.addShowClass;
}
return attrs;
},
@observes("topic.highest_post_number", "loading")
newPostAdded() {
this.queueRerender(() => this.queueDockCheck());
},
@observes("topic.details.notification_level")
_queueRerender() {
this.queueRerender();
},
dockCheck() {
const timeline = this.element.querySelector(".timeline-container");
const timelineHeight = (timeline && timeline.offsetHeight) || 400;
const prev = this.dockAt;
const posTop = headerOffset() + window.pageYOffset;
const pos = posTop + timelineHeight;
this.dockBottom = false;
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(this.topicBottom - timelineHeight, 10);
}
if (this.dockAt !== prev) {
this.queueRerender();
}
},
didInsertElement() {
this._super(...arguments);
if (this.fullscreen && !this.addShowClass) {
next(() => {
this.set("addShowClass", true);
this.queueRerender();
});
}
this.dispatch(
"topic:current-post-scrolled",
() => `timeline-scrollarea-${this.topic.id}`
);
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);
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]);
}
}
}
},
willDestroyElement() {
this._super(...arguments);
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);
if ("IntersectionObserver" in window) {
this.intersectionObserver?.disconnect();
this.intersectionObserver = null;
}
}
},
});