Started work on emote panel in admin page.
This commit is contained in:
parent
255e6e0d7f
commit
90d67024b7
|
|
@ -29,6 +29,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.-->
|
||||||
<%- include('partial/adminPanel/permList', {permList, rankEnum}) %>
|
<%- include('partial/adminPanel/permList', {permList, rankEnum}) %>
|
||||||
<%- include('partial/adminPanel/userBanList') %>
|
<%- include('partial/adminPanel/userBanList') %>
|
||||||
<%- include('partial/adminPanel/tokeCommandList') %>
|
<%- include('partial/adminPanel/tokeCommandList') %>
|
||||||
|
<%- include('partial/adminPanel/emoteList') %>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
<footer>
|
<footer>
|
||||||
|
|
|
||||||
28
src/views/partial/adminPanel/emoteList.ejs
Normal file
28
src/views/partial/adminPanel/emoteList.ejs
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
<!--Canopy - The next generation of stoner streaming software
|
||||||
|
Copyright (C) 2024 Rainbownapkin and the TTN Community
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.-->
|
||||||
|
<div id="emote-list-div" class="admin-list-div">
|
||||||
|
<h3>Emote List:</h3>
|
||||||
|
<div class="control-prompt">
|
||||||
|
<!-- Probably not the cleanest way to do this but fuggit -->
|
||||||
|
[<input placeholder="Emote Name..." id="new-emote-name-input" class="control-prompt">]
|
||||||
|
<button id="new-emote-button" class="positive-button">Add</button>
|
||||||
|
</div>
|
||||||
|
<div class="control-prompt">
|
||||||
|
<input placeholder="Emote Link..." id="new-emote-link-input" class="control-prompt">
|
||||||
|
</div>
|
||||||
|
<div class="dynamic-container" id="emote-list">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.-->
|
||||||
<div id="toke-command-list-div" class="admin-list-div">
|
<div id="toke-command-list-div" class="admin-list-div">
|
||||||
<h3>Toke Command List:</h3>
|
<h3>Toke Command List:</h3>
|
||||||
<div class="control-prompt">
|
<div class="control-prompt">
|
||||||
<input placeholder="Add Command..." id="new-toke-command-input" class="control-prompt">
|
!<input placeholder="Add Command..." id="new-toke-command-input" class="control-prompt">
|
||||||
<button id="new-toke-command-button" class="positive-button">Add</button>
|
<button id="new-toke-command-button" class="positive-button">Add</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="dynamic-container toke-command-list">
|
<div class="dynamic-container toke-command-list">
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.-->
|
||||||
<div id="toke-command-list-div" class="admin-list-div">
|
<div id="toke-command-list-div" class="admin-list-div">
|
||||||
<h3>Toke Command List:</h3>
|
<h3>Toke Command List:</h3>
|
||||||
<div class="control-prompt">
|
<div class="control-prompt">
|
||||||
<input placeholder="Add Command..." id="new-toke-command-input" class="control-prompt">
|
!<input placeholder="Add Command..." id="new-toke-command-input" class="control-prompt">
|
||||||
<button id="new-toke-command-button" class="positive-button">Add</button>
|
<button id="new-toke-command-button" class="positive-button">Add</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="dynamic-container toke-command-list">
|
<div class="dynamic-container toke-command-list">
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,10 @@ span.user-entry{
|
||||||
margin: 0.5em;
|
margin: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#chat-panel-prompt{
|
||||||
|
margin-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.toke{
|
.toke{
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 0.2em auto;
|
margin: 0.2em auto;
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,6 @@ i.control-prompt{
|
||||||
}
|
}
|
||||||
|
|
||||||
input.control-prompt{
|
input.control-prompt{
|
||||||
margin-left: 0.5em;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -517,8 +517,57 @@ class adminTokeCommandList{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class adminEmoteList{
|
||||||
|
constructor(){
|
||||||
|
this.linkPrompt = document.querySelector('new-emote-link-input');
|
||||||
|
this.namePrompt = document.querySelector('new-emote-link-input');
|
||||||
|
this.emoteList = document.querySelector('#emote-list');
|
||||||
|
|
||||||
|
this.updateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateList(){
|
||||||
|
const list = await adminUtil.getEmotes();
|
||||||
|
this.renderEmoteList(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEmoteList(list){
|
||||||
|
//Clear the current list
|
||||||
|
this.emoteList.innerHTML = "";
|
||||||
|
|
||||||
|
//For each emote in the list
|
||||||
|
list.forEach((emote) => {
|
||||||
|
const emoteSpan = document.createElement('span');
|
||||||
|
emoteSpan.classList.add('emote-list-emote');
|
||||||
|
|
||||||
|
//If the emote is an image
|
||||||
|
if(emote.type == 'image'){
|
||||||
|
//Create image node
|
||||||
|
var emoteMedia = document.createElement('img');
|
||||||
|
//add link as source
|
||||||
|
emoteMedia.src = emote.link;
|
||||||
|
//if emote is a video
|
||||||
|
}else if(emote.type == 'video'){
|
||||||
|
//create video node
|
||||||
|
var emoteMedia = document.createElement('video');
|
||||||
|
//Add video link
|
||||||
|
emoteMeida.src = emote.link;
|
||||||
|
//Set video properties
|
||||||
|
emoteMedia.autoplay = true;
|
||||||
|
emoteMedia.muted = true;
|
||||||
|
emoteMedia.controls = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
emoteSpan.appendChild(emoteMedia);
|
||||||
|
|
||||||
|
this.emoteList.appendChild(emoteSpan);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const adminUtil = new canopyAdminUtils();
|
const adminUtil = new canopyAdminUtils();
|
||||||
const userList = new adminUserList();
|
const userList = new adminUserList();
|
||||||
const permissionList = new adminPermissionList();
|
const permissionList = new adminPermissionList();
|
||||||
const userBanList = new adminUserBanList();
|
const userBanList = new adminUserBanList();
|
||||||
const tokeCommandList = new adminTokeCommandList();
|
const tokeCommandList = new adminTokeCommandList();
|
||||||
|
const emoteList = new adminEmoteList();
|
||||||
|
|
@ -7,9 +7,9 @@ class chatPostprocessor{
|
||||||
//Set current chat nodes
|
//Set current chat nodes
|
||||||
this.chatEntry = chatEntry;
|
this.chatEntry = chatEntry;
|
||||||
this.chatBody = this.chatEntry.querySelector(".chat-entry-body");
|
this.chatBody = this.chatEntry.querySelector(".chat-entry-body");
|
||||||
//Split the chat body into an array of objects representing each word
|
|
||||||
//We could pass this through arguments but these functions wont be very interoperable anyways since they expect a purpose-made hashtable
|
//Split the chat message into an array of objects representing each word
|
||||||
this.splitBody();
|
this.splitMessage();
|
||||||
|
|
||||||
//Inject links into un-processed placeholders
|
//Inject links into un-processed placeholders
|
||||||
this.processLinks();
|
this.processLinks();
|
||||||
|
|
@ -26,9 +26,9 @@ class chatPostprocessor{
|
||||||
return this.chatEntry;
|
return this.chatEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
splitBody(){
|
splitMessage(){
|
||||||
//Create an empty array to hold the body
|
//Create an empty array to hold the body
|
||||||
this.bodyArray = [];
|
this.messageArray = [];
|
||||||
//Split string by word-boundries, with negative lookaheads to exclude file seperators so we don't split link placeholders
|
//Split string by word-boundries, with negative lookaheads to exclude file seperators so we don't split link placeholders
|
||||||
const splitString = this.rawData.msg.split(/(?<!␜)\b/g);
|
const splitString = this.rawData.msg.split(/(?<!␜)\b/g);
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ class chatPostprocessor{
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add it to our body array
|
//Add it to our body array
|
||||||
this.bodyArray.push(wordObj);
|
this.messageArray.push(wordObj);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@ class chatPostprocessor{
|
||||||
|
|
||||||
const _this = this;
|
const _this = this;
|
||||||
//For each word object
|
//For each word object
|
||||||
this.bodyArray.forEach((wordObj) => {
|
this.messageArray.forEach((wordObj) => {
|
||||||
if(wordObj.type == 'word'){
|
if(wordObj.type == 'word'){
|
||||||
//Inject current wordObj string into the chat body
|
//Inject current wordObj string into the chat body
|
||||||
injectString(wordObj.string);
|
injectString(wordObj.string);
|
||||||
|
|
@ -60,7 +60,7 @@ class chatPostprocessor{
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
link.classList.add('chat-link');
|
link.classList.add('chat-link');
|
||||||
link.href = wordObj.link;
|
link.href = wordObj.link;
|
||||||
//Use textContent to be safe since links can't be escaped
|
//Use textContent to be safe since links can't be escaped serverside
|
||||||
link.textContent = wordObj.link;
|
link.textContent = wordObj.link;
|
||||||
|
|
||||||
//Append node to chatBody
|
//Append node to chatBody
|
||||||
|
|
@ -70,7 +70,7 @@ class chatPostprocessor{
|
||||||
const badLink = document.createElement('a');
|
const badLink = document.createElement('a');
|
||||||
badLink.classList.add('chat-dead-link', 'danger-link');
|
badLink.classList.add('chat-dead-link', 'danger-link');
|
||||||
badLink.href = wordObj.link;
|
badLink.href = wordObj.link;
|
||||||
//Use textContent to be safe since links can't be escaped
|
//Use textContent to be safe since links can't be escaped serverside
|
||||||
badLink.textContent = wordObj.link;
|
badLink.textContent = wordObj.link;
|
||||||
|
|
||||||
//Append node to chatBody
|
//Append node to chatBody
|
||||||
|
|
@ -91,7 +91,6 @@ class chatPostprocessor{
|
||||||
img.classList.add('chat-img');
|
img.classList.add('chat-img');
|
||||||
img.src = wordObj.link;
|
img.src = wordObj.link;
|
||||||
|
|
||||||
//stringArray.push(wordObj.string.replace('␜',img.outerHTML));
|
|
||||||
//Append node to chatBody
|
//Append node to chatBody
|
||||||
injectNode(wordObj, img);
|
injectNode(wordObj, img);
|
||||||
}else if(wordObj.type == 'video'){
|
}else if(wordObj.type == 'video'){
|
||||||
|
|
@ -104,7 +103,6 @@ class chatPostprocessor{
|
||||||
vid.loop = true;
|
vid.loop = true;
|
||||||
vid.muted = true;
|
vid.muted = true;
|
||||||
|
|
||||||
//stringArray.push(wordObj.string.replace('␜',vid.outerHTML));
|
|
||||||
injectNode(wordObj, vid);
|
injectNode(wordObj, vid);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -115,8 +113,9 @@ class chatPostprocessor{
|
||||||
if(typeof item == "string"){
|
if(typeof item == "string"){
|
||||||
//Add it to the chat's innerHTML (it should already be escaped by the server)
|
//Add it to the chat's innerHTML (it should already be escaped by the server)
|
||||||
this.chatBody.innerHTML += item;
|
this.chatBody.innerHTML += item;
|
||||||
|
//Otherwise it should be a DOM node
|
||||||
}else{
|
}else{
|
||||||
//Otherwise it should be a DOM node, therefore we should append it
|
//Append the node to our chat body
|
||||||
this.chatBody.appendChild(item);
|
this.chatBody.appendChild(item);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -151,12 +150,14 @@ class chatPostprocessor{
|
||||||
|
|
||||||
addWhitespace(){
|
addWhitespace(){
|
||||||
//for each word object in the body
|
//for each word object in the body
|
||||||
this.bodyArray.forEach((wordObj, wordIndex) => {
|
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||||
//if the word object hasn't been pre-processed elsewhere
|
//if the word object hasn't been pre-processed elsewhere
|
||||||
if(wordObj.type == "word"){
|
if(wordObj.type == "word"){
|
||||||
|
//Create an empty array to hold our word
|
||||||
var wordArray = [];
|
var wordArray = [];
|
||||||
//Add invisible whitespace in-between characters to keep it from breaking page layout
|
//For each character in the string of the current word object
|
||||||
this.bodyArray[wordIndex].string.split("").forEach((char, charIndex) => {
|
this.messageArray[wordIndex].string.split("").forEach((char, charIndex) => {
|
||||||
|
//push the current character to the wordArray
|
||||||
wordArray.push(char);
|
wordArray.push(char);
|
||||||
//After eight characters
|
//After eight characters
|
||||||
if(charIndex > 8){
|
if(charIndex > 8){
|
||||||
|
|
@ -166,7 +167,8 @@ class chatPostprocessor{
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.bodyArray[wordIndex].string = wordArray.join("");
|
//Join the wordArray into a single string, and use it to set the current wordObject's string
|
||||||
|
this.messageArray[wordIndex].string = wordArray.join("");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -178,12 +180,14 @@ class chatPostprocessor{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//For every link received in this message
|
||||||
this.rawData.links.forEach((link, linkIndex) => {
|
this.rawData.links.forEach((link, linkIndex) => {
|
||||||
this.bodyArray.forEach((wordObj, wordIndex) => {
|
//For every word obj in the message array
|
||||||
|
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||||
//Check current wordobj for link (placeholder may contain whitespace with it)
|
//Check current wordobj for link (placeholder may contain whitespace with it)
|
||||||
if(wordObj.string.match(`␜${linkIndex}`)){
|
if(wordObj.string.match(`␜${linkIndex}`)){
|
||||||
//Set current word object in the body array to the new link object
|
//Set current word object in the body array to the new link object
|
||||||
this.bodyArray[wordIndex] = {
|
this.messageArray[wordIndex] = {
|
||||||
//Don't want to use a numbered placeholder to make this easier during body injection
|
//Don't want to use a numbered placeholder to make this easier during body injection
|
||||||
//but we also don't want to clobber any surrounding whitespace
|
//but we also don't want to clobber any surrounding whitespace
|
||||||
string: wordObj.string.replace(`␜${linkIndex}`, '␜'),
|
string: wordObj.string.replace(`␜${linkIndex}`, '␜'),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue