From 032e1b5be6c26dacce610989cd7b0517cd327e5f Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 17 Aug 2024 20:57:08 -0500 Subject: [PATCH] improve loading of channels --- .dist/channel.js | 90 ++++++++++++++++++++++++++----------- .dist/embed.js | 11 +++++ .dist/infiniteScroller.js | 40 +++++++++++------ .dist/message.js | 35 ++++++++++----- webpage/channel.ts | 90 +++++++++++++++++++++++++------------ webpage/embed.ts | 11 +++++ webpage/index.html | 6 +-- webpage/index.ts | 2 + webpage/infiniteScroller.ts | 19 +++++--- webpage/jsontypes.ts | 2 + webpage/message.ts | 32 ++++++++----- webpage/style.css | 38 ++++++++++++++++ 12 files changed, 276 insertions(+), 100 deletions(-) diff --git a/.dist/channel.js b/.dist/channel.js index 623f1a0..0ccb793 100644 --- a/.dist/channel.js +++ b/.dist/channel.js @@ -149,7 +149,6 @@ class Channel { }); } setUpInfiniteScroller() { - const ids = {}; this.infinite = new InfiniteScroller(async function (id, offset) { const snowflake = SnowFlake.getSnowFlakeFromID(id, Message); if (offset === 1) { @@ -174,24 +173,28 @@ class Channel { } } }.bind(this), async function (id) { - let res; - const promise = new Promise(_ => { res = _; }); + //await new Promise(_=>{setTimeout(_,Math.random()*10)}) const snowflake = SnowFlake.getSnowFlakeFromID(id, Message); if (!snowflake.getObject()) { - await this.grabArround(id); + //await this.grabArround(id); + console.error("Uh..."); + } + try { + const html = snowflake.getObject().buildhtml(this.messageids.get(this.idToPrev.get(snowflake))); + return html; + } + catch (e) { + console.error(e); } - const html = snowflake.getObject().buildhtml(this.messageids.get(this.idToPrev.get(snowflake)), promise); - ids[id] = res; - return html; }.bind(this), async function (id) { - if (ids[id]) { - ids[id](); - delete ids[id]; - return true; + const message = SnowFlake.getSnowFlakeFromID(id, Message).getObject(); + try { + message.deleteDiv(); } - else { - return true; + catch (e) { + console.error(e); } + finally { } }.bind(this), this.readbottom.bind(this)); } constructor(json, owner) { @@ -620,6 +623,9 @@ class Channel { const prom = this.infinite.delete(); history.pushState(null, null, "/channels/" + this.guild_id + "/" + this.snowflake); document.getElementById("channelname").textContent = "#" + this.name; + const loading = document.getElementById("loadingdiv"); + Channel.regenLoadingMessages(); + loading.classList.add("loading"); await this.putmessages(); await prom; if (id !== Channel.genid) { @@ -627,15 +633,41 @@ class Channel { } this.makereplybox(); await this.buildmessages(); + //loading.classList.remove("loading"); console.log(this); document.getElementById("typebox").contentEditable = "" + this.canMessage; } + static regenLoadingMessages() { + const loading = document.getElementById("loadingdiv"); + loading.innerHTML = ""; + for (let i = 0; i < 15; i++) { + const div = document.createElement("div"); + div.classList.add("loadingmessage"); + if (Math.random() < .5) { + const pfp = document.createElement("div"); + pfp.classList.add("loadingpfp"); + const username = document.createElement("div"); + username.style.width = Math.floor(Math.random() * 96 * 1.5 + 40) + "px"; + username.classList.add("loadingcontent"); + div.append(pfp, username); + } + const content = document.createElement("div"); + content.style.width = Math.floor(Math.random() * 96 * 3 + 40) + "px"; + content.style.height = Math.floor(Math.random() * 3 + 1) * 20 + "px"; + content.classList.add("loadingcontent"); + div.append(content); + loading.append(div); + } + } lastmessage; async putmessages() { if (this.allthewayup) { return; } ; + if (this.lastreadmessageid && this.lastreadmessageid.getObject()) { + return; + } const j = await fetch(this.info.api + "/channels/" + this.snowflake + "/messages?limit=100", { headers: this.headers, }); @@ -764,8 +796,11 @@ class Channel { async tryfocusinfinate() { if (this.infinitefocus) return; + this.infinitefocus = true; const messages = document.getElementById("channelw"); - messages.innerHTML = ""; + const loading = document.getElementById("loadingdiv"); + const removetitle = document.getElementById("removetitle"); + //messages.innerHTML=""; let id; if (this.lastreadmessageid && this.lastreadmessageid.getObject()) { id = this.lastreadmessageid; @@ -774,31 +809,36 @@ class Channel { } else if (this.lastmessage && this.lastmessage.snowflake) { id = this.goBackIds(this.lastmessage.snowflake, 50); - console.log("shouldn't"); } if (!id) { - const title = document.createElement("h2"); - title.textContent = "No messages appear to be here, be the first to say something!"; - title.classList.add("titlespace"); - messages.append(title); + if (removetitle) { + const title = document.createElement("h2"); + title.id = "removetitle"; + title.textContent = "No messages appear to be here, be the first to say something!"; + title.classList.add("titlespace"); + messages.append(title); + } + this.infinitefocus = false; + loading.classList.remove("loading"); return; } - messages.innerHTML = ""; + else if (removetitle) { + removetitle.remove(); + } messages.append(await this.infinite.getDiv(id.id)); this.infinite.updatestuff(); this.infinite.watchForChange().then(async (_) => { - await new Promise(resolve => setTimeout(resolve, 0)); + //await new Promise(resolve => setTimeout(resolve, 0)); this.infinite.focus(id.id, false); //if someone could figure out how to make this work correctly without this, that's be great :P + loading.classList.remove("loading"); }); - this.infinite.focus(id.id, false); - this.infinitefocus = true; + //this.infinite.focus(id.id,false); } goBackIds(id, back, returnifnotexistant = true) { while (back !== 0) { const nextid = this.idToPrev.get(id); if (nextid) { id = nextid; - console.log(id); back--; } else { @@ -898,7 +938,6 @@ class Channel { if (replyjson) { body.message_reference = replyjson; } - console.log(body); return await fetch(this.info.api + "/channels/" + this.snowflake + "/messages", { method: "POST", headers: this.headers, @@ -917,7 +956,6 @@ class Channel { } formData.append('payload_json', JSON.stringify(body)); for (const i in attachments) { - console.log(attachments[i]); formData.append("files[" + i + "]", attachments[i]); } return await fetch(this.info.api + "/channels/" + this.snowflake + "/messages", { diff --git a/.dist/embed.js b/.dist/embed.js index a662fb1..0452a46 100644 --- a/.dist/embed.js +++ b/.dist/embed.js @@ -132,6 +132,17 @@ class Embed { full.show(); }; img.src = this.json.thumbnail.proxy_url; + if (this.json.thumbnail.width) { + let scale = 1; + const max = 96 * 3; + scale = Math.max(scale, this.json.thumbnail.width / max); + scale = Math.max(scale, this.json.thumbnail.height / max); + this.json.thumbnail.width /= scale; + this.json.thumbnail.height /= scale; + } + img.style.width = this.json.thumbnail.width + "px"; + img.style.height = this.json.thumbnail.height + "px"; + console.log(this.json, "Image fix"); return img; } generateLink() { diff --git a/.dist/infiniteScroller.js b/.dist/infiniteScroller.js index c289bd2..aa0cfa7 100644 --- a/.dist/infiniteScroller.js +++ b/.dist/infiniteScroller.js @@ -21,7 +21,7 @@ class InfiniteScroller { //div.classList.add("flexttb") const scroll = document.createElement("div"); scroll.classList.add("flexttb", "scroller"); - div.append(scroll); + div.appendChild(scroll); this.div = div; this.interval = setInterval(this.updatestuff.bind(this), 100); this.scroll = scroll; @@ -47,7 +47,7 @@ class InfiniteScroller { } async firstElement(id) { const html = await this.getHTMLFromID(id); - this.scroll.append(html); + this.scroll.appendChild(html); this.HTMLElements.push([html, id]); } currrunning = false; @@ -79,6 +79,11 @@ class InfiniteScroller { else { again = true; const html = await this.getHTMLFromID(nextid); + if (!html) { + this.destroyFromID(nextid); + console.error("html isn't defined"); + throw Error("html isn't defined"); + } this.scroll.prepend(html); this.HTMLElements.unshift([html, nextid]); this.scrollTop += 60; @@ -106,7 +111,7 @@ class InfiniteScroller { else { again = true; const html = await this.getHTMLFromID(nextid); - this.scroll.append(html); + this.scroll.appendChild(html); this.HTMLElements.push([html, nextid]); this.scrollBottom += 60; if (scrollBottom < 30) { @@ -126,18 +131,26 @@ class InfiniteScroller { } } async watchForChange() { - if (this.currrunning) { - return; - } - else { - this.currrunning = true; - } - if (!this.div) { + try { + if (this.currrunning) { + return; + } + else { + this.currrunning = true; + } + if (!this.div) { + this.currrunning = false; + return; + } + await Promise.allSettled([this.watchForTop(), this.watchForBottom()]); + if (!this.currrunning) { + console.error("something really bad happened"); + } this.currrunning = false; - return; } - await Promise.allSettled([this.watchForBottom(), this.watchForTop()]); - this.currrunning = false; + catch (e) { + console.error(e); + } } async focus(id, flash = true) { let element; @@ -146,7 +159,6 @@ class InfiniteScroller { element = thing[0]; } } - console.log(element, id, ":3"); if (element) { if (flash) { element.scrollIntoView({ diff --git a/.dist/message.js b/.dist/message.js index fca2bed..50f23f0 100644 --- a/.dist/message.js +++ b/.dist/message.js @@ -172,15 +172,23 @@ class Message { get info() { return this.owner.info; } - messageevents(obj, del = Message.del) { + messageevents(obj) { const func = Message.contextmenu.bind(obj, this); this.div = obj; - del.then(_ => { - obj.removeEventListener("click", func); + obj.classList.add("messagediv"); + } + deleteDiv() { + console.log(this.id); + if (!this.div) + return; + try { this.div.remove(); this.div = null; - }); - obj.classList.add("messagediv"); + console.log("done"); + } + catch (e) { + console.error(e); + } } mentionsuser(userd) { if (userd instanceof User) { @@ -461,16 +469,21 @@ class Message { } } } - buildhtml(premessage, del = Message.del) { + buildhtml(premessage) { if (this.div) { console.error(`HTML for ${this.snowflake} already exists, aborting`); return; } - //premessage??=messages.lastChild; - const div = document.createElement("div"); - this.div = div; - this.messageevents(div, del); - return this.generateMessage(premessage); + try { + //premessage??=messages.lastChild; + const div = document.createElement("div"); + this.div = div; + this.messageevents(div); + return this.generateMessage(premessage); + } + catch (e) { + console.error(e); + } } } function formatTime(date) { diff --git a/webpage/channel.ts b/webpage/channel.ts index 7cc5ca3..55d157f 100644 --- a/webpage/channel.ts +++ b/webpage/channel.ts @@ -165,7 +165,6 @@ class Channel{ }) } setUpInfiniteScroller(){ - const ids:{[key:string]:Function}={}; this.infinite=new InfiniteScroller(async function(this:Channel,id:string,offset:number):Promise{ const snowflake=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake; if(offset===1){ @@ -187,24 +186,24 @@ class Channel{ } }.bind(this), async function(this:Channel,id:string){ - let res:Function; - const promise=new Promise(_=>{res=_;}) as Promise; + //await new Promise(_=>{setTimeout(_,Math.random()*10)}) const snowflake=SnowFlake.getSnowFlakeFromID(id,Message); if(!snowflake.getObject()){ - await this.grabArround(id); + //await this.grabArround(id); + console.error("Uh...") + } + try{ + const html=snowflake.getObject().buildhtml(this.messageids.get(this.idToPrev.get(snowflake))); + return html; + }catch(e){ + console.error(e); } - const html=snowflake.getObject().buildhtml(this.messageids.get(this.idToPrev.get(snowflake)),promise); - ids[id]=res; - return html; }.bind(this), async function(this:Channel,id:string){ - if(ids[id]){ - ids[id](); - delete ids[id]; - return true; - }else{ - return true; - } + const message=SnowFlake.getSnowFlakeFromID(id,Message).getObject(); + try{ + message.deleteDiv(); + }catch(e){console.error(e)}finally{} }.bind(this), this.readbottom.bind(this) ); @@ -630,6 +629,9 @@ class Channel{ const prom=this.infinite.delete(); history.pushState(null, null,"/channels/"+this.guild_id+"/"+this.snowflake); document.getElementById("channelname").textContent="#"+this.name; + const loading=document.getElementById("loadingdiv"); + Channel.regenLoadingMessages(); + loading.classList.add("loading"); await this.putmessages(); await prom; if(id!==Channel.genid){ @@ -638,13 +640,38 @@ class Channel{ this.makereplybox(); await this.buildmessages(); - + //loading.classList.remove("loading"); console.log(this); document.getElementById("typebox").contentEditable=""+this.canMessage; } + static regenLoadingMessages(){ + const loading=document.getElementById("loadingdiv"); + loading.innerHTML=""; + for(let i=0;i<15;i++){ + const div=document.createElement("div"); + div.classList.add("loadingmessage"); + if(Math.random()<.5){ + const pfp=document.createElement("div") + pfp.classList.add("loadingpfp"); + const username=document.createElement("div"); + username.style.width=Math.floor(Math.random()*96*1.5+40)+"px"; + username.classList.add("loadingcontent"); + div.append(pfp,username); + } + const content=document.createElement("div"); + content.style.width=Math.floor(Math.random()*96*3+40)+"px"; + content.style.height=Math.floor(Math.random()*3+1)*20+"px"; + content.classList.add("loadingcontent"); + div.append(content); + loading.append(div); + } + } lastmessage:Message; async putmessages(){ if(this.allthewayup){return}; + if(this.lastreadmessageid&&this.lastreadmessageid.getObject()){ + return + } const j=await fetch(this.info.api+"/channels/"+this.snowflake+"/messages?limit=100",{ headers: this.headers, }); @@ -773,41 +800,48 @@ class Channel{ infinitefocus=false; private async tryfocusinfinate(){ if(this.infinitefocus) return; + this.infinitefocus=true; const messages=document.getElementById("channelw"); - messages.innerHTML=""; + const loading=document.getElementById("loadingdiv"); + const removetitle=document.getElementById("removetitle"); + //messages.innerHTML=""; let id:SnowFlake; - if(this.lastreadmessageid&&this.lastreadmessageid.getObject()){ id=this.lastreadmessageid; }else if(id=this.findClosest(this.lastreadmessageid)){ }else if(this.lastmessage&&this.lastmessage.snowflake){ id=this.goBackIds(this.lastmessage.snowflake,50); - console.log("shouldn't"); } if(!id){ - const title=document.createElement("h2"); - title.textContent="No messages appear to be here, be the first to say something!" - title.classList.add("titlespace"); - messages.append(title); + if(removetitle){ + const title=document.createElement("h2"); + title.id="removetitle"; + title.textContent="No messages appear to be here, be the first to say something!" + title.classList.add("titlespace"); + messages.append(title); + } + this.infinitefocus=false; + loading.classList.remove("loading"); return; + }else if(removetitle){ + removetitle.remove(); } - messages.innerHTML=""; messages.append(await this.infinite.getDiv(id.id)); this.infinite.updatestuff(); this.infinite.watchForChange().then(async _=>{ - await new Promise(resolve => setTimeout(resolve, 0)); + //await new Promise(resolve => setTimeout(resolve, 0)); this.infinite.focus(id.id,false);//if someone could figure out how to make this work correctly without this, that's be great :P + loading.classList.remove("loading"); }); - this.infinite.focus(id.id,false); - this.infinitefocus=true; + //this.infinite.focus(id.id,false); + } private goBackIds(id:SnowFlake,back:number,returnifnotexistant=true):SnowFlake{ while(back!==0){ const nextid=this.idToPrev.get(id); if(nextid){ id=nextid; - console.log(id); back--; }else{ if(returnifnotexistant){ @@ -895,7 +929,6 @@ class Channel{ if(replyjson){ body.message_reference=replyjson; } - console.log(body) return await fetch(this.info.api+"/channels/"+this.snowflake+"/messages",{ method:"POST", headers:this.headers, @@ -913,7 +946,6 @@ class Channel{ } formData.append('payload_json', JSON.stringify(body)); for(const i in attachments){ - console.log(attachments[i]) formData.append("files["+i+"]",attachments[i]); } return await fetch(this.info.api+"/channels/"+this.snowflake+"/messages", { diff --git a/webpage/embed.ts b/webpage/embed.ts index 50094cb..8b96f27 100644 --- a/webpage/embed.ts +++ b/webpage/embed.ts @@ -137,6 +137,17 @@ class Embed{ full.show(); } img.src=this.json.thumbnail.proxy_url; + if(this.json.thumbnail.width){ + let scale=1; + const max=96*3; + scale=Math.max(scale,this.json.thumbnail.width/max); + scale=Math.max(scale,this.json.thumbnail.height/max); + this.json.thumbnail.width/=scale; + this.json.thumbnail.height/=scale; + } + img.style.width=this.json.thumbnail.width+"px"; + img.style.height=this.json.thumbnail.height+"px"; + console.log(this.json,"Image fix"); return img; } generateLink(){ diff --git a/webpage/index.html b/webpage/index.html index f1cc77a..33cf0ba 100644 --- a/webpage/index.html +++ b/webpage/index.html @@ -19,7 +19,7 @@
- +

Jank Client is loading

This shouldn't take long

Switch Accounts

@@ -54,9 +54,7 @@ Channel
-
-
-
+
diff --git a/webpage/index.ts b/webpage/index.ts index b3c8a1f..e84ca69 100644 --- a/webpage/index.ts +++ b/webpage/index.ts @@ -208,3 +208,5 @@ if(mobile){ document.getElementById("servers").classList.remove("collapse"); } } + + diff --git a/webpage/infiniteScroller.ts b/webpage/infiniteScroller.ts index 1c72cab..7f1c9c6 100644 --- a/webpage/infiniteScroller.ts +++ b/webpage/infiniteScroller.ts @@ -21,7 +21,7 @@ class InfiniteScroller{ //div.classList.add("flexttb") const scroll=document.createElement("div"); scroll.classList.add("flexttb","scroller") - div.append(scroll); + div.appendChild(scroll); this.div=div; this.interval=setInterval(this.updatestuff.bind(this),100); @@ -49,7 +49,7 @@ class InfiniteScroller{ } async firstElement(id:string){ const html=await this.getHTMLFromID(id); - this.scroll.append(html); + this.scroll.appendChild(html); this.HTMLElements.push([html,id]); } currrunning:boolean=false; @@ -81,6 +81,11 @@ class InfiniteScroller{ }else{ again=true; const html=await this.getHTMLFromID(nextid); + if(!html){ + this.destroyFromID(nextid); + console.error("html isn't defined"); + throw Error("html isn't defined"); + } this.scroll.prepend(html); this.HTMLElements.unshift([html,nextid]); this.scrollTop+=60; @@ -109,7 +114,7 @@ class InfiniteScroller{ }else{ again=true; const html=await this.getHTMLFromID(nextid); - this.scroll.append(html); + this.scroll.appendChild(html); this.HTMLElements.push([html,nextid]); this.scrollBottom+=60; if(scrollBottom<30){ @@ -129,14 +134,19 @@ class InfiniteScroller{ } } async watchForChange():Promise{ + try{ if(this.currrunning){ return; }else{ this.currrunning=true; } if(!this.div){this.currrunning=false;return} - await Promise.allSettled([this.watchForBottom(),this.watchForTop()]) + await Promise.allSettled([this.watchForTop(),this.watchForBottom()]) + if(!this.currrunning){console.error("something really bad happened")} this.currrunning=false; + }catch(e){ + console.error(e); + } } async focus(id:string,flash=true){ let element:HTMLElement; @@ -145,7 +155,6 @@ class InfiniteScroller{ element=thing[0]; } } - console.log(element,id,":3"); if(element){ if(flash){ diff --git a/webpage/jsontypes.ts b/webpage/jsontypes.ts index 0678bab..0d1a312 100644 --- a/webpage/jsontypes.ts +++ b/webpage/jsontypes.ts @@ -322,6 +322,8 @@ type embedjson={ thumbnail:{ proxy_url:string, url:string, + width:number, + height:number }, provider:{ name:string, diff --git a/webpage/message.ts b/webpage/message.ts index b40630e..a9b4252 100644 --- a/webpage/message.ts +++ b/webpage/message.ts @@ -176,15 +176,21 @@ class Message{ get info(){ return this.owner.info; } - messageevents(obj:HTMLDivElement,del=Message.del){ + messageevents(obj:HTMLDivElement){ const func=Message.contextmenu.bind(obj,this); this.div=obj; - del.then(_=>{ - obj.removeEventListener("click",func); + obj.classList.add("messagediv"); + } + deleteDiv(){ + console.log(this.id); + if(!this.div) return; + try{ this.div.remove(); this.div=null; - }) - obj.classList.add("messagediv"); + console.log("done"); + }catch(e){ + console.error(e) + } } mentionsuser(userd:User|Member){ if(userd instanceof User){ @@ -465,14 +471,18 @@ class Message{ } } } - buildhtml(premessage:Message,del:Promise=Message.del){ + buildhtml(premessage:Message){ if(this.div){console.error(`HTML for ${this.snowflake} already exists, aborting`);return;} - //premessage??=messages.lastChild; - const div=document.createElement("div"); - this.div=div; + try{ + //premessage??=messages.lastChild; + const div=document.createElement("div"); + this.div=div; - this.messageevents(div,del); - return this.generateMessage(premessage); + this.messageevents(div); + return this.generateMessage(premessage); + }catch(e){ + console.error(e); + } } } diff --git a/webpage/style.css b/webpage/style.css index a1e1b2d..b4d69b5 100644 --- a/webpage/style.css +++ b/webpage/style.css @@ -557,6 +557,7 @@ hr { min-height: 0; height: 100%; /* width: 100%; */ + position: relative; } .timestamp { @@ -1891,4 +1892,41 @@ form div{ flex-wrap: wrap; justify-content: flex-start; align-items: flex-end; +} +#loadingdiv{ + position:absolute; + top:0; + left:0; + width:100%; + height:0px; + background: var(--primary-bg); + opacity:0; + &.loading{ + opacity:1; + height:100%; + } + ; + /* overflow: hidden; */ + display: flex; + flex-direction: column-reverse; + overflow-y: scroll; +} +.loadingmessage{ + position:relative; +} +.loadingpfp{ + position:absolute; + width:.4in; + height:.4in; + background:var(--channel-hover); + + margin-left:.05in; + border-radius:1in; +} +.loadingcontent{ + margin-left:.5in; + background:var(--channel-hover); + margin-bottom:.1in; + border-radius:.1in; + height:17px; } \ No newline at end of file