import { Author, Message } from "./message" import util from "./util" import { BatchTimer } from "./batch-timer" import { AdapterState } from "./adapter" export class AuthorMessagesElement extends HTMLElement { static observedAttributes = [ "data-latest", "data-adapter", "data-target" ]; private _id: string | null = null; private _adapter: string = ""; private _messages: Message[] = []; private _byAuthorTimer: BatchTimer | null = null; constructor() { super(); this.innerHTML = ``; } connectedCallback() { this._id = this.getAttribute("data-target"); this._adapter = this.getAttribute("data-adapter") ?? ""; const gateway = this.getAttribute("data-gateway") ?? ""; this._byAuthorTimer = new BatchTimer((ids: string[])=>{ let url = `${gateway}/api/adapters/${this._adapter}/fetch?entity_type=byAuthor`; for (let id of ids) { url += `&entity_id=${id}`; } util.authorizedFetch("GET", url, null); }); } attributeChangedCallback(attr: string, prev: string, next: string) { switch (attr) { case "data-target": if (!next) { return } this._id = next; if (this._byAuthorTimer) { this._byAuthorTimer.queue(next, 100) } break; case "data-latest": let datastore = AdapterState._instance.data.get(this._adapter); if (!datastore) { console.log("no data yet, wait for some to come in maybe..."); return; } let msg = datastore.messages.get(next); if (msg) { const existingIdx = this._messages.findIndex(m=>m.id == msg.id && ((m.edited ?? m.created) < (msg.edited ?? msg.created))); // first we update the backing data store if (existingIdx >= 0) { this._messages[existingIdx] = msg; } else if (!this._messages.some(m=>m.id == msg.id)) { this._messages.push(msg); } const ul = this.children[0]; if (ul) { // first pass through the dom, try to update a message if it's there for (let i = 0; i < ul.childElementCount; i++){ const id = ul.children[i]?.children[0]?.getAttribute("data-target"); const ogMsg = this._messages.find(m=>m.id == id); if (ogMsg && existingIdx >= 0) { ul.children[i]?.children[0]?.setAttribute("data-latest", id ?? ""); return; } } // if we made it this far, let's create a node const e = document.createElement("li"); e.innerHTML = `` // second pass, try to place it in reverse-chronological order for (let i = 0; i < ul.childElementCount; i++){ const id = ul.children[i]?.children[0]?.getAttribute("data-target"); const ogMsg = this._messages.find(m=>m.id == id); if (ogMsg && ogMsg.created < msg.created) { ul.insertBefore(e, ul.children[i]) e.children[0].setAttribute("data-latest", next); return; } } // final pass, we must be the earliest child (or maybe the first one to be rendered) ul.append(e); e.children[0].setAttribute("data-latest", next); } console.log(JSON.stringify(this._messages)); } } } }