From eddb92abe8a6fe2a7d4cd1ad820066a6d681ef4c Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Fri, 13 Dec 2024 15:08:49 -0600 Subject: [PATCH] adding emoji support --- src/webpage/guild.ts | 75 ++++++++++++++++++++++++++++++++++++++-- src/webpage/jsontypes.ts | 25 ++++++++++++-- src/webpage/localuser.ts | 9 ++++- src/webpage/message.ts | 2 +- src/webpage/style.css | 26 ++++++++++++++ 5 files changed, 130 insertions(+), 7 deletions(-) diff --git a/src/webpage/guild.ts b/src/webpage/guild.ts index ae9f861..c217cb7 100644 --- a/src/webpage/guild.ts +++ b/src/webpage/guild.ts @@ -6,9 +6,10 @@ import{ Member }from"./member.js"; import{ Dialog, Options, Settings }from"./settings.js"; import{ Permissions }from"./permissions.js"; import{ SnowFlake }from"./snowflake.js"; -import{channeljson,guildjson,emojijson,memberjson,invitejson,rolesjson,}from"./jsontypes.js"; +import{channeljson,guildjson,emojijson,memberjson,invitejson,rolesjson, emojipjson,}from"./jsontypes.js"; import{ User }from"./user.js"; import { I18n } from "./i18n.js"; +import { Emoji } from "./emoji.js"; class Guild extends SnowFlake{ owner!: Localuser; @@ -26,7 +27,7 @@ class Guild extends SnowFlake{ parent_id!: string; member!: Member; html!: HTMLElement; - emojis!: emojijson[]; + emojis!: emojipjson[]; large!: boolean; members=new Set(); static contextmenu = new Contextmenu("guild menu"); @@ -178,6 +179,75 @@ class Guild extends SnowFlake{ s1.options.push( new RoleList(permlist, this, this.updateRolePermissions.bind(this),false) ); + { + const emoji=settings.addButton("Emojis"); + emoji.addButtonInput("","Upload Emoji",()=>{ + const popup=new Dialog("Upload emoji"); + const form=popup.options.addForm("",()=>{ + popup.hide(); + },{ + fetchURL:`${this.info.api}/guilds/${this.id}/emojis`, + method:"POST", + headers:this.headers + }); + form.addFileInput("Image:","image",{required:true}); + form.addTextInput("Name:","name",{required:true}); + popup.show(); + }); + const containdiv=document.createElement("div"); + const genDiv=()=>{ + containdiv.innerHTML=""; + for(const emoji of this.emojis){ + const div=document.createElement("div"); + div.classList.add("flexltr","emojiOption"); + const emojic=new Emoji(emoji,this); + + const text=document.createElement("input"); + text.type="text"; + text.value=emoji.name; + text.addEventListener("change",()=>{ + fetch(`${this.info.api}/guilds/${this.id}/emojis/${emoji.id}`,{ + method:"PATCH", + headers:this.headers, + body:JSON.stringify({name:text.value}) + }).then(e=>{if(!e.ok)text.value=emoji.name;})//if not ok, undo + }); + + const del=document.createElement("span"); + del.classList.add("svgicon", "svg-x","deleteEmoji"); + del.onclick=()=>{ + const diaolog=new Dialog(""); + diaolog.options.addTitle("Are you sure you want to delete this emoji?"); + const options=diaolog.options.addOptions("",{ltr:true}); + options.addButtonInput("",I18n.getTranslation("yes"),()=>{ + fetch(`${this.info.api}/guilds/${this.id}/emojis/${emoji.id}`,{ + method:"DELETE", + headers:this.headers + }) + diaolog.hide(); + }); + options.addButtonInput("",I18n.getTranslation("no"),()=>{ + diaolog.hide(); + }) + diaolog.show(); + } + + + div.append(emojic.getHTML(true),":",text,":",del); + + containdiv.append(div); + } + } + this.onEmojiUpdate=()=>{ + if(!document.body.contains(containdiv)){ + this.onEmojiUpdate=()=>{}; + return; + } + genDiv(); + } + genDiv(); + emoji.addHTMLArea(containdiv); + } settings.show(); } makeInviteMenu(options:Options,valid:void|(Channel[])){ @@ -303,6 +373,7 @@ class Guild extends SnowFlake{ this.roles.splice(this.roles.indexOf(role),1); this.roleUpdate(role,-1); } + onEmojiUpdate=(_:emojipjson[])=>{}; constructor( json: guildjson | -1, owner: Localuser, diff --git a/src/webpage/jsontypes.ts b/src/webpage/jsontypes.ts index 45e10d8..57b39d3 100644 --- a/src/webpage/jsontypes.ts +++ b/src/webpage/jsontypes.ts @@ -168,14 +168,24 @@ type emojijson = { name: string; id?: string; animated?: boolean; - emoji?:string + emoji?:string; }; +type emojipjson=emojijson&{ + available: boolean, + guild_id:string, + user_id:string, + managed:boolean, + require_colons:boolean, + roles:string[], + groups:null//TODO figure out what this means lol +}; + type guildjson = { application_command_counts: { [key: string]: number }; channels: channeljson[]; data_mode: string; - emojis: emojijson[]; + emojis: emojipjson[]; guild_scheduled_events: []; id: string; large: boolean; @@ -543,6 +553,14 @@ roleCreate | { user:userjson }, s:number +}|{ + op: 0, + t: "GUILD_EMOJIS_UPDATE", + d: { + guild_id: string, + emojis: emojipjson[] + }, + s: number }; @@ -706,5 +724,6 @@ export{ voiceserverupdate, webRTCSocket, sdpback, - opRTC12 + opRTC12, + emojipjson }; diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index a59fd06..43d5288 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -5,7 +5,7 @@ import{ AVoice }from"./audio/voice.js"; import{ User }from"./user.js"; import{ getapiurls, SW }from"./utils/utils.js"; import { getBulkInfo, setTheme, Specialuser } from "./utils/utils.js"; -import{channeljson,guildjson,mainuserjson,memberjson,memberlistupdatejson,messageCreateJson,presencejson,readyjson,startTypingjson,wsjson,}from"./jsontypes.js"; +import{channeljson,emojipjson,guildjson,mainuserjson,memberjson,memberlistupdatejson,messageCreateJson,presencejson,readyjson,startTypingjson,wsjson,}from"./jsontypes.js"; import{ Member }from"./member.js"; import{ Dialog, Form, FormError, Options, Settings }from"./settings.js"; import{ getTextNodeAtPosition, MarkDown }from"./markdown.js"; @@ -589,6 +589,13 @@ class Localuser{ member.remove(); break; } + case "GUILD_EMOJIS_UPDATE":{ + const guild=this.guildids.get(temp.d.guild_id); + if(!guild) break; + guild.emojis=temp.d.emojis; + guild.onEmojiUpdate(guild.emojis); + break; + } default :{ //@ts-ignore console.warn("Unhandled case "+temp.t,temp); diff --git a/src/webpage/message.ts b/src/webpage/message.ts index 540ef40..a65dd2d 100644 --- a/src/webpage/message.ts +++ b/src/webpage/message.ts @@ -468,7 +468,7 @@ class Message extends SnowFlake{ div.appendChild(replyline); } div.appendChild(build); - const messageTypes=new Set([0,19]) + const messageTypes=new Set([0,19]); if(messageTypes.has(this.type) || this.attachments.length !== 0){ const pfpRow = document.createElement("div"); let pfpparent, current; diff --git a/src/webpage/style.css b/src/webpage/style.css index 96f3b0a..3edfb67 100644 --- a/src/webpage/style.css +++ b/src/webpage/style.css @@ -2175,6 +2175,8 @@ fieldset input[type="radio"] { } .bigemoji{ width:.6in; + object-fit: contain; + height: .6in; } .friendlyButton{ padding: .07in; @@ -2189,3 +2191,27 @@ fieldset input[type="radio"] { .friendlyButton:hover{ background:black; } +.emojiOption{ + border: solid 1px var(--black); + display:flex; + align-items: center; + padding: .075in; + margin-bottom: .2in; + border-radius: .1in; + background: var(--primary-hover); + position: relative; + input{ + width:2in !important; + height:.3in; + } + .bigemoji{ + padding-right:.5in; + } +} +.deleteEmoji{ + width: .3in; + height: .3in; + position: absolute; + right: .2in; + cursor: pointer; +}