82 lines
2.6 KiB
JavaScript
82 lines
2.6 KiB
JavaScript
const {ElemJS, q, ejs} = require("./basic.js")
|
|
const {store} = require("./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 beforeChangeSubscription = () => {
|
|
// 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)
|
|
}
|
|
this.addSubscription("beforeChange", timeline, beforeChangeSubscription)
|
|
|
|
//Make sure after loading scrollback we don't move the scroll position
|
|
const beforeScrollbackLoadSubscription = () => {
|
|
const lastScrollHeight = chatMessages.scrollHeight;
|
|
|
|
const afterScrollbackLoadSub = () => {
|
|
const scrollDiff = chatMessages.scrollHeight - lastScrollHeight;
|
|
chatMessages.scrollTop += scrollDiff;
|
|
|
|
timeline.unsubscribe("afterScrollbackLoad", afterScrollbackLoadSub)
|
|
}
|
|
|
|
timeline.subscribe("afterScrollbackLoad", afterScrollbackLoadSub)
|
|
}
|
|
this.addSubscription("beforeScrollbackLoad", timeline, beforeScrollbackLoadSubscription)
|
|
}
|
|
this.render()
|
|
}
|
|
addSubscription(name, target, subscription) {
|
|
this.removableSubscriptions.push({name, target, subscription})
|
|
target.subscribe(name, subscription)
|
|
}
|
|
|
|
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()
|
|
|
|
module.exports = {chat}
|