Per-Channel Emotes Implemented.
This commit is contained in:
parent
163cecf9f0
commit
c3d016e1af
14 changed files with 483 additions and 20 deletions
|
|
@ -155,8 +155,7 @@ p.panel-head-element{
|
|||
}
|
||||
|
||||
.chat-entry-username{
|
||||
margin: 0.2em;
|
||||
margin-left: 0;
|
||||
margin: auto 0.2em auto 0;
|
||||
}
|
||||
|
||||
.chat-entry-body{
|
||||
|
|
@ -169,8 +168,7 @@ p.panel-head-element{
|
|||
}
|
||||
|
||||
.chat-entry-high-level{
|
||||
margin: 0.2em;
|
||||
margin-right: 0;
|
||||
margin: auto 0 auto 0.2em;
|
||||
}
|
||||
|
||||
.high-level{
|
||||
|
|
|
|||
|
|
@ -539,8 +539,6 @@ class adminEmoteList{
|
|||
//Strip name from element id
|
||||
const name = event.target.id.replace('emote-list-delete-','');
|
||||
|
||||
console.log(name);
|
||||
|
||||
//Delete emote and pull list
|
||||
const list = await adminUtil.deleteEmote(name);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class commandPreprocessor{
|
|||
defineListeners(){
|
||||
//When we receive site-wide emote list
|
||||
this.client.socket.on("siteEmotes", this.setSiteEmotes.bind(this));
|
||||
this.client.socket.on("chanEmotes", this.setChanEmotes.bind(this));
|
||||
}
|
||||
|
||||
preprocess(command){
|
||||
|
|
@ -53,23 +54,30 @@ class commandPreprocessor{
|
|||
}
|
||||
|
||||
processEmotes(){
|
||||
//Does checking each word for an emote use more or less cycles than running replace against each emote?
|
||||
//Not sure, but it's sure as fuck easier to write it that way lmao
|
||||
this.emotes.site.forEach((emote) => {
|
||||
this.message = this.message.replaceAll(`[${emote.name}]`, emote.link);
|
||||
});
|
||||
//inject invisible whitespace in-between emotes to prevent from mushing links together
|
||||
this.message = this.message.replaceAll('][',']ㅤ[');
|
||||
|
||||
//For each list of emotes
|
||||
Object.keys(this.emotes).forEach((key) => {
|
||||
//For each emote in the current list
|
||||
this.emotes[key].forEach((emote) => {
|
||||
//Inject emote links into the message
|
||||
this.message = this.message.replaceAll(`[${emote.name}]`, emote.link);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
processLinks(){
|
||||
//Strip out file seperators in-case the user is being a smart-ass
|
||||
this.message = this.message.replaceAll('␜','');
|
||||
//Split message by links
|
||||
var splitMessage = this.message.split(/(https?:\/\/[^\s]+)/g);
|
||||
var splitMessage = this.message.split(/(https?:\/\/[^\sㅤ]+)/g);
|
||||
//Create an empty array to hold links
|
||||
this.links = [];
|
||||
|
||||
splitMessage.forEach((chunk, chunkIndex) => {
|
||||
if(chunk.match(/(https?:\/\/[^\s]+)/g)){
|
||||
//For each chunk that is a link
|
||||
if(chunk.match(/(https?:\/\/[^\sㅤ]+)/g)){
|
||||
//I looked online for obscure characters that no one would use to prevent people from chatting embed placeholders
|
||||
//Then I found this fucker, turns out it's literally made for the job lmao (even if it was originally intended for paper/magnetic tape)
|
||||
//Replace link with indexed placeholder
|
||||
|
|
@ -92,6 +100,10 @@ class commandPreprocessor{
|
|||
this.emotes.site = data;
|
||||
}
|
||||
|
||||
setChanEmotes(data){
|
||||
this.emotes.chan = data;
|
||||
}
|
||||
|
||||
getEmoteByLink(link){
|
||||
//Create an empty variable to hold the found emote
|
||||
var foundEmote = null;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class channelSettingsPage{
|
|||
this.permList = new permList(this.channel);
|
||||
this.prefrenceList = new prefrenceList(this.channel);
|
||||
this.tokeCommandList = new tokeCommandList(this.channel);
|
||||
this.emoteList = new emoteList(this.channel);
|
||||
this.deleteBtn = new deleteBtn(this.channel);
|
||||
}
|
||||
}
|
||||
|
|
@ -413,6 +414,124 @@ class tokeCommandList{
|
|||
}
|
||||
}
|
||||
|
||||
class emoteList{
|
||||
constructor(channel){
|
||||
this.channel = channel
|
||||
this.linkPrompt = document.querySelector('#new-emote-link-input');
|
||||
this.namePrompt = document.querySelector('#new-emote-name-input');
|
||||
this.addButton = document.querySelector('#new-emote-button');
|
||||
this.emoteList = document.querySelector('#emote-list');
|
||||
|
||||
//Setup input
|
||||
this.setupInput();
|
||||
|
||||
//Pull and render emote list
|
||||
this.updateList();
|
||||
}
|
||||
|
||||
setupInput(){
|
||||
this.addButton.addEventListener('click', this.addEmote.bind(this));
|
||||
}
|
||||
|
||||
async deleteEmote(event){
|
||||
//Strip name from element id
|
||||
const name = event.target.id.replace('emote-list-delete-','');
|
||||
|
||||
//Delete emote and pull list
|
||||
const list = await utils.ajax.deleteChanEmote(this.channel, name);
|
||||
|
||||
//If we received a list
|
||||
if(list != null){
|
||||
//Pass updated liste to renderEmoteList function instead of pulling it twice
|
||||
this.renderEmoteList(list);
|
||||
}
|
||||
}
|
||||
|
||||
async addEmote(event){
|
||||
//Add emote to list and ingest returned updates list
|
||||
const list = await utils.ajax.addChanEmote(this.channel, this.namePrompt.value, this.linkPrompt.value);
|
||||
|
||||
//If we received a list
|
||||
if(list != null){
|
||||
//Pass updated liste to renderEmoteList function instead of pulling it twice
|
||||
this.renderEmoteList(list);
|
||||
|
||||
//Clear out the prompts
|
||||
this.namePrompt.value = '';
|
||||
this.linkPrompt.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
async updateList(){
|
||||
const list = await utils.ajax.getChanEmotes(this.channel);
|
||||
this.renderEmoteList(list);
|
||||
}
|
||||
|
||||
renderEmoteList(list){
|
||||
//Clear the current list
|
||||
this.emoteList.innerHTML = "";
|
||||
|
||||
//For each emote in the list
|
||||
list.forEach((emote) => {
|
||||
//Create span to hold emote
|
||||
const emoteDiv = document.createElement('div');
|
||||
emoteDiv.classList.add('emote-list-emote');
|
||||
|
||||
//If the emote is an image
|
||||
if(emote.type == 'image'){
|
||||
//Create image node
|
||||
var emoteMedia = document.createElement('img');
|
||||
//if emote is a video
|
||||
}else if(emote.type == 'video'){
|
||||
//create video node
|
||||
var emoteMedia = document.createElement('video');
|
||||
//Set video properties
|
||||
emoteMedia.autoplay = true;
|
||||
emoteMedia.muted = true;
|
||||
emoteMedia.controls = false;
|
||||
emoteMedia.loop = true;
|
||||
}
|
||||
|
||||
//set media link as source
|
||||
emoteMedia.src = emote.link;
|
||||
//Set media class
|
||||
emoteMedia.classList.add('emote-list-media');
|
||||
|
||||
//Create title span
|
||||
const titleSpan = document.createElement('span');
|
||||
titleSpan.classList.add('emote-list-title');
|
||||
|
||||
//Create paragraph tag
|
||||
const emoteTitle = document.createElement('p');
|
||||
//Set title class
|
||||
emoteTitle.classList.add('emote-list-title');
|
||||
//Set emote title
|
||||
emoteTitle.innerHTML = `[${emote.name}]`;
|
||||
|
||||
//Create delete icon
|
||||
const deleteIcon = document.createElement('i');
|
||||
//Set delete icon id and class
|
||||
deleteIcon.classList.add('bi-trash-fill', 'emote-list-delete');
|
||||
deleteIcon.id = `emote-list-delete-${emote.name}`;
|
||||
//Add delete icon event listener
|
||||
deleteIcon.addEventListener('click',this.deleteEmote.bind(this));
|
||||
|
||||
|
||||
//Add the emote media to the emote span
|
||||
emoteDiv.appendChild(emoteMedia);
|
||||
//Add title paragraph node
|
||||
titleSpan.appendChild(emoteTitle);
|
||||
//Add trash icon node
|
||||
titleSpan.appendChild(deleteIcon);
|
||||
//Add title span
|
||||
emoteDiv.appendChild(titleSpan);
|
||||
|
||||
//Append the mote span to the emote list
|
||||
this.emoteList.appendChild(emoteDiv);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class deleteBtn{
|
||||
constructor(channel){
|
||||
this.channel = channel;
|
||||
|
|
@ -444,12 +563,11 @@ class deleteAccountPopup{
|
|||
}
|
||||
|
||||
setupInput(){
|
||||
this.prompt.addEventListener("keydown", this.nukeAccount.bind(this));
|
||||
this.prompt.addEventListener("keydown", this.nukeChannel.bind(this));
|
||||
}
|
||||
|
||||
async nukeAccount(event){
|
||||
async nukeChannel(event){
|
||||
if(event.key == "Enter"){
|
||||
console.log(this.channel);
|
||||
if(this.channel === event.target.value){
|
||||
await utils.ajax.deleteChannel(this.channel, event.target.value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -561,6 +561,54 @@ class canopyAjaxUtils{
|
|||
utils.ux.displayResponseError(await response.json());
|
||||
}
|
||||
}
|
||||
|
||||
async getChanEmotes(chanName){
|
||||
var response = await fetch(`/api/channel/emote?chanName=${chanName}`,{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
|
||||
if(response.status == 200){
|
||||
return await response.json();
|
||||
}else{
|
||||
utils.ux.displayResponseError(await response.json());
|
||||
}
|
||||
}
|
||||
|
||||
async addChanEmote(chanName, emoteName, link){
|
||||
var response = await fetch('/api/channel/emote',{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({chanName, emoteName, link})
|
||||
});
|
||||
|
||||
if(response.status == 200){
|
||||
return await response.json();
|
||||
}else{
|
||||
utils.ux.displayResponseError(await response.json());
|
||||
}
|
||||
}
|
||||
|
||||
async deleteChanEmote(chanName, emoteName){
|
||||
var response = await fetch('/api/channel/emote',{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({chanName, emoteName})
|
||||
});
|
||||
|
||||
if(response.status == 200){
|
||||
return await response.json();
|
||||
}else{
|
||||
utils.ux.displayResponseError(await response.json());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const utils = new canopyUtils()
|
||||
Loading…
Add table
Add a link
Reference in a new issue