From 2502d8f977889333fc786de58132321506c95f64 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Tue, 26 Nov 2024 22:30:04 -0600 Subject: [PATCH] friend and more update --- gulpfile.cjs | 1 + src/webpage/channel.ts | 10 +- src/webpage/direct.ts | 244 ++++++++++++++++++++++++++++++-- src/webpage/guild.ts | 4 +- src/webpage/icons/addfriend.svg | 1 + src/webpage/icons/frmessage.svg | 1 + src/webpage/index.html | 2 +- src/webpage/jsontypes.ts | 20 ++- src/webpage/localuser.ts | 20 +++ src/webpage/settings.ts | 92 ++++++++++-- src/webpage/style.css | 70 ++++++++- src/webpage/user.ts | 82 ++++++----- translations/en.json | 23 ++- 13 files changed, 491 insertions(+), 79 deletions(-) create mode 100644 src/webpage/icons/addfriend.svg create mode 100644 src/webpage/icons/frmessage.svg diff --git a/gulpfile.cjs b/gulpfile.cjs index fd43e3a..f317e6f 100644 --- a/gulpfile.cjs +++ b/gulpfile.cjs @@ -40,6 +40,7 @@ jsc: { gulp.task('watch', function () { gulp.watch('./src', gulp.series("default")); + gulp.watch('./translations', gulp.series("default")); }, {debounceDelay: 10}); // Clean task to delete the dist directory diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index 9e88783..01dab52 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -842,6 +842,10 @@ class Channel extends SnowFlake{ if(this.voice&&localStorage.getItem("Voice enabled")){ this.localuser.joinVoice(this); } + (document.getElementById("typebox") as HTMLDivElement).contentEditable =""+this.canMessage; + (document.getElementById("upload") as HTMLElement).style.visibility=this.canMessage?"visible":"hidden"; + (document.getElementById("typediv") as HTMLElement).style.visibility="visible"; + (document.getElementById("typebox") as HTMLDivElement).focus(); await this.putmessages(); await prom; if(id !== Channel.genid){ @@ -851,10 +855,7 @@ class Channel extends SnowFlake{ await this.buildmessages(); //loading.classList.remove("loading"); - (document.getElementById("typebox") as HTMLDivElement).contentEditable =""+this.canMessage; - (document.getElementById("upload") as HTMLElement).style.visibility=this.canMessage?"visible":"hidden"; - (document.getElementById("typediv") as HTMLElement).style.visibility="visible"; - (document.getElementById("typebox") as HTMLDivElement).focus(); + } typingmap: Map = new Map(); async typingStart(typing: startTypingjson): Promise{ @@ -938,6 +939,7 @@ class Channel extends SnowFlake{ } lastmessage: Message | undefined; async putmessages(){ + //TODO swap out with the WS op code if(this.allthewayup){ return; } diff --git a/src/webpage/direct.ts b/src/webpage/direct.ts index 8e99394..d3c0324 100644 --- a/src/webpage/direct.ts +++ b/src/webpage/direct.ts @@ -8,9 +8,11 @@ import{ Permissions }from"./permissions.js"; import{ SnowFlake }from"./snowflake.js"; import{ Contextmenu }from"./contextmenu.js"; import { I18n } from "./i18n.js"; +import { Float, FormError } from "./settings.js"; class Direct extends Guild{ declare channelids: { [key: string]: Group }; + channels: Group[]; getUnixTime(): number{ throw new Error("Do not call this for Direct, it does not make sense"); } @@ -26,7 +28,7 @@ class Direct extends Guild{ this.roles = []; this.roleids = new Map(); this.prevchannel = undefined; - this.properties.name = "Direct Messages"; + this.properties.name = I18n.getTranslation("DMs.name"); for(const thing of json){ const temp = new Group(thing, this); this.channels.push(temp); @@ -60,7 +62,7 @@ class Direct extends Guild{ icon.classList.add("svgicon","svg-friends","space"); freindDiv.append(icon); - freindDiv.append("Friends"); + freindDiv.append(I18n.getTranslation("friends.friends")); ddiv.append(freindDiv); freindDiv.onclick=()=>{ this.loadChannel(null); @@ -69,6 +71,217 @@ class Direct extends Guild{ ddiv.append(build); return ddiv; } + noChannel(addstate:boolean){ + if(addstate){ + history.pushState([this.id,undefined], "", "/channels/" + this.id); + } + this.localuser.pageTitle(I18n.getTranslation("friends.friendlist")); + const channelTopic = document.getElementById("channelTopic") as HTMLSpanElement; + channelTopic.removeAttribute("hidden"); + channelTopic.textContent=""; + + const loading = document.getElementById("loadingdiv") as HTMLDivElement; + loading.classList.remove("loading"); + this.localuser.getSidePannel(); + + const messages = document.getElementById("channelw") as HTMLDivElement; + for(const thing of Array.from(messages.getElementsByClassName("messagecontainer"))){ + thing.remove(); + } + const container=document.createElement("div"); + container.classList.add("messagecontainer","flexttb","friendcontainer") + + messages.append(container); + const checkVoid=()=>{ + if(this.localuser.channelfocus!==undefined||this.localuser.lookingguild!==this){ + this.localuser.relationshipsUpdate=()=>{}; + } + } + function genuserstrip(user:User,icons:HTMLElement):HTMLElement{ + const div=document.createElement("div"); + div.classList.add("flexltr","liststyle"); + user.bind(div); + div.append(user.buildpfp()); + + const userinfos=document.createElement("div"); + userinfos.classList.add("flexttb"); + const username=document.createElement("span"); + username.textContent=user.name; + userinfos.append(username,user.getStatus()); + div.append(userinfos); + User.contextmenu.bindContextmenu(div,user,undefined); + userinfos.style.flexGrow="1"; + + div.append(icons); + return div; + } + { + //TODO update on users coming online + const online=document.createElement("button"); + online.textContent=I18n.getTranslation("friends.online"); + channelTopic.append(online); + const genOnline=()=>{ + this.localuser.relationshipsUpdate=genOnline; + checkVoid(); + container.innerHTML=""; + container.append(I18n.getTranslation("friends.online:")); + for(const user of this.localuser.inrelation){ + if(user.relationshipType===1&&user.online){ + const buttonc=document.createElement("div"); + const button1=document.createElement("span"); + button1.classList.add("svg-frmessage","svgicon"); + buttonc.append(button1); + buttonc.classList.add("friendlyButton"); + buttonc.onclick=(e)=>{ + e.stopImmediatePropagation(); + user.opendm(); + } + container.append(genuserstrip(user,buttonc)); + } + } + } + online.onclick=genOnline; + genOnline(); + } + { + const all=document.createElement("button"); + all.textContent=I18n.getTranslation("friends.all"); + const genAll=()=>{ + this.localuser.relationshipsUpdate=genAll; + checkVoid(); + container.innerHTML=""; + container.append(I18n.getTranslation("friends.all:")); + for(const user of this.localuser.inrelation){ + if(user.relationshipType===1){ + const buttonc=document.createElement("div"); + const button1=document.createElement("span"); + button1.classList.add("svg-frmessage","svgicon"); + buttonc.append(button1); + buttonc.classList.add("friendlyButton"); + buttonc.onclick=(e)=>{ + e.stopImmediatePropagation(); + user.opendm(); + } + container.append(genuserstrip(user,buttonc)); + } + } + } + all.onclick=genAll; + channelTopic.append(all); + } + { + const pending=document.createElement("button"); + pending.textContent=I18n.getTranslation("friends.pending"); + const genPending=()=>{ + this.localuser.relationshipsUpdate=genPending; + checkVoid(); + container.innerHTML=""; + container.append(I18n.getTranslation("friends.pending:")); + for(const user of this.localuser.inrelation){ + if(user.relationshipType===3||user.relationshipType===4){ + const buttons=document.createElement("div"); + buttons.classList.add("flexltr"); + const buttonc=document.createElement("div"); + const button1=document.createElement("span"); + button1.classList.add("svgicon","svg-x"); + if(user.relationshipType===3){ + const buttonc=document.createElement("div"); + const button2=document.createElement("span"); + button2.classList.add("svgicon","svg-x"); + button2.classList.add("svg-addfriend"); + buttonc.append(button2); + buttonc.classList.add("friendlyButton"); + buttonc.append(button2); + buttons.append(buttonc); + buttonc.onclick=(e)=>{ + e.stopImmediatePropagation(); + user.changeRelationship(1); + outerDiv.remove(); + } + } + buttonc.append(button1); + buttonc.classList.add("friendlyButton"); + buttonc.onclick=(e)=>{ + e.stopImmediatePropagation(); + user.changeRelationship(0); + outerDiv.remove(); + } + buttons.append(buttonc); + const outerDiv=genuserstrip(user,buttons); + container.append(outerDiv); + } + } + } + pending.onclick=genPending; + channelTopic.append(pending); + } + { + const blocked=document.createElement("button"); + blocked.textContent=I18n.getTranslation("friends.blocked"); + + const genBlocked=()=>{ + this.localuser.relationshipsUpdate=genBlocked; + checkVoid(); + container.innerHTML=""; + container.append(I18n.getTranslation("friends.blockedusers")); + for(const user of this.localuser.inrelation){ + if(user.relationshipType===2){ + const buttonc=document.createElement("div"); + const button1=document.createElement("span"); + button1.classList.add("svg-x","svgicon"); + buttonc.append(button1); + buttonc.classList.add("friendlyButton"); + buttonc.onclick=(e)=>{ + user.changeRelationship(0); + e.stopImmediatePropagation(); + outerDiv.remove(); + } + const outerDiv=genuserstrip(user,buttonc); + container.append(outerDiv); + } + } + } + blocked.onclick=genBlocked; + channelTopic.append(blocked); + } + { + const add=document.createElement("button"); + add.textContent=I18n.getTranslation("friends.addfriend"); + add.onclick=()=>{ + this.localuser.relationshipsUpdate=()=>{}; + container.innerHTML=""; + const float=new Float(""); + const options=float.options; + const form=options.addForm("",(e:any)=>{ + console.log(e); + if(e.code===404){ + throw new FormError(text,I18n.getTranslation("friends.notfound")); + }else if(e.code===400){ + throw new FormError(text,e.message.split("Error: ")[1]); + }else{ + const box=text.input.deref(); + if(!box)return; + box.value=""; + } + },{ + method:"POST", + fetchURL:this.info.api+"/users/@me/relationships", + headers:this.headers + }); + const text=form.addTextInput(I18n.getTranslation("friends.addfriendpromt"),"username"); + form.addPreprocessor((obj:any)=>{ + const [username,discriminator]=obj.username.split("#"); + obj.username=username; + obj.discriminator=discriminator; + if(!discriminator){ + throw new FormError(text,I18n.getTranslation("friends.discnotfound")); + } + }); + container.append(float.generateHTML()); + } + channelTopic.append(add); + } + } giveMember(_member: memberjson){ console.error("not a real guild, can't give member object"); } @@ -143,15 +356,15 @@ class Group extends Channel{ this.user = this.localuser.user; } this.name ??= this.localuser.user.username; - this.parent_id!; - this.parent!; - this.children = []; - this.guild_id = "@me"; - this.permission_overwrites = new Map(); - this.lastmessageid = json.last_message_id; - this.mentions = 0; - this.setUpInfiniteScroller(); - this.updatePosition(); + this.parent_id!; + this.parent!; + this.children = []; + this.guild_id = "@me"; + this.permission_overwrites = new Map(); + this.lastmessageid = json.last_message_id; + this.mentions = 0; + this.setUpInfiniteScroller(); + this.updatePosition(); } updatePosition(){ if(this.lastmessageid){ @@ -202,6 +415,10 @@ class Group extends Channel{ loading.classList.add("loading"); this.rendertyping(); + (document.getElementById("typebox") as HTMLDivElement).contentEditable ="" + true; + (document.getElementById("upload") as HTMLElement).style.visibility="visible"; + (document.getElementById("typediv") as HTMLElement).style.visibility="visible"; + (document.getElementById("typebox") as HTMLDivElement).focus(); await this.putmessages(); await prom; this.localuser.getSidePannel(); @@ -209,10 +426,7 @@ class Group extends Channel{ return; } this.buildmessages(); - (document.getElementById("typebox") as HTMLDivElement).contentEditable ="" + true; - (document.getElementById("upload") as HTMLElement).style.visibility="visible"; - (document.getElementById("typediv") as HTMLElement).style.visibility="visible"; - (document.getElementById("typebox") as HTMLDivElement).focus(); + } messageCreate(messagep: { d: messagejson }){ const messagez = new Message(messagep.d, this); diff --git a/src/webpage/guild.ts b/src/webpage/guild.ts index a729a2c..79e7b7d 100644 --- a/src/webpage/guild.ts +++ b/src/webpage/guild.ts @@ -626,7 +626,7 @@ class Guild extends SnowFlake{ if(addstate){ history.pushState([this.id,undefined], "", "/channels/" + this.id); } - this.localuser.pageTitle("Weird spot"); + this.localuser.pageTitle(I18n.getTranslation("guild.emptytitle")); const channelTopic = document.getElementById("channelTopic") as HTMLSpanElement; channelTopic.setAttribute("hidden", ""); @@ -640,7 +640,7 @@ class Guild extends SnowFlake{ } const h1=document.createElement("h1"); h1.classList.add("messagecontainer") - h1.textContent="You're in a weird spot, this guild has no channels"; + h1.textContent=I18n.getTranslation("guild.emptytext"); messages.append(h1); } loadGuild(){ diff --git a/src/webpage/icons/addfriend.svg b/src/webpage/icons/addfriend.svg new file mode 100644 index 0000000..5f34ade --- /dev/null +++ b/src/webpage/icons/addfriend.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/webpage/icons/frmessage.svg b/src/webpage/icons/frmessage.svg new file mode 100644 index 0000000..efcc42d --- /dev/null +++ b/src/webpage/icons/frmessage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/webpage/index.html b/src/webpage/index.html index b1933ce..13f6276 100644 --- a/src/webpage/index.html +++ b/src/webpage/index.html @@ -59,7 +59,7 @@ - + Channel name diff --git a/src/webpage/jsontypes.ts b/src/webpage/jsontypes.ts index d9a2d2c..ae6134a 100644 --- a/src/webpage/jsontypes.ts +++ b/src/webpage/jsontypes.ts @@ -505,7 +505,25 @@ roleCreate | { op:9, d:boolean, s:number -}|memberlistupdatejson|voiceupdate|voiceserverupdate; +}|memberlistupdatejson|voiceupdate|voiceserverupdate|{ + op: 0, + t: "RELATIONSHIP_ADD", + d: { + id: string, + type: 0|1|2|3|4|5|6, + user: userjson + }, + s: number +}|{ + op: 0, + t: "RELATIONSHIP_REMOVE", + d: { + id: string, + type: number, + nickname: null + }, + s: number +}; type memberChunk = { diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index 0422d50..24c73d0 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -124,12 +124,14 @@ class Localuser{ const user = new User(thing.user, this); user.nickname = thing.nickname; user.relationshipType = thing.type; + this.inrelation.add(user); } this.pingEndpoint(); this.userinfo.updateLocal(); } + inrelation=new Set(); outoffocus(): void{ const servers = document.getElementById("servers") as HTMLDivElement; servers.innerHTML = ""; @@ -365,6 +367,7 @@ class Localuser{ }); await promise; } + relationshipsUpdate=()=>{}; async handleEvent(temp: wsjson){ console.debug(temp); if(temp.s)this.lastSequence = temp.s; @@ -539,6 +542,23 @@ class Localuser{ guild.memberupdate(temp.d) break } + case "RELATIONSHIP_ADD":{ + const user = new User(temp.d.user, this); + user.nickname = null; + user.relationshipType = temp.d.type; + this.inrelation.add(user); + this.relationshipsUpdate(); + break; + } + case "RELATIONSHIP_REMOVE":{ + const user = this.userMap.get(temp.d.id); + if(!user) return; + user.nickname = null; + user.relationshipType = 0; + this.inrelation.delete(user); + this.relationshipsUpdate(); + break; + } default :{ //@ts-ignore console.warn("Unhandled case "+temp.t,temp); diff --git a/src/webpage/settings.ts b/src/webpage/settings.ts index 9c21cf2..a4bae0c 100644 --- a/src/webpage/settings.ts +++ b/src/webpage/settings.ts @@ -516,11 +516,27 @@ class HtmlArea implements OptionsElement{ } watchForChange(){} } +/** +* This is a simple wrapper class for Options to make it happy so it can be used outside of Settings. +*/ +class Float{ + options:Options; + /** + * This is a simple wrapper class for Options to make it happy so it can be used outside of Settings. + */ + constructor(name:string, options={ ltr:false, noSubmit:false}){ + this.options=new Options(name,this,options) + } + changed=()=>{}; + generateHTML(){ + return this.options.generateHTML(); + } +} class Options implements OptionsElement{ name: string; haschanged = false; readonly options: OptionsElement[]; - readonly owner: Buttons | Options | Form; + readonly owner: Buttons | Options | Form | Float; readonly ltr: boolean; value!: void; readonly html: WeakMap, WeakRef> = new WeakMap(); @@ -530,7 +546,7 @@ class Options implements OptionsElement{ ); constructor( name: string, - owner: Buttons | Options | Form, + owner: Buttons | Options | Form | Float, { ltr = false, noSubmit=false} = {} ){ this.name = name; @@ -1145,38 +1161,84 @@ class Form implements OptionsElement{ } console.log("middle2"); await Promise.allSettled(promises); - this.preprocessor(build); + try{ + this.preprocessor(build); + }catch(e){ + if(e instanceof FormError){ + const elm = this.options.html.get(e.elem); + if(elm){ + const html = elm.deref(); + if(html){ + this.makeError(html, e.message); + } + } + } + return; + } if(this.fetchURL !== ""){ fetch(this.fetchURL, { method: this.method, body: JSON.stringify(build), headers: this.headers, }) - .then(_=>_.json()) + .then(_=>{ + return _.text() + }).then(_=>{ + if(_==="") return {}; + return JSON.parse(_) + }) .then(json=>{ - if(json.errors && this.errors(json.errors))return; - this.onSubmit(json); + if(json.errors){ + if(this.errors(json)){ + return; + } + } + try{ + this.onSubmit(json); + }catch(e){ + console.error(e); + if(e instanceof FormError){ + const elm = this.options.html.get(e.elem); + if(elm){ + const html = elm.deref(); + if(html){ + this.makeError(html, e.message); + } + } + } + return; + } }); }else{ - this.onSubmit(build); + try{ + this.onSubmit(build); + }catch(e){ + if(e instanceof FormError){ + const elm = this.options.html.get(e.elem); + if(elm){ + const html = elm.deref(); + if(html){ + this.makeError(html, e.message); + } + } + } + return; + } } console.warn("needs to be implemented"); } - errors(errors: { - code: number; - message: string; - errors: { [key: string]: { _errors: { message: string; code: string } } }; - }){ + errors(errors: {code: number; message: string; errors: { [key: string]: { _errors: { message: string; code: string }[] } }}){ if(!(errors instanceof Object)){ return; } - for(const error of Object.keys(errors)){ + for(const error of Object.keys(errors.errors)){ const elm = this.names.get(error); if(elm){ const ref = this.options.html.get(elm); if(ref && ref.deref()){ const html = ref.deref() as HTMLDivElement; - this.makeError(html, errors.errors[error]._errors.message); + const errorMessage=errors.errors[error]._errors[0].message; + this.makeError(html, errorMessage); return true; } } @@ -1253,4 +1315,4 @@ class Settings extends Buttons{ } } -export{ Settings, OptionsElement, Buttons, Options,Form }; +export{ Settings, OptionsElement, Buttons, Options,Form,Float }; diff --git a/src/webpage/style.css b/src/webpage/style.css index fb23e4c..87cbc96 100644 --- a/src/webpage/style.css +++ b/src/webpage/style.css @@ -256,9 +256,15 @@ textarea { } .svg-friends{ mask: url(/icons/friends.svg); - width: 24px !important;!i;!; - height: 24px !important;!i;!; - margin-right: 0 !important;!i;!; + width: 24px !important; + height: 24px !important; + margin-right: 0 !important; +} +.svg-frmessage{ + mask: url(/icons/frmessage.svg); +} +.svg-addfriend{ + mask: url(/icons/addfriend.svg); } .svgicon { display: block; @@ -833,6 +839,9 @@ span.instanceStatus { margin: auto 0 0 8px; font-size: .9em; color: var(--primary-text-soft); + button{ + margin-right:.05in; + } } #channelTopic[hidden] { display: none; @@ -2045,7 +2054,18 @@ fieldset input[type="radio"] { margin: 6px 12px; } } - +.friendcontainer{ + display: flex; + width: 100%; + padding: .2in; + >div{ + background:#00000030; + margin-bottom:.1in; + padding:.06in .1in; + border-radius:.1in; + border: solid 1px var(--black); + } +} .fixedsearch{ position: absolute; background: var(--primary-bg); @@ -2064,6 +2084,35 @@ fieldset input[type="radio"] { } } +.suberror{ + animation: goout 6s forwards; +} +.suberrora{ + background:var(--channel-hover); + border-radius:.1in; + position:absolute; + border:solid var(--primary-text) .02in; + color:color-mix(in hsl,var(--yellow),var(--red)); + font-weight:bold; + opacity:0; + cursor:default; + /* height: .4in; */ + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: space-evenly; + padding: .075in; + box-sizing: border-box; + pointer-events: none; +} +@keyframes goout { + 0%,100%{ + opacity:0; + } + 5%,90%{ + opacity:1; + } +} .friendsbutton{ transition: background-color .2s; background-color: #00000050; @@ -2072,3 +2121,16 @@ fieldset input[type="radio"] { .bigemoji{ width:.6in; } +.friendlyButton{ + padding: .07in; + background: #00000045; + transition:background .2s; + border-radius: 1in; + border: solid 1px var(--black); + width: 24px; + height: 24px; + margin: 0 .05in; +} +.friendlyButton:hover{ + background:black; +} diff --git a/src/webpage/user.ts b/src/webpage/user.ts index e47b7c3..621793f 100644 --- a/src/webpage/user.ts +++ b/src/webpage/user.ts @@ -8,6 +8,7 @@ import{ presencejson, userjson }from"./jsontypes.js"; import { Role } from "./role.js"; import { Search } from "./search.js"; import { I18n } from "./i18n.js"; +import { Direct } from "./direct.js"; class User extends SnowFlake{ owner: Localuser; @@ -15,7 +16,7 @@ class User extends SnowFlake{ avatar!: string | null; username!: string; nickname: string | null = null; - relationshipType: 0 | 1 | 2 | 3 | 4 = 0; + relationshipType: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 0; bio!: MarkDown; discriminator!: string; pronouns!: string; @@ -85,31 +86,59 @@ class User extends SnowFlake{ this.setstatus("offline"); } } - + get online(){ + return (this.status)&&(this.status!="offline"); + } setstatus(status: string): void{ this.status = status; } - async getStatus(): Promise{ + getStatus(): string{ return this.status || "offline"; } static contextmenu = new Contextmenu("User Menu"); - + async opendm(){ + for(const dm of (this.localuser.guildids.get("@me") as Direct).channels){ + if(dm.user.id===this.id){ + this.localuser.goToChannel(dm.id); + return; + } + } + await fetch(this.info.api + "/users/@me/channels", { + method: "POST", + body: JSON.stringify({ recipients: [this.id] }), + headers: this.localuser.headers, + }) + .then(res=>res.json()) + .then(json=>{ + this.localuser.goToChannel(json.id); + }); + return; + } + async changeRelationship(type:0|1|2|3|4|5){ + if(type!==0){ + await fetch(`${this.info.api}/users/@me/relationships/${this.id}`, { + method: "PUT", + headers: this.owner.headers, + body: JSON.stringify({ + type, + }), + }); + }else{ + await fetch(`${this.info.api}/users/@me/relationships/${this.id}`, { + method: "DELETE", + headers: this.owner.headers + }); + } + this.relationshipType=type; + } static setUpContextMenu(): void{ this.contextmenu.addbutton(()=>I18n.getTranslation("user.copyId"), function(this: User){ navigator.clipboard.writeText(this.id); }); this.contextmenu.addbutton(()=>I18n.getTranslation("user.message"), function(this: User){ - fetch(this.info.api + "/users/@me/channels", { - method: "POST", - body: JSON.stringify({ recipients: [this.id] }), - headers: this.localuser.headers, - }) - .then(res=>res.json()) - .then(json=>{ - this.localuser.goToChannel(json.id); - }); + this.opendm(); }); this.contextmenu.addbutton( ()=>I18n.getTranslation("user.block"), @@ -133,13 +162,7 @@ class User extends SnowFlake{ } ); this.contextmenu.addbutton(()=>I18n.getTranslation("user.friendReq"), function(this: User){ - fetch(`${this.info.api}/users/@me/relationships/${this.id}`, { - method: "PUT", - headers: this.owner.headers, - body: JSON.stringify({ - type: 1, - }), - }); + this.changeRelationship(1); }); this.contextmenu.addbutton( ()=>I18n.getTranslation("user.kick"), @@ -370,15 +393,8 @@ class User extends SnowFlake{ ); } - block(): void{ - fetch(`${this.info.api}/users/@me/relationships/${this.id}`, { - method: "PUT", - headers: this.owner.headers, - body: JSON.stringify({ - type: 2, - }), - }); - this.relationshipType = 2; + async block(){ + await this.changeRelationship(2); const channel = this.localuser.channelfocus; if(channel){ for(const message of channel.messages){ @@ -387,12 +403,8 @@ class User extends SnowFlake{ } } - unblock(): void{ - fetch(`${this.info.api}/users/@me/relationships/${this.id}`, { - method: "DELETE", - headers: this.owner.headers, - }); - this.relationshipType = 0; + async unblock(){ + await this.changeRelationship(0); const channel = this.localuser.channelfocus; if(channel){ for(const message of channel.messages){ diff --git a/translations/en.json b/translations/en.json index 370939b..e27ef3f 100644 --- a/translations/en.json +++ b/translations/en.json @@ -229,7 +229,9 @@ "noDelete":"Nevermind", "create":"Create guild", "loadingDiscovery":"Loading...", - "disoveryTitle":"Guild discovery ($1) {{PLURAL:$1|entry|entries}}" + "disoveryTitle":"Guild discovery ($1) {{PLURAL:$1|entry|entries}}", + "emptytitle":"Weird spot", + "emptytext":"You're in a weird spot, this guild has no channels" }, "role":{ "displaySettings":"Display settings", @@ -345,11 +347,28 @@ "joinUsing":"Join using invite", "inviteLinkCode":"Invite Link/Code" }, + "friends":{ + "blocked":"Blocked", + "blockedusers":"Blocked Users:", + "addfriend":"Add Friend", + "addfriendpromt":"Add friends by username:", + "notfound":"User not found", + "discnotfound":"Discriminator not found", + "pending":"Pending", + "pending:":"Pending friend requests:", + "all":"All", + "all:":"All friends:", + "online":"Online", + "online:":"Online friends:", + "friendlist":"Friend List", + "friends":"Friends" + }, "replyingTo":"Replying to $1", "DMs":{ "copyId":"Copy DM id", "markRead":"Mark as read", - "close":"Close DM" + "close":"Close DM", + "name":"Dirrect Messages" }, "user":{ "copyId":"Copy user ID",