Carbon/src/js/chat.js

73 lines
2.1 KiB
JavaScript

import { ElemJS, q, ejs } from "./basic.js";
import { store } from "./store/store.js";
const chatMessages = q("#c-chat-messages");
class Chat extends ElemJS {
constructor() {
super(q("#c-chat"));
this.removableSubscriptions = [];
store.activeRoom.subscribe("changeSelf", this.changeRoom.bind(this));
this.render();
}
unsubscribe() {
this.removableSubscriptions.forEach(({ name, target, subscription }) => {
target.unsubscribe(name, subscription);
});
this.removableSubscriptions.length = 0;
}
changeRoom() {
// disconnect from the previous room
this.unsubscribe();
// connect to the new room's timeline updater
if (store.activeRoom.exists()) {
const timeline = store.activeRoom.value().timeline;
const subscription = () => {
// scroll anchor does not work if the timeline is scrolled to the top.
// at the start, when there are not enough messages for a full screen, this is the case.
// once there are enough messages that scrolling is necessary, we initiate a scroll down to activate the scroll anchor.
let oldDifference =
chatMessages.scrollHeight - chatMessages.clientHeight;
setTimeout(() => {
let newDifference =
chatMessages.scrollHeight - chatMessages.clientHeight;
// console.log("height difference", oldDifference, newDifference)
if (oldDifference < 24) {
// this is jank
this.element.parentElement.scrollBy(0, 1000);
}
}, 0);
};
const name = "beforeChange";
this.removableSubscriptions.push({
name,
target: timeline,
subscription,
});
timeline.subscribe(name, subscription);
}
this.render();
}
render() {
this.clearChildren();
if (store.activeRoom.exists()) {
const reactiveTimeline = store.activeRoom.value().timeline.getTimeline();
this.child(reactiveTimeline);
setTimeout(() => {
this.element.parentElement.scrollBy(0, 1);
reactiveTimeline.anchor.scroll();
}, 0);
}
}
}
const chat = new Chat();
export { chat };