diff --git a/src/webpage/hover.ts b/src/webpage/hover.ts index fcd5982..aa02bbd 100644 --- a/src/webpage/hover.ts +++ b/src/webpage/hover.ts @@ -2,29 +2,43 @@ import { Contextmenu } from "./contextmenu.js"; import { MarkDown } from "./markdown.js"; class Hover{ - str:string|MarkDown - constructor(txt:string|MarkDown){ + str:string|MarkDown|(()=>Promise|MarkDown|string); + constructor(txt:string|MarkDown|(()=>Promise|MarkDown|string)){ this.str=txt; } addEvent(elm:HTMLElement){ let timeOut=setTimeout(()=>{},0); let elm2=document.createElement("div"); elm.addEventListener("mouseover",()=>{ - timeOut=setTimeout(()=>{ - elm2=this.makeHover(elm); + timeOut=setTimeout(async ()=>{ + elm2=await this.makeHover(elm); },750) }); elm.addEventListener("mouseout",()=>{ clearTimeout(timeOut); elm2.remove(); - }) + }); + new MutationObserver(function (e) { + if (e[0].removedNodes) { + clearTimeout(timeOut); + elm2.remove(); + }; + }).observe(elm,{ childList: true }); } - makeHover(elm:HTMLElement){ + async makeHover(elm:HTMLElement){ + if(!document.contains(elm)) return document.createDocumentFragment() as unknown as HTMLDivElement; const div=document.createElement("div"); if(this.str instanceof MarkDown){ - div.append(this.str.makeHTML({stdsize:true})) + div.append(this.str.makeHTML()) + }else if(this.str instanceof Function){ + const hover=await this.str(); + if(hover instanceof MarkDown){ + div.append(hover.makeHTML()); + }else{ + div.innerText=hover; + } }else{ - div.append(this.str); + div.innerText=this.str; } const box=elm.getBoundingClientRect(); div.style.top=(box.bottom+4)+"px"; diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index 43d5288..5e953e3 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -1473,7 +1473,7 @@ class Localuser{ localStorage.setItem("Voice enabled","true") }else{ - box.value=true; + box.value=false; const checkbox=box.input.deref(); if(checkbox){ checkbox.checked=false; @@ -1483,6 +1483,23 @@ class Localuser{ localStorage.removeItem("Voice enabled"); } } + const box2=security.addCheckboxInput("Enable logging of bad stuff",()=>{},{initState:Boolean(localStorage.getItem("logbad"))}); + box2.onchange=(e)=>{ + if(e){ + if(confirm("this is meant for spacebar devs")){ + localStorage.setItem("logbad","true") + + }else{ + box2.value=false; + const checkbox=box2.input.deref(); + if(checkbox){ + checkbox.checked=false; + } + } + }else{ + localStorage.removeItem("logbad"); + } + } } }; genSecurity(); diff --git a/src/webpage/member.ts b/src/webpage/member.ts index 6104e3e..d08be76 100644 --- a/src/webpage/member.ts +++ b/src/webpage/member.ts @@ -359,6 +359,9 @@ class Member extends SnowFlake{ ): Promise{ let user: User; if(owner.localuser.userMap.has(memberjson.id)){ + if(memberjson.user){ + new User(memberjson.user, owner.localuser); + } user = owner.localuser.userMap.get(memberjson.id) as User; }else if(memberjson.user){ user = new User(memberjson.user, owner.localuser); diff --git a/src/webpage/message.ts b/src/webpage/message.ts index a65dd2d..27d632b 100644 --- a/src/webpage/message.ts +++ b/src/webpage/message.ts @@ -8,7 +8,7 @@ import{ Localuser }from"./localuser.js"; import{ Role }from"./role.js"; import{ File }from"./file.js"; import{ SnowFlake }from"./snowflake.js"; -import{ memberjson, messagejson }from"./jsontypes.js"; +import{ memberjson, messagejson, userjson }from"./jsontypes.js"; import{ Emoji }from"./emoji.js"; import{ mobile }from"./utils/utils.js"; import { I18n } from "./i18n.js"; @@ -725,17 +725,42 @@ class Message extends SnowFlake{ } let emoji: HTMLElement; if(thing.emoji.id || /\d{17,21}/.test(thing.emoji.name)){ - if(/\d{17,21}/.test(thing.emoji.name)) + if(/\d{17,21}/.test(thing.emoji.name)){ thing.emoji.id = thing.emoji.name; //Should stop being a thing once the server fixes this bug - const emo = new Emoji( - thing.emoji as { name: string; id: string; animated: boolean }, - this.guild - ); + } + const emo = new Emoji(thing.emoji as { name: string; id: string; animated: boolean },this.guild); emoji = emo.getHTML(false); }else{ emoji = document.createElement("p"); emoji.textContent = thing.emoji.name; } + const h=new Hover(async ()=>{ + //TODO this can't be real, name conflicts must happen, but for now it's fine + const f=await fetch(`${this.info.api}/channels/${this.channel.id}/messages/${this.id}/reactions/${thing.emoji.name}?limit=3&type=0`,{headers:this.headers}); + const json=await f.json() as userjson[]; + let build=""; + let users=json.map(_=>new User(_,this.localuser)); + //FIXME this is a spacebar bug, I can't fix this the api ignores limit and just sends everything. + users=users.splice(0,3); + let first=true; + for(const user of users){ + if(!first){ + build+=", "; + } + build+=user.name; + first=false; + } + if(thing.count>3){ + build+=", and more!" + }else{ + + } + build+="\nReacted with "+thing.emoji.name; + console.log(build); + return build; + + }); + h.addEvent(reaction); const count = document.createElement("p"); count.textContent = "" + thing.count; count.classList.add("reactionCount"); diff --git a/src/webpage/user.ts b/src/webpage/user.ts index 5175644..6401446 100644 --- a/src/webpage/user.ts +++ b/src/webpage/user.ts @@ -38,6 +38,9 @@ class User extends SnowFlake{ constructor(userjson: userjson, owner: Localuser, dontclone = false){ super(userjson.id); this.owner = owner; + if(localStorage.getItem("logbad")&&owner.user&&owner.user.id!==userjson.id){ + this.checkfortmi(userjson) + } if(!owner){ console.error("missing localuser"); } @@ -57,7 +60,22 @@ class User extends SnowFlake{ return User.checkuser(userjson, owner); } } - + /** + * function is meant to check if userjson contains too much information IE non-public stuff + * + * + */ + checkfortmi(json:any){ + if(json.data){ + console.error("Server sent *way* too much info, this is really bad, it sent data") + } + const bad=new Set(["fingerprints", "extended_settings", "mfa_enabled", "nsfw_allowed", "premium_usage_flags", "totp_last_ticket", "totp_secret", "webauthn_enabled"]); + for(const thing of bad){ + if(json.hasOwnProperty(thing)){ + console.error(thing+" should not be exposed to the client"); + } + } + } tojson():userjson{ return { username: this.username,