From ec6ab101c021a3f9add0597892efce90c8a0993a Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 20 Jul 2024 14:36:19 -0500 Subject: [PATCH] Adds a more proper infinate scroller It probally does more, but I can't remember what lol --- .dist/channel.js | 113 ++++++++++++++------------- .dist/direct.js | 39 ++++------ .dist/embed.js | 12 +-- .dist/file.js | 6 +- .dist/fullscreen.js | 2 +- .dist/index.js | 88 --------------------- .dist/infiniteScroller.js | 146 +++++++++++++++++++++++++++++++++++ .dist/localuser.js | 22 +----- .dist/markdown.js | 37 ++++++++- .dist/message.js | 27 ++++--- .dist/register.js | 2 +- .dist/settings.js | 2 +- webpage/channel.ts | 128 ++++++++++++++++--------------- webpage/direct.ts | 40 ++++------ webpage/file.ts | 6 +- webpage/index.ts | 102 +------------------------ webpage/infiniteScroller.ts | 148 ++++++++++++++++++++++++++++++++++++ webpage/localuser.ts | 20 +---- webpage/markdown.ts | 10 ++- webpage/message.ts | 31 +++++--- webpage/register.ts | 2 +- webpage/style.css | 19 ++++- 22 files changed, 572 insertions(+), 430 deletions(-) create mode 100644 .dist/infiniteScroller.js create mode 100644 webpage/infiniteScroller.ts diff --git a/.dist/channel.js b/.dist/channel.js index ac24437..361f57f 100644 --- a/.dist/channel.js +++ b/.dist/channel.js @@ -6,13 +6,13 @@ import { Fullscreen } from "./fullscreen.js"; import { markdown } from "./markdown.js"; import { Permissions } from "./permissions.js"; import { Settings, RoleList } from "./settings.js"; +import { InfiniteScroller } from "./infiniteScroller.js"; Settings; class Channel { editing; type; owner; headers; - messages; name; id; parent_id; @@ -35,6 +35,9 @@ class Channel { allthewayup; static contextmenu = new Contextmenu("channel menu"); replyingto; + infinate; + idToPrev = {}; + idToNext = {}; static setupcontextmenu() { this.contextmenu.addbutton("Copy channel id", function () { console.log(this); @@ -68,6 +71,33 @@ class Channel { return order; }); } + setUpInfinateScroller() { + const ids = {}; + this.infinate = new InfiniteScroller(async function (id, offset) { + if (offset === 1) { + if (this.idToPrev[id]) { + return this.idToPrev[id]; + } + else { + await this.grabmoremessages(id); + return this.idToPrev[id]; + } + } + else { + return this.idToNext[id]; + } + }.bind(this), function (id) { + let res; + const promise = new Promise(_ => { res = _; }); + const html = this.messageids[id].buildhtml(this.messageids[this.idToPrev[id]], promise); + ids[id] = res; + return html; + }.bind(this), async function (id) { + ids[id](); + delete ids[id]; + return true; + }.bind(this), this.readbottom.bind(this)); + } constructor(JSON, owner) { if (JSON === -1) { return; @@ -76,7 +106,6 @@ class Channel { this.type = JSON.type; this.owner = owner; this.headers = this.owner.headers; - this.messages = []; this.name = JSON.name; this.id = JSON.id; this.parent_id = JSON.parent_id; @@ -100,6 +129,7 @@ class Channel { this.position = JSON.position; this.lastreadmessageid = null; this.lastmessageid = JSON.last_message_id; + this.setUpInfinateScroller(); } isAdmin() { return this.guild.isAdmin(); @@ -487,7 +517,7 @@ class Channel { this.myhtml.classList.add("viewChannel"); this.guild.prevchannel = this; this.localuser.channelfocus = this; - const prom = Message.wipeChanel(); + const prom = this.infinate.delete(); await this.putmessages(); await prom; if (id !== Channel.genid) { @@ -501,7 +531,7 @@ class Channel { document.getElementById("typebox").disabled = !this.canMessage; } async putmessages() { - if (this.messages.length >= 100 || this.allthewayup) { + if (this.allthewayup) { return; } ; @@ -512,11 +542,16 @@ class Channel { if (response.length !== 100) { this.allthewayup = true; } + let prev = undefined; for (const thing of response) { - const messager = new Message(thing, this); - if (this.messageids[messager.id] === undefined) { - this.messageids[messager.id] = messager; - this.messages.push(messager); + const message = new Message(thing, this); + if (prev) { + this.idToNext[message.id] = prev.id; + this.idToPrev[prev.id] = message.id; + } + prev = message; + if (this.messageids[message.id] === undefined) { + this.messageids[message.id] = message; } } } @@ -529,20 +564,18 @@ class Channel { } this.children = build; } - async grabmoremessages() { - if (this.messages.length === 0 || this.allthewayup) { + async grabmoremessages(id) { + if (this.allthewayup) { return; } - const out = this; - await fetch(this.info.api.toString() + "/channels/" + this.id + "/messages?before=" + this.messages[this.messages.length - 1].id + "&limit=100", { + await fetch(this.info.api.toString() + "/channels/" + this.id + "/messages?before=" + id + "&limit=100", { headers: this.headers }).then((j) => { return j.json(); }).then(response => { - //messages.innerHTML = ''; - //response.reverse() let next; if (response.length === 0) { - out.allthewayup = true; + this.allthewayup = true; } + let previd = id; for (const i in response) { let messager; if (!next) { @@ -558,10 +591,11 @@ class Channel { next = undefined; console.log("ohno", +i + 1); } - if (out.messageids[messager.id] == undefined) { - out.messageids[messager.id] = messager; - out.buildmessage(messager, next); - out.messages.push(messager); + if (this.messageids[messager.id] === undefined) { + this.idToNext[messager.id] = previd; + this.idToPrev[previd] = messager.id; + previd = messager.id; + this.messageids[messager.id] = messager; } else { console.log("How???"); @@ -576,30 +610,9 @@ class Channel { document.getElementById("messages").prepend(built); } buildmessages() { - for (const i in this.messages) { - const prev = this.messages[(+i) + 1]; - const built = this.messages[i].buildhtml(prev); - document.getElementById("messages").prepend(built); - if (prev) { - const prevDate = new Date(prev.timestamp); - const currentDate = new Date(this.messages[i].timestamp); - if (prevDate.toLocaleDateString() != currentDate.toLocaleDateString()) { - const dateContainer = document.createElement("div"); - dateContainer.classList.add("replyflex"); - const line = document.createElement("hr"); - line.classList.add("reply"); - dateContainer.appendChild(line); - const date = document.createElement("span"); - date.textContent = currentDate.toLocaleDateString(undefined, { weekday: "long", year: "numeric", month: "long", day: "numeric" }); - dateContainer.appendChild(date); - const line2 = document.createElement("hr"); - line2.classList.add("reply"); - dateContainer.appendChild(line2); - document.getElementById("messages").prepend(dateContainer); - } - } - } - document.getElementById("messagecontainer").scrollTop = document.getElementById("messagecontainer").scrollHeight; + const messages = document.getElementById("channelw"); + messages.innerHTML = ""; + messages.append(this.infinate.getDiv(this.lastmessageid)); } updateChannel(JSON) { this.type = JSON.type; @@ -694,7 +707,10 @@ class Channel { return; } const messagez = new Message(messagep.d, this); + this.idToNext[this.lastmessageid] = messagez.id; + this.idToPrev[messagez.id] = this.lastmessageid; this.lastmessageid = messagez.id; + this.messageids[messagez.id] = messagez; if (messagez.author === this.localuser.user) { this.lastreadmessageid = messagez.id; if (this.myhtml) { @@ -707,16 +723,7 @@ class Channel { } } this.guild.unreads(); - this.messages.unshift(messagez); - const scrolly = document.getElementById("messagecontainer"); - this.messageids[messagez.id] = messagez; - if (this.localuser.lookingguild.prevchannel === this) { - var shouldScroll = scrolly.scrollTop + scrolly.clientHeight > scrolly.scrollHeight - 20; - document.getElementById("messages").appendChild(messagez.buildhtml(this.messages[1])); - } - if (shouldScroll) { - scrolly.scrollTop = scrolly.scrollHeight; - } + this.infinate.addedBottom(); if (messagez.author === this.localuser.user) { return; } diff --git a/.dist/direct.js b/.dist/direct.js index a39d928..3fe9902 100644 --- a/.dist/direct.js +++ b/.dist/direct.js @@ -64,7 +64,6 @@ class Group extends Channel { super(-1, owner); this.owner = owner; this.headers = this.guild.headers; - this.messages = []; this.name = JSON.recipients[0]?.username; if (JSON.recipients[0]) { this.user = new User(JSON.recipients[0], this.localuser); @@ -83,6 +82,7 @@ class Group extends Channel { this.lastmessageid = JSON.last_message_id; this.lastmessageid ??= "0"; this.mentions = 0; + this.setUpInfinateScroller(); } createguildHTML() { const div = document.createElement("div"); @@ -102,9 +102,9 @@ class Group extends Channel { if (this.guild !== this.localuser.lookingguild) { this.guild.loadGuild(); } - const prom = Message.wipeChanel(); this.guild.prevchannel = this; this.localuser.channelfocus = this; + const prom = this.infinate.delete(); await this.putmessages(); await prom; if (id !== Channel.genid) { @@ -116,38 +116,29 @@ class Group extends Channel { } messageCreate(messagep) { const messagez = new Message(messagep.d, this); + this.idToNext[this.lastmessageid] = messagez.id; + this.idToPrev[messagez.id] = this.lastmessageid; this.lastmessageid = messagez.id; + this.messageids[messagez.id] = messagez; if (messagez.author === this.localuser.user) { this.lastreadmessageid = messagez.id; + if (this.myhtml) { + this.myhtml.classList.remove("cunread"); + } } - this.messages.unshift(messagez); - const scrolly = document.getElementById("messagecontainer"); - this.messageids[messagez.id] = messagez; - if (this.localuser.lookingguild.prevchannel === this) { - var shouldScroll = scrolly.scrollTop + scrolly.clientHeight > scrolly.scrollHeight - 20; - document.getElementById("messages").appendChild(messagez.buildhtml(this.messages[1])); - } - if (shouldScroll) { - scrolly.scrollTop = scrolly.scrollHeight; - } - console.log(document.getElementById("channels").children); - if (this.localuser.lookingguild === this.guild) { - const channellist = document.getElementById("channels").children[0]; - for (const thing of channellist.children) { - if (thing["myinfo"] === this) { - channellist.prepend(thing); - break; - } + else { + if (this.myhtml) { + this.myhtml.classList.add("cunread"); } } this.unreads(); + this.infinate.addedBottom(); if (messagez.author === this.localuser.user) { return; } if (this.localuser.lookingguild.prevchannel === this && document.hasFocus()) { return; } - console.log(this.notification); if (this.notification === "all") { this.notify(messagez); } @@ -185,9 +176,9 @@ class Group extends Channel { console.log(this); div.append(buildpfp); sentdms.append(div); - div.onclick = function () { - this["noti"].guild.loadGuild(); - this["noti"].getHTML(); + div.onclick = _ => { + this.guild.loadGuild(); + this.getHTML(); }; } else if (current) { diff --git a/.dist/embed.js b/.dist/embed.js index 172bdd3..6a755cd 100644 --- a/.dist/embed.js +++ b/.dist/embed.js @@ -1,4 +1,5 @@ import { Fullscreen } from "./fullscreen.js"; +import { markdown } from "./markdown.js"; class Embed { type; owner; @@ -45,7 +46,7 @@ class Embed { authorline.append(img); } const a = document.createElement("a"); - a.innerText = this.json.author.name; + a.textContent = this.json.author.name; if (this.json.author.url) { a.href = this.json.author.url; } @@ -54,7 +55,7 @@ class Embed { embed.append(authorline); } const title = document.createElement("a"); - title.textContent = this.json.title; + title.append(markdown(this.json.title)); if (this.json.url) { title.href = this.json.url; } @@ -62,7 +63,7 @@ class Embed { embed.append(title); if (this.json.description) { const p = document.createElement("p"); - p.textContent = this.json.description; + p.append(markdown(this.json.description)); embed.append(p); } embed.append(document.createElement("br")); @@ -72,9 +73,8 @@ class Embed { const b = document.createElement("b"); b.textContent = thing.name; div.append(b); - let p; - p = document.createElement("p"); - p.textContent = thing.value; + const p = document.createElement("p"); + p.append(markdown(thing.value)); p.classList.add("embedp"); div.append(p); if (thing.inline) { diff --git a/.dist/file.js b/.dist/file.js index 2484889..90979c1 100644 --- a/.dist/file.js +++ b/.dist/file.js @@ -32,8 +32,10 @@ class File { full.show(); }; img.src = src; - img.height = this.height; - img.width = this.width; + if (this.width) { + img.height = this.height; + img.width = this.width; + } console.log(this.width, this.height); return img; } diff --git a/.dist/fullscreen.js b/.dist/fullscreen.js index 3d271b0..44d790c 100644 --- a/.dist/fullscreen.js +++ b/.dist/fullscreen.js @@ -62,7 +62,7 @@ class Fullscreen { const checkbox = document.createElement('input'); div.appendChild(checkbox); const label = document.createElement("span"); - checkbox.value = array[2]; + checkbox.checked = array[2]; label.textContent = array[1]; div.appendChild(label); checkbox.addEventListener("change", array[3]); diff --git a/.dist/index.js b/.dist/index.js index 02331b2..7421acd 100644 --- a/.dist/index.js +++ b/.dist/index.js @@ -14,9 +14,6 @@ const users = getBulkUsers(); if (!users.currentuser) { window.location.href = '/login.html'; } -var info = users.users[users.currentuser].serverurls; -let token = users.users[users.currentuser].token; -let READY; let thisuser = new Localuser(users.users[users.currentuser]); thisuser.initwebsocket().then(_ => { thisuser.loaduser(); @@ -104,7 +101,6 @@ thisuser.initwebsocket().then(_ => { }, null, _ => { return thisuser.isAdmin(); }); menu.bind(document.getElementById("channels")); } -function editchannelf(channel) { channel.editChannel(); } const pasteimage = document.getElementById("pasteimage"); let replyingto = null; async function enter(event) { @@ -145,9 +141,6 @@ typebox.addEventListener("keydown", event => { }); console.log(typebox); typebox.onclick = console.log; -let serverz = 0; -let serverid = []; -let cchanel = 0; function getguildinfo() { const path = window.location.pathname.split("/"); const channel = path[3]; @@ -155,49 +148,6 @@ function getguildinfo() { } const images = []; const imageshtml = []; -function createunknown(fname, fsize) { - const div = document.createElement("table"); - div.classList.add("unknownfile"); - const nametr = document.createElement("tr"); - div.append(nametr); - const fileicon = document.createElement("td"); - nametr.append(fileicon); - fileicon.append("🗎"); - fileicon.classList.add("fileicon"); - fileicon.rowSpan = 2; - const nametd = document.createElement("td"); - { - nametd.textContent = fname; - } - nametd.classList.add("filename"); - nametr.append(nametd); - const sizetr = document.createElement("tr"); - const size = document.createElement("td"); - sizetr.append(size); - size.textContent = "Size:" + filesizehuman(fsize); - size.classList.add("filesize"); - div.appendChild(sizetr); - return div; -} -function filesizehuman(fsize) { - var i = fsize == 0 ? 0 : Math.floor(Math.log(fsize) / Math.log(1024)); - return +((fsize / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Terabytes'][i]; -} -function createunknownfile(file) { - return createunknown(file.name, file.size); -} -function filetohtml(file) { - if (file.type.startsWith('image/')) { - const img = document.createElement('img'); - const blob = URL.createObjectURL(file); - img.src = blob; - return img; - } - else { - console.log(file.name); - return createunknownfile(file); - } -} import { File } from "./file.js"; document.addEventListener('paste', async (e) => { Array.from(e.clipboardData.files).forEach(async (f) => { @@ -214,27 +164,6 @@ function userSettings() { thisuser.usersettings.show(); } document.getElementById("settings").onclick = userSettings; -let triggered = false; -document.getElementById("messagecontainer").addEventListener("scroll", (e) => { - const messagecontainer = document.getElementById("messagecontainer"); - if (messagecontainer.scrollTop < 2000) { - if (!triggered) { - thisuser.lookingguild.prevchannel.grabmoremessages().then(() => { - triggered = false; - if (messagecontainer.scrollTop === 0) { - messagecontainer.scrollTop = 1; - } - }); - } - triggered = true; - } - else { - if (Math.abs(messagecontainer.scrollHeight - messagecontainer.scrollTop - messagecontainer.clientHeight) < 3) { - thisuser.lookingguild.prevchannel.readbottom(); - } - } - // -}); if (mobile) { document.getElementById("channelw").onclick = function () { document.getElementById("channels").parentNode.classList.add("collapse"); @@ -248,20 +177,3 @@ if (mobile) { document.getElementById("servers").classList.remove("collapse"); }; } -/* -{ - const messages=document.getElementById("messages"); - let height=messages.clientHeight; - // - const resizeObserver=new ResizeObserver(()=>{ - console.log(messages.scrollTop,messages.clientHeight-height-messages.scrollHeight); - messages.scrollTop-=height-messages.scrollHeight; - console.log(messages.scrollTop) - //if(shouldsnap){ - // document.getElementById("messagecontainer").scrollTop = document.getElementById("messagecontainer").scrollHeight; - //} - height=messages.scrollHeight; - }) - resizeObserver.observe(messages) -} -*/ diff --git a/.dist/infiniteScroller.js b/.dist/infiniteScroller.js new file mode 100644 index 0000000..ec34c33 --- /dev/null +++ b/.dist/infiniteScroller.js @@ -0,0 +1,146 @@ +class InfiniteScroller { + getIDFromOffset; + getHTMLFromID; + destroyFromID; + reachesBottom; + minDist = 3000; + maxDist = 8000; + HTMLElements = []; + div; + scroll; + constructor(getIDFromOffset, getHTMLFromID, destroyFromID, reachesBottom = () => { }) { + this.getIDFromOffset = getIDFromOffset; + this.getHTMLFromID = getHTMLFromID; + this.destroyFromID = destroyFromID; + this.reachesBottom = reachesBottom; + } + interval; + getDiv(initialId, bottom = true) { + const div = document.createElement("div"); + div.classList.add("messagecontainer"); + //div.classList.add("flexttb") + const scroll = document.createElement("div"); + scroll.classList.add("flexttb", "scroller"); + div.append(scroll); + this.div = div; + this.interval = setInterval(this.updatestuff.bind(this), 100); + this.scroll = scroll; + this.scroll.addEventListener("scroll", this.watchForChange.bind(this)); + new ResizeObserver(this.watchForChange.bind(this)).observe(div); + new ResizeObserver(this.watchForChange.bind(this)).observe(scroll); + this.firstElement(initialId); + this.updatestuff(); + this.watchForChange().then(_ => { + this.scroll.scrollTop = this.scroll.scrollHeight; + }); + return div; + } + scrollBottom; + scrollTop; + updatestuff() { + this.scrollBottom = this.scroll.scrollHeight - this.scroll.scrollTop - this.scroll.clientHeight; + this.scrollTop = this.scroll.scrollTop; + if (this.scrollBottom) { + this.reachesBottom(); + } + //this.watchForChange(); + } + firstElement(id) { + const html = this.getHTMLFromID(id); + this.scroll.append(html); + this.HTMLElements.push([html, id]); + } + currrunning = false; + async addedBottom() { + this.updatestuff(); + const scrollBottom = this.scrollBottom; + await this.watchForChange(); + if (scrollBottom < 30) { + this.scroll.scrollTop = this.scroll.scrollHeight; + } + } + async watchForChange() { + if (this.currrunning) { + return; + } + else { + this.currrunning = true; + } + let again = false; + if (!this.div) { + this.currrunning = false; + return; + } + /* + if(this.scrollTop===0){ + this.scrollTop=10; + } + */ + if (this.scrollTop === 0) { + this.scrollTop = 1; + this.scroll.scrollTop = 1; + } + if (this.scrollTop < this.minDist) { + const previd = this.HTMLElements.at(0)[1]; + const nextid = await this.getIDFromOffset(previd, 1); + if (!nextid) { + } + else { + again = true; + const html = this.getHTMLFromID(nextid); + this.scroll.prepend(html); + this.HTMLElements.unshift([html, nextid]); + this.scrollTop += 60; + } + ; + } + if (this.scrollTop > this.maxDist) { + again = true; + const html = this.HTMLElements.shift(); + await this.destroyFromID(html[1]); + this.scrollTop -= 60; + } + const scrollBottom = this.scrollBottom; + if (scrollBottom < this.minDist) { + const previd = this.HTMLElements.at(-1)[1]; + const nextid = await this.getIDFromOffset(previd, -1); + if (!nextid) { + } + else { + again = true; + const html = this.getHTMLFromID(nextid); + this.scroll.append(html); + this.HTMLElements.push([html, nextid]); + this.scrollBottom += 60; + if (scrollBottom < 30) { + this.scroll.scrollTop = this.scroll.scrollHeight; + } + } + ; + } + if (scrollBottom > this.maxDist) { + again = true; + const html = this.HTMLElements.pop(); + await this.destroyFromID(html[1]); + this.scrollBottom -= 60; + } + this.currrunning = false; + if (again) { + await this.watchForChange(); + } + this.currrunning = false; + } + async delete() { + for (const thing of this.HTMLElements) { + await this.destroyFromID(thing[1]); + } + this.HTMLElements = []; + clearInterval(this.interval); + if (this.div) { + this.div.remove(); + } + this.scroll = null; + this.div = null; + } +} +export { InfiniteScroller }; diff --git a/.dist/localuser.js b/.dist/localuser.js index b7c9d94..ed50944 100644 --- a/.dist/localuser.js +++ b/.dist/localuser.js @@ -2,7 +2,6 @@ import { Guild } from "./guild.js"; import { Direct } from "./direct.js"; import { Voice } from "./audio.js"; import { User } from "./user.js"; -import { markdown } from "./markdown.js"; import { Fullscreen } from "./fullscreen.js"; import { setTheme } from "./login.js"; const wsCodesRetry = new Set([4000, 4003, 4005, 4007, 4008, 4009]); @@ -85,7 +84,7 @@ class Localuser { outoffocus() { document.getElementById("servers").textContent = ""; document.getElementById("channels").textContent = ""; - document.getElementById("messages").textContent = ""; + this.channelfocus.infinate.delete(); this.lookingguild = null; this.channelfocus = null; } @@ -145,23 +144,8 @@ class Localuser { returny(); break; case "MESSAGE_UPDATE": - if (this.initialized) { - if (this.channelfocus.id === temp.d.channel_id) { - const find = temp.d.id; - const messagelist = document.getElementById("messages").children; - for (const message of messagelist) { - const all = message["all"]; - if (all.id === find) { - all.content = temp.d.content; - message["txt"].innerHTML = markdown(temp.d.content).innerHTML; - break; - } - } - } - else { - this.resolveChannelFromID(temp.d.channel_id).messages.find(e => e.id === temp.d.channel_id).content = temp.d.content; - } - } + const message = this.resolveChannelFromID(temp.d.channel_id).messageids[temp.d.id]; + message.giveData(temp.d); break; case "TYPING_START": if (this.initialized) { diff --git a/.dist/markdown.js b/.dist/markdown.js index 2521580..0e1febb 100644 --- a/.dist/markdown.js +++ b/.dist/markdown.js @@ -1,12 +1,15 @@ export { markdown }; function markdown(text, { keep = false, stdsize = false } = {}) { let txt; - if ((typeof txt) === "string") { + if ((typeof text) === (typeof "")) { txt = text.split(""); } else { txt = text; } + if (txt === undefined) { + txt = []; + } const span = document.createElement("span"); let current = document.createElement("span"); function appendcurrent() { @@ -399,6 +402,38 @@ function markdown(text, { keep = false, stdsize = false } = {}) { continue; } } + if (txt[i] === "<" && (txt[i + 1] === ":" || (txt[i + 1] === "a" && txt[i + 2] === ":"))) { + let found = false; + const build = txt[i + 1] === "a" ? ["<", "a", ":"] : ["<", ":"]; + let j = i + build.length; + for (; txt[j] !== void 0; j++) { + build.push(txt[j]); + if (txt[j] === ">") { + found = true; + break; + } + } + if (found) { + const parts = build.join("").match(/^<(a)?:\w+:(\d{10,30})>$/); + if (parts && parts[2]) { + appendcurrent(); + i = j; + console.log(typeof txt, txt); + const isEmojiOnly = txt.join("").trim() === build.join("").trim(); + const emojiElem = document.createElement("img"); + emojiElem.classList.add("md-emoji"); + emojiElem.width = isEmojiOnly ? 48 : 22; + emojiElem.height = isEmojiOnly ? 48 : 22; + emojiElem.crossOrigin = "anonymous"; + //emojiElem.src=this.info.cdn.toString() + "/emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32"; + //must uncomment later + emojiElem.alt = ""; + emojiElem.loading = "lazy"; + span.appendChild(emojiElem); + continue; + } + } + } current.textContent += txt[i]; } appendcurrent(); diff --git a/.dist/message.js b/.dist/message.js index f6f43b3..799f605 100644 --- a/.dist/message.js +++ b/.dist/message.js @@ -52,6 +52,9 @@ class Message { constructor(messagejson, owner) { this.owner = owner; this.headers = this.owner.headers; + this.giveData(messagejson); + } + giveData(messagejson) { for (const thing of Object.keys(messagejson)) { if (thing === "attachments") { this.attachments = []; @@ -76,6 +79,9 @@ class Message { if (this.mentionsuser(this.localuser.user)) { console.log(this); } + if (this.div) { + this.generateMessage(); + } } canDelete() { return this.channel.hasPermission("MANAGE_MESSAGES") || this.author.id === this.localuser.user.id; @@ -92,11 +98,12 @@ class Message { get info() { return this.owner.info; } - messageevents(obj) { + messageevents(obj, del = Message.del) { const func = Message.contextmenu.bind(obj, this); this.div = obj; - Message.del.then(_ => { + del.then(_ => { obj.removeEventListener("click", func); + this.div.remove(); this.div = null; }); obj.classList.add("messagediv"); @@ -136,17 +143,19 @@ class Message { this.div.innerHTML = ""; this.div = null; } - const index = this.channel.messages.indexOf(this); - this.channel.messages.splice(this.channel.messages.indexOf(this), 1); + const prev = this.channel.idToPrev[this.id]; + const next = this.channel.idToNext[this.id]; + this.channel.idToNext[prev] = next; + this.channel.idToPrev[next] = prev; delete this.channel.messageids[this.id]; - const regen = this.channel.messages[index - 1]; + const regen = this.channel.messageids[prev]; if (regen) { regen.generateMessage(); } } generateMessage(premessage = null) { if (!premessage) { - premessage = this.channel.messages[this.channel.messages.indexOf(this) + 1]; + premessage = this.channel.messageids[this.channel.idToNext[this.id]]; } const div = this.div; if (this === this.channel.replyingto) { @@ -203,7 +212,6 @@ class Message { }); div.appendChild(replyline); } - this.messageevents(div); build.classList.add("message"); div.appendChild(build); if ({ 0: true, 19: true }[this.type] || this.attachments.length !== 0) { @@ -304,14 +312,15 @@ class Message { div["all"] = this; return (div); } - buildhtml(premessage) { + buildhtml(premessage, del = Message.del) { if (this.div) { - console.error(`HTML for ${this} already exists, aborting`); + console.error(`HTML for ${this.id} already exists, aborting`); return; } //premessage??=messages.lastChild; const div = document.createElement("div"); this.div = div; + this.messageevents(div, del); return this.generateMessage(premessage); } } diff --git a/.dist/register.js b/.dist/register.js index 8db00d0..5478eaa 100644 --- a/.dist/register.js +++ b/.dist/register.js @@ -57,4 +57,4 @@ async function tosLogic() { console.log(tosPage); } tosLogic(); -checkInstance.alt = tosLogic; +checkInstance["alt"] = tosLogic; diff --git a/.dist/settings.js b/.dist/settings.js index 08ce7bd..18d032a 100644 --- a/.dist/settings.js +++ b/.dist/settings.js @@ -80,7 +80,7 @@ class PermissionToggle { div.append(name); div.append(this.generateCheckbox()); const p = document.createElement("p"); - p.innerText = this.rolejson.description; + p.textContent = this.rolejson.description; div.appendChild(p); return div; } diff --git a/webpage/channel.ts b/webpage/channel.ts index fdc76a0..15d177d 100644 --- a/webpage/channel.ts +++ b/webpage/channel.ts @@ -9,6 +9,7 @@ import { Localuser } from "./localuser.js"; import { Permissions } from "./permissions.js"; import { Settings, RoleList } from "./settings.js"; import { Role } from "./role.js"; +import {InfiniteScroller} from "./infiniteScroller.js" Settings; declare global { interface NotificationOptions { @@ -20,7 +21,6 @@ class Channel{ type:number; owner:Guild; headers:Localuser["headers"]; - messages:Message[]; name:string; id:string; parent_id:string; @@ -43,6 +43,9 @@ class Channel{ allthewayup:boolean; static contextmenu=new Contextmenu("channel menu"); replyingto:Message; + infinate:InfiniteScroller; + idToPrev:{[key:string]:string}={}; + idToNext:{[key:string]:string}={}; static setupcontextmenu(){ this.contextmenu.addbutton("Copy channel id",function(){ console.log(this) @@ -82,16 +85,45 @@ class Channel{ return order; }) } + setUpInfinateScroller(){ + const ids:{[key:string]:Function}={}; + this.infinate=new InfiniteScroller(async function(id:string,offset:number){ + if(offset===1){ + if(this.idToPrev[id]){ + return this.idToPrev[id]; + }else{ + await this.grabmoremessages(id); + return this.idToPrev[id]; + } + }else{ + return this.idToNext[id]; + } + }.bind(this), + function(this:Channel,id:string){ + let res:Function; + const promise=new Promise(_=>{res=_;}) as Promise; + const html=this.messageids[id].buildhtml(this.messageids[this.idToPrev[id]],promise); + ids[id]=res; + return html; + }.bind(this), + async function(id:string){ + ids[id](); + delete ids[id]; + return true; + }.bind(this), + this.readbottom.bind(this) + ); + } constructor(JSON,owner:Guild){ if(JSON===-1){ return; } + this.editing; this.type=JSON.type; this.owner=owner; this.headers=this.owner.headers; - this.messages=[]; this.name=JSON.name; this.id=JSON.id; this.parent_id=JSON.parent_id; @@ -113,6 +145,7 @@ class Channel{ this.position=JSON.position; this.lastreadmessageid=null; this.lastmessageid=JSON.last_message_id; + this.setUpInfinateScroller(); } isAdmin(){ return this.guild.isAdmin(); @@ -495,7 +528,7 @@ class Channel{ this.myhtml.classList.add("viewChannel") this.guild.prevchannel=this; this.localuser.channelfocus=this; - const prom=Message.wipeChanel(); + const prom=this.infinate.delete(); await this.putmessages(); await prom; if(id!==Channel.genid){ @@ -509,7 +542,7 @@ class Channel{ (document.getElementById("typebox") as HTMLInputElement).disabled=!this.canMessage; } async putmessages(){ - if(this.messages.length>=100||this.allthewayup){return}; + if(this.allthewayup){return}; const j=await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?limit=100",{ headers: this.headers, }) @@ -517,11 +550,16 @@ class Channel{ if(response.length!==100){ this.allthewayup=true; } + let prev=undefined; for(const thing of response){ - const messager=new Message(thing,this) - if(this.messageids[messager.id]===undefined){ - this.messageids[messager.id]=messager; - this.messages.push(messager); + const message=new Message(thing,this); + if(prev){ + this.idToNext[message.id]=prev.id; + this.idToPrev[prev.id]=message.id; + } + prev=message; + if(this.messageids[message.id]===undefined){ + this.messageids[message.id]=message; } } } @@ -534,25 +572,23 @@ class Channel{ } this.children=build; } - async grabmoremessages(){ - if(this.messages.length===0||this.allthewayup){ + async grabmoremessages(id:string){ + if(this.allthewayup){ return; } - const out=this; - await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?before="+this.messages[this.messages.length-1].id+"&limit=100",{ + await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?before="+id+"&limit=100",{ headers:this.headers }).then((j)=>{return j.json()}).then(response=>{ - //messages.innerHTML = ''; - //response.reverse() let next:Message; if(response.length===0){ - out.allthewayup=true; + this.allthewayup=true; } + let previd=id; for(const i in response){ let messager:Message; if(!next){ - messager=new Message(response[i],this) + messager=new Message(response[i],this); }else{ messager=next; } @@ -560,12 +596,13 @@ class Channel{ next=new Message(response[+i+1],this); }else{ next=undefined; - console.log("ohno",+i+1) + console.log("ohno",+i+1); } - if(out.messageids[messager.id]==undefined){ - out.messageids[messager.id]=messager; - out.buildmessage(messager,next); - out.messages.push(messager); + if(this.messageids[messager.id]===undefined){ + this.idToNext[messager.id]=previd; + this.idToPrev[previd]=messager.id; + previd=messager.id; + this.messageids[messager.id]=messager; }else{ console.log("How???") } @@ -579,37 +616,9 @@ class Channel{ document.getElementById("messages").prepend(built); } buildmessages(){ - for(const i in this.messages){ - const prev=this.messages[(+i)+1]; - const built=this.messages[i].buildhtml(prev); - document.getElementById("messages").prepend(built); - - if (prev) { - const prevDate=new Date(prev.timestamp); - const currentDate=new Date(this.messages[i].timestamp); - - if (prevDate.toLocaleDateString() != currentDate.toLocaleDateString()) { - const dateContainer=document.createElement("div"); - dateContainer.classList.add("replyflex"); - - const line=document.createElement("hr"); - line.classList.add("reply"); - dateContainer.appendChild(line); - - const date=document.createElement("span"); - date.textContent=currentDate.toLocaleDateString(undefined, { weekday: "long", year: "numeric", month: "long", day: "numeric" }); - dateContainer.appendChild(date); - - const line2=document.createElement("hr"); - line2.classList.add("reply"); - dateContainer.appendChild(line2); - - document.getElementById("messages").prepend(dateContainer); - } - } - } - document.getElementById("messagecontainer").scrollTop = document.getElementById("messagecontainer").scrollHeight; - + const messages=document.getElementById("channelw"); + messages.innerHTML=""; + messages.append(this.infinate.getDiv(this.lastmessageid)); } updateChannel(JSON){ this.type=JSON.type; @@ -698,7 +707,10 @@ class Channel{ messageCreate(messagep:any):void{ if(!this.hasPermission("VIEW_CHANNEL")){return} const messagez=new Message(messagep.d,this); + this.idToNext[this.lastmessageid]=messagez.id; + this.idToPrev[messagez.id]=this.lastmessageid; this.lastmessageid=messagez.id; + this.messageids[messagez.id]=messagez; if(messagez.author===this.localuser.user){ this.lastreadmessageid=messagez.id; if(this.myhtml){ @@ -710,16 +722,7 @@ class Channel{ } } this.guild.unreads(); - this.messages.unshift(messagez); - const scrolly=document.getElementById("messagecontainer"); - this.messageids[messagez.id]=messagez; - if(this.localuser.lookingguild.prevchannel===this){ - var shouldScroll=scrolly.scrollTop+scrolly.clientHeight>scrolly.scrollHeight-20; - document.getElementById("messages").appendChild(messagez.buildhtml(this.messages[1])); - } - if(shouldScroll){ - scrolly.scrollTop = scrolly.scrollHeight; - } + this.infinate.addedBottom(); if(messagez.author===this.localuser.user){ return; } @@ -731,6 +734,7 @@ class Channel{ }else if(this.notification==="mentions"&&messagez.mentionsuser(this.localuser.user)){ this.notify(messagez); } + } notititle(message:Message):string{ return message.author.username+" > "+this.guild.properties.name+" > "+this.name; diff --git a/webpage/direct.ts b/webpage/direct.ts index cf8a9de..8915f8e 100644 --- a/webpage/direct.ts +++ b/webpage/direct.ts @@ -67,7 +67,6 @@ class Group extends Channel{ super(-1,owner); this.owner=owner; this.headers=this.guild.headers; - this.messages=[]; this.name=JSON.recipients[0]?.username; if(JSON.recipients[0]){ this.user=new User(JSON.recipients[0],this.localuser); @@ -85,6 +84,7 @@ class Group extends Channel{ this.lastmessageid=JSON.last_message_id; this.lastmessageid??="0"; this.mentions=0; + this.setUpInfinateScroller(); } createguildHTML(){ const div=document.createElement("div") @@ -104,9 +104,9 @@ class Group extends Channel{ if(this.guild!==this.localuser.lookingguild){ this.guild.loadGuild(); } - const prom=Message.wipeChanel(); this.guild.prevchannel=this; this.localuser.channelfocus=this; + const prom=this.infinate.delete(); await this.putmessages(); await prom; if(id!==Channel.genid){ @@ -118,38 +118,28 @@ class Group extends Channel{ } messageCreate(messagep){ const messagez=new Message(messagep.d,this); + this.idToNext[this.lastmessageid]=messagez.id; + this.idToPrev[messagez.id]=this.lastmessageid; this.lastmessageid=messagez.id; + this.messageids[messagez.id]=messagez; if(messagez.author===this.localuser.user){ this.lastreadmessageid=messagez.id; - } - this.messages.unshift(messagez); - const scrolly=document.getElementById("messagecontainer"); - this.messageids[messagez.id]=messagez; - if(this.localuser.lookingguild.prevchannel===this){ - var shouldScroll=scrolly.scrollTop+scrolly.clientHeight>scrolly.scrollHeight-20; - document.getElementById("messages").appendChild(messagez.buildhtml(this.messages[1])); - } - if(shouldScroll){ - scrolly.scrollTop = scrolly.scrollHeight; - } - console.log(document.getElementById("channels").children) - if(this.localuser.lookingguild===this.guild){ - const channellist=document.getElementById("channels").children[0] - for(const thing of channellist.children){ - if(thing["myinfo"]===this){ - channellist.prepend(thing); - break; - } + if(this.myhtml){ + this.myhtml.classList.remove("cunread"); + } + }else{ + if(this.myhtml){ + this.myhtml.classList.add("cunread"); } } this.unreads(); + this.infinate.addedBottom(); if(messagez.author===this.localuser.user){ return; } if(this.localuser.lookingguild.prevchannel===this&&document.hasFocus()){ return; } - console.log(this.notification); if(this.notification==="all"){ this.notify(messagez); }else if(this.notification==="mentions"&&messagez.mentionsuser(this.localuser.user)){ @@ -183,9 +173,9 @@ class Group extends Channel{ console.log(this); div.append(buildpfp) sentdms.append(div); - div.onclick=function(){ - this["noti"].guild.loadGuild(); - this["noti"].getHTML(); + div.onclick=_=>{ + this.guild.loadGuild(); + this.getHTML(); } }else if(current){ diff --git a/webpage/file.ts b/webpage/file.ts index b055f7f..d71d384 100644 --- a/webpage/file.ts +++ b/webpage/file.ts @@ -34,8 +34,10 @@ class File{ full.show(); } img.src=src; - img.height=this.height; - img.width=this.width; + if(this.width){ + img.height=this.height; + img.width=this.width; + } console.log(this.width,this.height) return img; }else if(this.content_type.startsWith('video/')){ diff --git a/webpage/index.ts b/webpage/index.ts index a5d367e..48fce30 100644 --- a/webpage/index.ts +++ b/webpage/index.ts @@ -3,7 +3,7 @@ import {Contextmenu} from "./contextmenu.js"; import {mobile, getBulkUsers,setTheme, Specialuser} from "./login.js"; async function waitforload(){ - let res + let res; new Promise(r=>{res=r}); document.addEventListener("DOMContentLoaded", function(){ res(); @@ -18,9 +18,6 @@ const users=getBulkUsers(); if(!users.currentuser){ window.location.href = '/login.html'; } -var info=users.users[users.currentuser].serverurls; -let token=users.users[users.currentuser].token; -let READY; let thisuser=new Localuser(users.users[users.currentuser]); thisuser.initwebsocket().then(_=>{ @@ -117,11 +114,6 @@ thisuser.initwebsocket().then(_=>{ menu.bind(document.getElementById("channels")) } - -function editchannelf(channel){channel.editChannel();} - - - const pasteimage=document.getElementById("pasteimage"); let replyingto=null; async function enter(event){ @@ -163,17 +155,6 @@ console.log(typebox) typebox.onclick=console.log; - - -let serverz=0; -let serverid=[]; - - - - -let cchanel=0; - - function getguildinfo(){ const path=window.location.pathname.split("/"); const channel=path[3]; @@ -183,50 +164,7 @@ function getguildinfo(){ const images:Blob[]=[]; const imageshtml=[]; -function createunknown(fname,fsize){ - const div=document.createElement("table"); - div.classList.add("unknownfile"); - const nametr=document.createElement("tr"); - div.append(nametr); - const fileicon=document.createElement("td"); - nametr.append(fileicon); - fileicon.append("🗎"); - fileicon.classList.add("fileicon"); - fileicon.rowSpan=2; - const nametd=document.createElement("td"); - { - nametd.textContent=fname; - } - nametd.classList.add("filename"); - nametr.append(nametd); - const sizetr=document.createElement("tr"); - const size=document.createElement("td"); - sizetr.append(size); - size.textContent="Size:"+filesizehuman(fsize); - size.classList.add("filesize"); - div.appendChild(sizetr) - return div; -} -function filesizehuman(fsize){ - var i = fsize == 0 ? 0 : Math.floor(Math.log(fsize) / Math.log(1024)); - return +((fsize / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Terabytes'][i]; -} -function createunknownfile(file){ - return createunknown(file.name,file.size) -} -function filetohtml(file){ - if (file.type.startsWith('image/')) { - const img = document.createElement('img'); - const blob = URL.createObjectURL(file); - img.src = blob; - return img; - }else{ - console.log(file.name); - - return createunknownfile(file); - } -} import { File } from "./file.js"; document.addEventListener('paste', async (e) => { Array.from(e.clipboardData.files).forEach(async (f) => { @@ -245,26 +183,7 @@ function userSettings(){ thisuser.usersettings.show(); } document.getElementById("settings").onclick=userSettings; -let triggered=false; -document.getElementById("messagecontainer").addEventListener("scroll",(e)=>{ - const messagecontainer=document.getElementById("messagecontainer") - if(messagecontainer.scrollTop<2000){ - if(!triggered){ - thisuser.lookingguild.prevchannel.grabmoremessages().then(()=>{ - triggered=false; - if(messagecontainer.scrollTop===0){ - messagecontainer.scrollTop=1; - } - }); - } - triggered=true; - }else{ - if(Math.abs(messagecontainer.scrollHeight-messagecontainer.scrollTop-messagecontainer.clientHeight) < 3){ - thisuser.lookingguild.prevchannel.readbottom(); - } - } - // -}) + if(mobile){ document.getElementById("channelw").onclick=function(){ (document.getElementById("channels").parentNode as HTMLElement).classList.add("collapse"); @@ -278,20 +197,3 @@ if(mobile){ document.getElementById("servers").classList.remove("collapse"); } } -/* -{ - const messages=document.getElementById("messages"); - let height=messages.clientHeight; - // - const resizeObserver=new ResizeObserver(()=>{ - console.log(messages.scrollTop,messages.clientHeight-height-messages.scrollHeight); - messages.scrollTop-=height-messages.scrollHeight; - console.log(messages.scrollTop) - //if(shouldsnap){ - // document.getElementById("messagecontainer").scrollTop = document.getElementById("messagecontainer").scrollHeight; - //} - height=messages.scrollHeight; - }) - resizeObserver.observe(messages) -} -*/ diff --git a/webpage/infiniteScroller.ts b/webpage/infiniteScroller.ts new file mode 100644 index 0000000..6b3be1b --- /dev/null +++ b/webpage/infiniteScroller.ts @@ -0,0 +1,148 @@ +class InfiniteScroller{ + readonly getIDFromOffset:(ID:string,offset:number)=>Promise; + readonly getHTMLFromID:(ID:string)=>HTMLElement; + readonly destroyFromID:(ID:string)=>Promise; + readonly reachesBottom:()=>void; + private readonly minDist=3000; + private readonly maxDist=8000; + HTMLElements:[HTMLElement,string][]=[]; + div:HTMLDivElement; + scroll:HTMLDivElement; + constructor(getIDFromOffset:InfiniteScroller["getIDFromOffset"],getHTMLFromID:InfiniteScroller["getHTMLFromID"],destroyFromID:InfiniteScroller["destroyFromID"],reachesBottom:InfiniteScroller["reachesBottom"]=()=>{}){ + this.getIDFromOffset=getIDFromOffset; + this.getHTMLFromID=getHTMLFromID; + this.destroyFromID=destroyFromID; + this.reachesBottom=reachesBottom; + } + interval:NodeJS.Timeout; + getDiv(initialId:string,bottom=true):HTMLDivElement{ + const div=document.createElement("div"); + div.classList.add("messagecontainer"); + //div.classList.add("flexttb") + const scroll=document.createElement("div"); + scroll.classList.add("flexttb","scroller") + div.append(scroll); + this.div=div; + this.interval=setInterval(this.updatestuff.bind(this),100); + + this.scroll=scroll; + this.scroll.addEventListener("scroll",this.watchForChange.bind(this)); + new ResizeObserver(this.watchForChange.bind(this)).observe(div); + new ResizeObserver(this.watchForChange.bind(this)).observe(scroll); + + this.firstElement(initialId); + this.updatestuff(); + this.watchForChange().then(_=>{ + this.scroll.scrollTop=this.scroll.scrollHeight; + }) + return div; + } + scrollBottom:number; + scrollTop:number; + updatestuff(){ + this.scrollBottom = this.scroll.scrollHeight - this.scroll.scrollTop - this.scroll.clientHeight; + this.scrollTop=this.scroll.scrollTop; + if(this.scrollBottom){ + this.reachesBottom(); + } + //this.watchForChange(); + } + firstElement(id:string){ + const html=this.getHTMLFromID(id); + this.scroll.append(html); + this.HTMLElements.push([html,id]); + } + currrunning:boolean=false; + async addedBottom(){ + this.updatestuff(); + const scrollBottom=this.scrollBottom; + await this.watchForChange(); + if(scrollBottom<30){ + this.scroll.scrollTop=this.scroll.scrollHeight; + } + } + async watchForChange():Promise{ + if(this.currrunning){ + return; + }else{ + this.currrunning=true; + } + let again=false; + if(!this.div){this.currrunning=false;return} + /* + if(this.scrollTop===0){ + this.scrollTop=10; + } + */ + if(this.scrollTop===0){ + this.scrollTop=1; + this.scroll.scrollTop=1; + } + if(this.scrollTopthis.maxDist){ + + again=true; + const html=this.HTMLElements.shift(); + await this.destroyFromID(html[1]); + this.scrollTop-=60; + } + const scrollBottom = this.scrollBottom; + if(scrollBottomthis.maxDist){ + + again=true; + const html=this.HTMLElements.pop(); + await this.destroyFromID(html[1]); + this.scrollBottom-=60; + } + + this.currrunning=false; + if(again){ + await this.watchForChange(); + } + this.currrunning=false; + } + async delete():Promise{ + for(const thing of this.HTMLElements){ + await this.destroyFromID(thing[1]); + } + this.HTMLElements=[]; + clearInterval(this.interval); + if(this.div){ + this.div.remove(); + } + this.scroll=null; + this.div=null; + } +} +export {InfiniteScroller}; diff --git a/webpage/localuser.ts b/webpage/localuser.ts index 9ca8b11..76c8834 100644 --- a/webpage/localuser.ts +++ b/webpage/localuser.ts @@ -91,7 +91,7 @@ class Localuser{ outoffocus():void{ document.getElementById("servers").textContent=""; document.getElementById("channels").textContent=""; - document.getElementById("messages").textContent=""; + this.channelfocus.infinate.delete(); this.lookingguild=null; this.channelfocus=null; } @@ -154,22 +154,8 @@ class Localuser{ returny(); break; case "MESSAGE_UPDATE": - if(this.initialized){ - if(this.channelfocus.id===temp.d.channel_id){ - const find=temp.d.id; - const messagelist=document.getElementById("messages").children; - for(const message of messagelist){ - const all = message["all"]; - if(all.id===find){ - all.content=temp.d.content; - message["txt"].innerHTML=markdown(temp.d.content).innerHTML; - break; - } - } - }else{ - this.resolveChannelFromID(temp.d.channel_id).messages.find(e=>e.id===temp.d.channel_id).content=temp.d.content; - } - } + const message=this.resolveChannelFromID(temp.d.channel_id).messageids[temp.d.id]; + message.giveData(temp.d); break; case "TYPING_START": if(this.initialized){ diff --git a/webpage/markdown.ts b/webpage/markdown.ts index 5c912e4..128297d 100644 --- a/webpage/markdown.ts +++ b/webpage/markdown.ts @@ -1,11 +1,14 @@ export {markdown}; function markdown(text : string|string[],{keep=false,stdsize=false} = {}){ let txt : string[]; - if((typeof txt)==="string"){ + if((typeof text)===(typeof "")){ txt=(text as string).split(""); }else{ txt=(text as string[]); } + if(txt===undefined){ + txt=[]; + } const span=document.createElement("span"); let current=document.createElement("span"); function appendcurrent(){ @@ -378,7 +381,7 @@ function markdown(text : string|string[],{keep=false,stdsize=false} = {}){ if (parts && parts[2]) { appendcurrent(); i=j; - + console.log(typeof txt,txt); const isEmojiOnly = txt.join("").trim()===build.join("").trim(); const emojiElem=document.createElement("img"); @@ -386,7 +389,8 @@ function markdown(text : string|string[],{keep=false,stdsize=false} = {}){ emojiElem.width=isEmojiOnly ? 48 : 22; emojiElem.height=isEmojiOnly ? 48 : 22; emojiElem.crossOrigin="anonymous"; - emojiElem.src=this.info.cdn.toString() + "/emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32"; + //emojiElem.src=this.info.cdn.toString() + "/emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32"; + //must uncomment later emojiElem.alt=""; emojiElem.loading="lazy"; span.appendChild(emojiElem); diff --git a/webpage/message.ts b/webpage/message.ts index 9a7f02b..91eb35b 100644 --- a/webpage/message.ts +++ b/webpage/message.ts @@ -3,7 +3,6 @@ import {User} from "./user.js"; import {Member} from "./member.js"; import {markdown} from "./markdown.js"; import {Embed} from "./embed.js"; -import {Fullscreen} from "./fullscreen.js"; import { Channel } from "./channel.js"; import {Localuser} from "./localuser.js"; import { Role } from "./role.js"; @@ -57,6 +56,10 @@ class Message{ constructor(messagejson,owner:Channel){ this.owner=owner; this.headers=this.owner.headers; + this.giveData(messagejson); + + } + giveData(messagejson){ for(const thing of Object.keys(messagejson)){ if(thing==="attachments"){ this.attachments=[]; @@ -81,6 +84,9 @@ class Message{ if(this.mentionsuser(this.localuser.user)){ console.log(this); } + if(this.div){ + this.generateMessage(); + } } canDelete(){ return this.channel.hasPermission("MANAGE_MESSAGES")||this.author.id===this.localuser.user.id; @@ -97,11 +103,12 @@ class Message{ get info(){ return this.owner.info; } - messageevents(obj:HTMLDivElement){ + messageevents(obj:HTMLDivElement,del=Message.del){ const func=Message.contextmenu.bind(obj,this); this.div=obj; - Message.del.then(_=>{ + del.then(_=>{ obj.removeEventListener("click",func); + this.div.remove(); this.div=null; }) obj.classList.add("messagediv"); @@ -140,17 +147,19 @@ class Message{ this.div.innerHTML=""; this.div=null; } - const index=this.channel.messages.indexOf(this); - this.channel.messages.splice(this.channel.messages.indexOf(this),1); + const prev=this.channel.idToPrev[this.id]; + const next=this.channel.idToNext[this.id]; + this.channel.idToNext[prev]=next; + this.channel.idToPrev[next]=prev; delete this.channel.messageids[this.id]; - const regen=this.channel.messages[index-1] + const regen=this.channel.messageids[prev] if(regen){ regen.generateMessage(); } } generateMessage(premessage:Message=null){ if(!premessage){ - premessage=this.channel.messages[this.channel.messages.indexOf(this)+1]; + premessage=this.channel.messageids[this.channel.idToNext[this.id]]; } const div=this.div; if(this===this.channel.replyingto){ @@ -209,8 +218,6 @@ class Message{ }); div.appendChild(replyline); } - - this.messageevents(div); build.classList.add("message"); div.appendChild(build); if({0:true,19:true}[this.type]||this.attachments.length!==0){ @@ -313,11 +320,13 @@ class Message{ div["all"]=this; return(div) } - buildhtml(premessage:Message){ - if(this.div){console.error(`HTML for ${this} already exists, aborting`);return;} + buildhtml(premessage:Message,del:Promise=Message.del){ + if(this.div){console.error(`HTML for ${this.id} already exists, aborting`);return;} //premessage??=messages.lastChild; const div=document.createElement("div"); this.div=div; + + this.messageevents(div,del); return this.generateMessage(premessage); } } diff --git a/webpage/register.ts b/webpage/register.ts index afc0d17..4a72f0d 100644 --- a/webpage/register.ts +++ b/webpage/register.ts @@ -58,4 +58,4 @@ async function tosLogic(){ } tosLogic(); -checkInstance.alt=tosLogic; +checkInstance["alt"]=tosLogic; diff --git a/webpage/style.css b/webpage/style.css index eb154e8..eb4a392 100644 --- a/webpage/style.css +++ b/webpage/style.css @@ -74,6 +74,8 @@ th { flex-wrap: nowrap; flex-direction: column; max-height: 20in; + flex-shrink: 0; + width: 100%; } pre { background-color: var(--code-bg); @@ -215,6 +217,8 @@ img { vertical-align: middle; max-width: 3in; max-height: 3in; + width: auto; + height: auto; } #page { @@ -242,8 +246,8 @@ img { font-weight: normal; } -#messagecontainer { - overflow-y: auto; +.messagecontainer { + overflow-y: hidden; display: flex; max-width: 100%; flex-shrink: 1; @@ -725,7 +729,7 @@ textarea { } .servernamediv { - /* width: 100%; */ + width: 99%; /* max-width: 100%; */ } @@ -1169,6 +1173,7 @@ span { /* margin-bottom: 1in; */ /* padding-bottom: .1in; */ align-items: flex-start; + width: 100%; } .settingbuttons{ padding-top:.075in; @@ -1348,6 +1353,12 @@ span { overflow: hidden; flex-wrap: wrap; width: 100%; - flex-direction: row; + flex-direction: column; max-height:100in; } +<<<<<<< Updated upstream +======= +.sizeupdown{ + height:4in; +} +>>>>>>> Stashed changes