Started work on emotes panel
This commit is contained in:
parent
6a10bf3dea
commit
633884534c
20
src/controllers/panel/emoteController.js
Normal file
20
src/controllers/panel/emoteController.js
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*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/>.*/
|
||||||
|
|
||||||
|
//root index functions
|
||||||
|
module.exports.get = async function(req, res){
|
||||||
|
res.render('partial/panels/emote', {});
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@ const { Router } = require('express');
|
||||||
|
|
||||||
//local imports
|
//local imports
|
||||||
const placeholderController = require("../controllers/panel/placeholderController");
|
const placeholderController = require("../controllers/panel/placeholderController");
|
||||||
|
const emoteController = require("../controllers/panel/emoteController");
|
||||||
const popoutContainerController = require("../controllers/panel/popoutContainerController");
|
const popoutContainerController = require("../controllers/panel/popoutContainerController");
|
||||||
|
|
||||||
//globals
|
//globals
|
||||||
|
|
@ -27,6 +28,7 @@ const router = Router();
|
||||||
|
|
||||||
//routing functions
|
//routing functions
|
||||||
router.get('/placeholder', placeholderController.get);
|
router.get('/placeholder', placeholderController.get);
|
||||||
|
router.get('/emote', emoteController.get);
|
||||||
router.get('/popoutContainer', popoutContainerController.get);
|
router.get('/popoutContainer', popoutContainerController.get);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.-->
|
||||||
<script src="/js/channel/userlist.js"></script>
|
<script src="/js/channel/userlist.js"></script>
|
||||||
<script src="/js/channel/player.js"></script>
|
<script src="/js/channel/player.js"></script>
|
||||||
<script src="/js/channel/cpanel.js"></script>
|
<script src="/js/channel/cpanel.js"></script>
|
||||||
|
<script src="/js/channel/panels/emotePanel.js"></script>
|
||||||
<script src="/js/channel/channel.js"></script>
|
<script src="/js/channel/channel.js"></script>
|
||||||
</footer>
|
</footer>
|
||||||
</html>
|
</html>
|
||||||
34
src/views/partial/panels/emote.ejs
Normal file
34
src/views/partial/panels/emote.ejs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<!--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/>.-->
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/panel/emote.css">
|
||||||
|
<span class="title-span">
|
||||||
|
<span class="title-filler-span"></span>
|
||||||
|
<h3>Site Emotes <i class="bi-caret-down-fill" id="site-emotes-toggle"></i></h3>
|
||||||
|
<span class="title-filler-span"></span>
|
||||||
|
</span>
|
||||||
|
<div class="emote-panel-list" id="emote-panel-site-list"></div>
|
||||||
|
<span class="title-span">
|
||||||
|
<span class="title-filler-span"></span>
|
||||||
|
<h3>Channel Emotes <i class="bi-caret-down-fill" id="chan-emotes-toggle"></i></h3>
|
||||||
|
<span class="title-filler-span"></span>
|
||||||
|
</span>
|
||||||
|
<div class="emote-panel-list" id="emote-panel-chan-list"></div>
|
||||||
|
<span class="title-span">
|
||||||
|
<span class="title-filler-span"></span>
|
||||||
|
<h3>Personal Emotes <i class="bi-caret-down-fill" id="personal-emotes-toggle"></i></h3>
|
||||||
|
<span class="title-filler-span"></span>
|
||||||
|
</span>
|
||||||
|
<div class="emote-panel-list" id="emote-panel-personal-list"></div>
|
||||||
37
www/css/panel/emote.css
Normal file
37
www/css/panel/emote.css
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
.title-span{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
text-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-filler-span{
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
margin: auto 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emote-panel-list{
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(9em, 1fr));
|
||||||
|
padding: 1em;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.emote-panel-list-emote{
|
||||||
|
width: 9em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 0.5em 0;
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.emote-list-title{
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emote-list-media{
|
||||||
|
max-height: 8em;
|
||||||
|
max-width: 8em;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
@ -341,3 +341,13 @@ select.panel-head-element{
|
||||||
#delete-account-popup-title, #delete-channel-popup-title{
|
#delete-account-popup-title, #delete-channel-popup-title{
|
||||||
color: var(--danger0);
|
color: var(--danger0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* panel */
|
||||||
|
.title-filler-span{
|
||||||
|
background-color: var(--accent0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.emote-panel-list-emote{
|
||||||
|
border: 1px solid var(--accent0);
|
||||||
|
}
|
||||||
|
|
@ -54,9 +54,9 @@ class chatBox{
|
||||||
//Chat bar
|
//Chat bar
|
||||||
this.chatPrompt.addEventListener("keydown", this.send.bind(this));
|
this.chatPrompt.addEventListener("keydown", this.send.bind(this));
|
||||||
this.sendButton.addEventListener("click", this.send.bind(this));
|
this.sendButton.addEventListener("click", this.send.bind(this));
|
||||||
this.settingsIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new panelObj)});
|
this.settingsIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new panelObj(client))});
|
||||||
this.adminIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new panelObj)});
|
this.adminIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new panelObj(client))});
|
||||||
this.emoteIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new panelObj)});
|
this.emoteIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new emotePanel(client))});
|
||||||
|
|
||||||
//Header icons
|
//Header icons
|
||||||
this.aspectLockIcon.addEventListener("click", this.lockAspect.bind(this));
|
this.aspectLockIcon.addEventListener("click", this.lockAspect.bind(this));
|
||||||
|
|
|
||||||
|
|
@ -69,11 +69,16 @@ class cPanel{
|
||||||
this.activePanelTitle.textContent = this.activePanel.name;
|
this.activePanelTitle.textContent = this.activePanel.name;
|
||||||
|
|
||||||
//Call panel initialization function
|
//Call panel initialization function
|
||||||
this.activePanel.panelInit();
|
this.activePanel.panelDocument = this.activePanelDoc;
|
||||||
|
this.activePanel.docSwitch();
|
||||||
}
|
}
|
||||||
|
|
||||||
hideActivePanel(){
|
hideActivePanel(){
|
||||||
|
//Hide the panel
|
||||||
this.activePanelDiv.style.display = "none";
|
this.activePanelDiv.style.display = "none";
|
||||||
|
//Clear out the panel
|
||||||
|
this.activePanelDoc.innerHTML = '';
|
||||||
|
//Set active panel to null
|
||||||
this.activePanel = null;
|
this.activePanel = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,7 +106,8 @@ class cPanel{
|
||||||
this.pinnedPanelDiv.style.display = "flex";
|
this.pinnedPanelDiv.style.display = "flex";
|
||||||
|
|
||||||
//Call panel initialization function
|
//Call panel initialization function
|
||||||
this.pinnedPanel.panelInit();
|
this.pinnedPanel.panelDocument = this.pinnedPanelDoc;
|
||||||
|
this.pinnedPanel.docSwitch();
|
||||||
|
|
||||||
//Resize to window/content
|
//Resize to window/content
|
||||||
this.pinnedPanelDragger.fixCutoff();
|
this.pinnedPanelDragger.fixCutoff();
|
||||||
|
|
@ -131,10 +137,11 @@ class cPanel{
|
||||||
}
|
}
|
||||||
|
|
||||||
class panelObj{
|
class panelObj{
|
||||||
constructor(name = "Placeholder Panel", pageURL = "/panel/placeholder", panelDocument = window.document){
|
constructor(client, name = "Placeholder Panel", pageURL = "/panel/placeholder", panelDocument = window.document){
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.pageURL = pageURL;
|
this.pageURL = pageURL;
|
||||||
this.panelDocument = panelDocument;
|
this.panelDocument = panelDocument;
|
||||||
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPage(){
|
async getPage(){
|
||||||
|
|
@ -145,7 +152,7 @@ class panelObj{
|
||||||
return await response.text();
|
return await response.text();
|
||||||
}
|
}
|
||||||
|
|
||||||
panelInit(){
|
docSwitch(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,10 +202,15 @@ class poppedPanel{
|
||||||
|
|
||||||
//Set Window Title
|
//Set Window Title
|
||||||
this.window.document.title = this.window.document.title.replace("NULL_POPOUT", `${this.panel.name} (${client.channelName})`);
|
this.window.document.title = this.window.document.title.replace("NULL_POPOUT", `${this.panel.name} (${client.channelName})`);
|
||||||
|
|
||||||
//Set Panel Content
|
//Set Panel Content
|
||||||
this.panelTitle.innerText = this.panel.name;
|
this.panelTitle.innerText = this.panel.name;
|
||||||
this.panelDoc.innerHTML = this.panelBody;
|
this.panelDoc.innerHTML = this.panelBody;
|
||||||
|
|
||||||
|
//Set panel object document and call the related function
|
||||||
|
this.panel.panelDocument = this.window.document;
|
||||||
|
this.panel.docSwitch();
|
||||||
|
|
||||||
this.setupInput();
|
this.setupInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,11 +227,14 @@ class poppedPanel{
|
||||||
unpop(){
|
unpop(){
|
||||||
//Set active panel
|
//Set active panel
|
||||||
this.cPanel.setActivePanel(this.panel, this.panelDoc.innerHTML);
|
this.cPanel.setActivePanel(this.panel, this.panelDoc.innerHTML);
|
||||||
|
|
||||||
|
//Close the popped window
|
||||||
this.window.close();
|
this.window.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(){
|
pin(){
|
||||||
this.cPanel.setPinnedPanel(this.panel, this.panelDoc.innerHTML);
|
this.cPanel.setPinnedPanel(this.panel, this.panelDoc.innerHTML);
|
||||||
|
|
||||||
this.window.close();
|
this.window.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
116
www/js/channel/panels/emotePanel.js
Normal file
116
www/js/channel/panels/emotePanel.js
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
class emotePanel extends panelObj{
|
||||||
|
constructor(client, panelDocument){
|
||||||
|
super(client, "Emote Panel", "/panel/emote", panelDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
docSwitch(){
|
||||||
|
this.siteEmoteToggle = this.panelDocument.querySelector('#site-emotes-toggle');
|
||||||
|
this.chanEmoteToggle = this.panelDocument.querySelector('#chan-emotes-toggle');
|
||||||
|
this.personalEmoteToggle = this.panelDocument.querySelector('#personal-emotes-toggle');
|
||||||
|
|
||||||
|
this.siteEmoteList = this.panelDocument.querySelector('#emote-panel-site-list');
|
||||||
|
this.chanEmoteList = this.panelDocument.querySelector('#emote-panel-chan-list');
|
||||||
|
this.personalEmoteList = this.panelDocument.querySelector('#emote-panel-personal-list');
|
||||||
|
|
||||||
|
this.setupInput();
|
||||||
|
|
||||||
|
this.renderEmotes(this.client.chatBox.commandPreprocessor.emotes.site, this.siteEmoteList);
|
||||||
|
this.renderEmotes(this.client.chatBox.commandPreprocessor.emotes.chan, this.chanEmoteList);
|
||||||
|
this.renderEmotes(this.client.chatBox.commandPreprocessor.emotes.personal, this.personalEmoteList);
|
||||||
|
}
|
||||||
|
|
||||||
|
setupInput(){
|
||||||
|
//Make sure to remove any event listeners in-case we moving an already instantiated panel
|
||||||
|
this.siteEmoteToggle.removeEventListener("click", this.toggleSiteEmotes.bind(this));
|
||||||
|
this.siteEmoteToggle.addEventListener("click", this.toggleSiteEmotes.bind(this));
|
||||||
|
|
||||||
|
this.chanEmoteToggle.removeEventListener("click", this.toggleChanEmotes.bind(this));
|
||||||
|
this.chanEmoteToggle.addEventListener("click", this.toggleChanEmotes.bind(this));
|
||||||
|
|
||||||
|
this.personalEmoteToggle.removeEventListener("click", this.togglePersonalEmotes.bind(this));
|
||||||
|
this.personalEmoteToggle.addEventListener("click", this.togglePersonalEmotes.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleSiteEmotes(event){
|
||||||
|
this.toggleEmotes(this.siteEmoteToggle, this.siteEmoteList);
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleChanEmotes(event){
|
||||||
|
this.toggleEmotes(this.chanEmoteToggle, this.chanEmoteList);
|
||||||
|
}
|
||||||
|
|
||||||
|
togglePersonalEmotes(event){
|
||||||
|
this.toggleEmotes(this.personalEmoteToggle, this.personalEmoteList);
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleEmotes(icon, list){
|
||||||
|
if(list.checkVisibility()){
|
||||||
|
icon.classList.replace('bi-caret-down-fill','bi-caret-left-fill');
|
||||||
|
list.style.display = 'none';
|
||||||
|
}else{
|
||||||
|
icon.classList.replace('bi-caret-left-fill', 'bi-caret-down-fill');
|
||||||
|
list.style.display = 'grid';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEmote(emote){
|
||||||
|
//If we're using this from the active panel
|
||||||
|
if(client.cPanel.activePanel == this){
|
||||||
|
//Close it
|
||||||
|
this.client.cPanel.hideActivePanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add the emote to the chatbox prompt
|
||||||
|
this.client.chatBox.chatPrompt.value += `[${emote}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEmotes(emoteList, container){
|
||||||
|
//Clear out the container
|
||||||
|
container.innerHTML = '';
|
||||||
|
|
||||||
|
//For each emote
|
||||||
|
emoteList.forEach((emote) => {
|
||||||
|
//Create div to hold emote
|
||||||
|
const emoteDiv = document.createElement('div');
|
||||||
|
emoteDiv.classList.add('emote-panel-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 paragraph tag
|
||||||
|
const emoteTitle = document.createElement('p');
|
||||||
|
//Set title class
|
||||||
|
emoteTitle.classList.add('emote-list-title');
|
||||||
|
//Set emote title
|
||||||
|
emoteTitle.innerHTML = `[${emote.name}]`;
|
||||||
|
|
||||||
|
//Add the emote media to the emote span
|
||||||
|
emoteDiv.appendChild(emoteMedia);
|
||||||
|
//Add title paragraph node
|
||||||
|
emoteDiv.appendChild(emoteTitle);
|
||||||
|
|
||||||
|
//Add useEmote event listener
|
||||||
|
emoteDiv.addEventListener('click', ()=>{this.useEmote(emote.name)});
|
||||||
|
|
||||||
|
//Append the mote span to the emote list
|
||||||
|
container.appendChild(emoteDiv);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue