Carbon/build/static/Timeline.js

96 lines
2.3 KiB
JavaScript

import {ElemJS} from "./basic.js"
import {Subscribable} from "./store/Subscribable.js"
class Event extends ElemJS {
constructor(data) {
super("div")
this.class("c-message")
this.data = null
this.update(data)
}
update(data) {
this.data = data
this.render()
}
render() {
this.child(this.data.content.body)
}
}
class Timeline extends Subscribable {
constructor() {
super()
Object.assign(this.events, {
addItem: [],
removeItem: []
})
Object.assign(this.eventDeps, {
addItem: [],
removeItem: []
})
this.list = []
this.map = new Map()
this.elementsMap = new Map()
this.elementsList = []
}
_binarySearch(event, min = 0, max = -1) {
if (this.list.length === 0) return {success: false, i: 0}
if (max === -1) max = this.list.length - 1
let mid = Math.floor((max + min) / 2)
// success condition
if (this.list[mid] && this.list[mid].event_id === event.event_id) return {success: true, i: mid}
// failed condition
if (min >= max) {
while (mid !== -1 && (!this.list[mid] || this.list[mid].origin_server_ts > event.origin_server_ts)) mid--
return {
success: false,
i: mid + 1
}
}
// recurse (below)
if (this.list[mid].origin_server_ts > event.origin_server_ts) return this._binarySearch(event, min, mid-1)
// recurse (above)
else return this._binarySearch(event, mid+1, max)
}
updateEvents(events) {
for (const event of events) {
if (this.map.has(event.event_id)) {
this.map.set(event.event_id, event)
this.elementsMap.get(event.event_id).update(this.map.get(event.event_id))
} else {
const index = this._binarySearch(event).i
this.list.splice(index, 0, event)
this.map.set(event.event_id, event)
const e = new Event(event)
this.elementsList.splice(index, 0, e)
this.elementsMap.set(event.event_id, e)
this.broadcast("addItem", {index, element: e})
}
}
}
getGroupedEvents() {
let currentSender = Symbol("N/A")
let groups = []
let currentGroup = []
for (const event of this.list) {
if (event.sender === currentSender) {
currentGroup.push(event)
} else {
if (currentGroup.length) groups.push(currentGroup)
currentGroup = [event]
currentSender = event.sender
}
}
if (currentGroup.length) groups.push(currentGroup)
return groups
}
}
export {Timeline}