diff --git a/frontend/ts/author-messages-element.ts b/frontend/ts/author-messages-element.ts index ffde06e..e9dfac3 100644 --- a/frontend/ts/author-messages-element.ts +++ b/frontend/ts/author-messages-element.ts @@ -14,7 +14,7 @@ export class AuthorMessagesElement extends HTMLElement { constructor() { super(); - this.innerHTML = "" + this.innerHTML = ``; } connectedCallback() { @@ -49,16 +49,47 @@ export class AuthorMessagesElement extends HTMLElement { } let msg = datastore.messages.get(next); if (msg) { - // if _messages has this one, and this updated date is greater - const existingIdx = this._messages.findIndex(m=>m.id == msg.id && ((m.edited ?? 0) < (msg.edited ?? 0))); + 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; - // and update it in the dom - } else { + } else if (!this._messages.some(m=>m.id == msg.id)) { this._messages.push(msg); - // and insert in into the dom - } - console.log(JSON.stringify(this._messages)); + } + + + 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)); } } } diff --git a/frontend/ts/index.ts b/frontend/ts/index.ts index 9e065bf..a8a894d 100644 --- a/frontend/ts/index.ts +++ b/frontend/ts/index.ts @@ -15,11 +15,8 @@ function main() { const saveData = localStorage.getItem("underbbs_settings"); Settings._instance = saveData ? JSON.parse(saveData) : new Settings(); - customElements.define("underbbs-tabbar", TabBarElement); customElements.define("underbbs-message", MessageElement); customElements.define("underbbs-settings", SettingsElement); - customElements.define("underbbs-adapter", AdapterElement); - customElements.define("underbbs-thread-summary", ThreadSummaryElement); customElements.define("underbbs-profile", ProfileElement); customElements.define("underbbs-author-messages", AuthorMessagesElement); diff --git a/frontend/ts/message-element.ts b/frontend/ts/message-element.ts index d34907e..9e9a84c 100644 --- a/frontend/ts/message-element.ts +++ b/frontend/ts/message-element.ts @@ -1,5 +1,7 @@ import util from "./util" -var _ = util._ +import { Message } from "./message" +import { BatchTimer } from "./batch-timer" +import { AdapterState } from "./adapter" export class MessageElement extends HTMLElement { static observedAttributes = [ "data-target", "data-latest", "data-adapter", "data-replyCt", "data-reactionCt", "data-boostCt" ] @@ -7,20 +9,101 @@ export class MessageElement extends HTMLElement { private _id: string | null = null; private _adapter: string | null = null; + private _message: Message | null = null; + + private _messageTimer: BatchTimer | null = null; + constructor() { super(); + this.innerHTML = `
` } connectedCallback() { this._id = this.getAttribute("data-target"); this._adapter = this.getAttribute("data-adapter"); - - // grab message content from the store and format our innerHTML + const gateway = this.getAttribute("data-gateway") ?? ""; + this._messageTimer = new BatchTimer((ids: string[])=>{ + let url = `${gateway}/api/adapters/${this._adapter}/fetch?entity_type=message`; + 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._messageTimer) { + this._messageTimer.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); + console.log("MessageElement.attributeChangedCallback: " + JSON.stringify(msg)); + if (msg) { + this._message = msg; + const metadata = this.querySelector(".message_metadata"); + const content = this.querySelector(".message_content"); + const attachments = this.querySelector(".message_attachments"); + if (metadata) { + metadata.innerHTML = `${this._message.author}${new Date(this._message.created)}${this._message.visibility}${this._message.protocol}` + } + if (content) { + content.innerHTML = this._message.content; + } + if (attachments && this._message.attachments.length > 0) { + let html = ""; + attachments.innerHTML = html; + } + } break; } } diff --git a/frontend/ts/message.ts b/frontend/ts/message.ts index 70d31eb..84de9a0 100644 --- a/frontend/ts/message.ts +++ b/frontend/ts/message.ts @@ -27,10 +27,10 @@ export class Author { } export class Attachment { - public Src: string = ""; - public ThumbSrc: string = ""; - public Desc: string = ""; - public CreatedAt: Date = new Date(); + public src: string = ""; + public thumbSrc: string = ""; + public desc: string = ""; + public createdAt: Date = new Date(); } export default { Message, Attachment, Author } \ No newline at end of file