JSDoc for www/js/channel/*.js complete. Just need to hadnle ww/js/channel/panels.
This commit is contained in:
parent
ac06f839ea
commit
c0f219276f
2611
www/doc/client/cPanel.html
Normal file
2611
www/doc/client/cPanel.html
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
<h2><span class="attribs"><span class="type-signature"></span></span>channel<span class="signature">()</span><span class="type-signature"></span></h2>
|
<h2><span class="attribs"><span class="type-signature"></span></span>channel<span class="signature">()</span><span class="type-signature"></span></h2>
|
||||||
|
|
||||||
<div class="class-description">Class for object containing base code for the Canopy channel client.</div>
|
<div class="class-description">Class containing base code for the Canopy channel client.</div>
|
||||||
|
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
|
|
@ -1248,13 +1248,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="channel.html">channel</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="userList.html">userList</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:53 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ 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/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for object containing base code for the Canopy channel client.
|
* Class containing base code for the Canopy channel client.
|
||||||
*/
|
*/
|
||||||
class channel{
|
class channel{
|
||||||
/**
|
/**
|
||||||
|
|
@ -283,13 +283,13 @@ const client = new channel();</code></pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="channel.html">channel</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="userList.html">userList</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:53 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
671
www/doc/client/chat.js.html
Normal file
671
www/doc/client/chat.js.html
Normal file
|
|
@ -0,0 +1,671 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>JSDoc: Source: chat.js</title>
|
||||||
|
|
||||||
|
<script src="scripts/prettify/prettify.js"> </script>
|
||||||
|
<script src="scripts/prettify/lang-css.js"> </script>
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
<h1 class="page-title">Source: chat.js</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<article>
|
||||||
|
<pre class="prettyprint source linenums"><code>/*Canopy - The next generation of stoner streaming software
|
||||||
|
Copyright (C) 2024-2025 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/>.*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which represents Canopy Chat Box UI
|
||||||
|
*/
|
||||||
|
class chatBox{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Chat Box object
|
||||||
|
* @param {channel} client - Parent client Management Object
|
||||||
|
*/
|
||||||
|
constructor(client){
|
||||||
|
/**
|
||||||
|
* Parent Client Management Object
|
||||||
|
*/
|
||||||
|
this.client = client
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not chat-size should be locked to current media aspect ratio
|
||||||
|
*/
|
||||||
|
this.aspectLock = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the chat box should auto-scroll on new chat
|
||||||
|
*/
|
||||||
|
this.autoScroll = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat Buffer Scroll Top on last scroll
|
||||||
|
*/
|
||||||
|
this.lastPos = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Height of Chat Buffer on last scroll
|
||||||
|
*/
|
||||||
|
this.lastHeight = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Width of Chat Buffer on last scroll
|
||||||
|
*/
|
||||||
|
this.lastWidth = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Click-Dragger Object for handling dynamic chat/video split re-sizing
|
||||||
|
*/
|
||||||
|
this.clickDragger = new canopyUXUtils.clickDragger("#chat-panel-drag-handle", "#chat-panel-div");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command Pre-Processor Object
|
||||||
|
*/
|
||||||
|
this.commandPreprocessor = new commandPreprocessor(client);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat Post-Processor Object
|
||||||
|
*/
|
||||||
|
this.chatPostprocessor = new chatPostprocessor(client);
|
||||||
|
|
||||||
|
//Element Nodes
|
||||||
|
/**
|
||||||
|
* Chat Panel Container Div
|
||||||
|
*/
|
||||||
|
this.chatPanel = document.querySelector("#chat-panel-div");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* High Level Selector
|
||||||
|
*/
|
||||||
|
this.highSelect = document.querySelector("#chat-panel-high-level-select");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flair Selector
|
||||||
|
*/
|
||||||
|
this.flairSelect = document.querySelector("#chat-panel-flair-select");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat Buffer Div
|
||||||
|
*/
|
||||||
|
this.chatBuffer = document.querySelector("#chat-panel-buffer-div");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat Prompt
|
||||||
|
*/
|
||||||
|
this.chatPrompt = document.querySelector("#chat-panel-prompt");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-Complete Placeholder
|
||||||
|
*/
|
||||||
|
this.autocompletePlaceholder = document.querySelector("#chat-panel-prompt-autocomplete-filler");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-Complete Display
|
||||||
|
*/
|
||||||
|
this.autocompleteDisplay = document.querySelector("#chat-panel-prompt-autocomplete-display");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings Panel Icon
|
||||||
|
*/
|
||||||
|
this.settingsIcon = document.querySelector("#chat-panel-settings-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Admin Panel Icon
|
||||||
|
*/
|
||||||
|
this.adminIcon = document.querySelector("#chat-panel-admin-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emote Icon
|
||||||
|
*/
|
||||||
|
this.emoteIcon = document.querySelector("#chat-panel-emote-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send Chat/Command Button
|
||||||
|
*/
|
||||||
|
this.sendButton = document.querySelector("#chat-panel-send-button");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aspect Lock Icon
|
||||||
|
* Seems weird to stick this in here, but the split is dictated by chat width :P
|
||||||
|
*/
|
||||||
|
this.aspectLockIcon = document.querySelector("#media-panel-aspect-lock-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide Chat Icon
|
||||||
|
*/
|
||||||
|
this.hideChatIcon = document.querySelector("#chat-panel-div-hide");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show Chat Icon
|
||||||
|
*/
|
||||||
|
this.showChatIcon = document.querySelector("#media-panel-show-chat-icon");
|
||||||
|
|
||||||
|
//Setup functions
|
||||||
|
this.setupInput();
|
||||||
|
this.defineListeners();
|
||||||
|
this.sizeToAspect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines input-related event listeners
|
||||||
|
*/
|
||||||
|
setupInput(){
|
||||||
|
//Chat bar
|
||||||
|
this.chatPrompt.addEventListener("keydown", this.send.bind(this));
|
||||||
|
this.chatPrompt.addEventListener("keydown", this.tabComplete.bind(this));
|
||||||
|
this.chatPrompt.addEventListener("input", this.displayAutocomplete.bind(this));
|
||||||
|
this.autocompleteDisplay.addEventListener("click", this.tabComplete.bind(this));
|
||||||
|
this.sendButton.addEventListener("click", this.send.bind(this));
|
||||||
|
this.settingsIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new settingsPanel(client))});
|
||||||
|
this.adminIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new queuePanel(client))});
|
||||||
|
this.emoteIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new emotePanel(client))});
|
||||||
|
|
||||||
|
//Header icons
|
||||||
|
this.aspectLockIcon.addEventListener("click", this.lockAspect.bind(this));
|
||||||
|
this.showChatIcon.addEventListener("click", ()=>{this.toggleUI()});
|
||||||
|
this.hideChatIcon.addEventListener("click", ()=>{this.toggleUI()});
|
||||||
|
this.highSelect.addEventListener("change", this.setHighLevel.bind(this));
|
||||||
|
this.flairSelect.addEventListener("change", this.setFlair.bind(this));
|
||||||
|
|
||||||
|
//Clickdragger/Resize
|
||||||
|
this.clickDragger.handle.addEventListener("mousedown", this.unlockAspect.bind(this));
|
||||||
|
this.clickDragger.handle.addEventListener("clickdrag", this.handleAutoScroll.bind(this));
|
||||||
|
window.addEventListener("resize", this.resizeAspect.bind(this));
|
||||||
|
|
||||||
|
//chatbuffer
|
||||||
|
this.chatBuffer.addEventListener('scroll', this.scrollHandler.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines network-related event listners
|
||||||
|
*/
|
||||||
|
defineListeners(){
|
||||||
|
this.client.socket.on("chatMessage", this.displayChat.bind(this));
|
||||||
|
this.client.socket.on("clearChat", this.clearChat.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears chat on command from server
|
||||||
|
* @param {Object} data - Data from server
|
||||||
|
*/
|
||||||
|
clearChat(data){
|
||||||
|
//If we where passed a user to check
|
||||||
|
if(data.user != null){
|
||||||
|
var clearedChats = document.querySelectorAll(`.chat-entry-${data.user}`);
|
||||||
|
}else{
|
||||||
|
var clearedChats = document.querySelectorAll('.chat-entry');
|
||||||
|
}
|
||||||
|
|
||||||
|
//For each chat found
|
||||||
|
clearedChats.forEach((chat) => {
|
||||||
|
//fuckin' nukem!
|
||||||
|
chat.remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives, Post-Processes, and Displays chat messages from server
|
||||||
|
* @param {Object} data De-hydrated chat object from server
|
||||||
|
*/
|
||||||
|
displayChat(data){
|
||||||
|
//Create chat-entry span
|
||||||
|
var chatEntry = document.createElement('span');
|
||||||
|
chatEntry.classList.add("chat-panel-buffer","chat-entry",`chat-entry-${data.user}`);
|
||||||
|
|
||||||
|
//Create high-level label
|
||||||
|
var highLevel = document.createElement('p');
|
||||||
|
highLevel.classList.add("chat-panel-buffer","chat-entry-high-level","high-level");
|
||||||
|
highLevel.textContent = utils.unescapeEntities(`${data.highLevel}`);
|
||||||
|
chatEntry.appendChild(highLevel);
|
||||||
|
|
||||||
|
//If we're not using classic flair
|
||||||
|
if(data.flair != "classic"){
|
||||||
|
//Use flair
|
||||||
|
var flair = `flair-${data.flair}`;
|
||||||
|
//Otherwise
|
||||||
|
}else{
|
||||||
|
//Pull user's assigned color from the color map
|
||||||
|
var flair = this.client.userList.colorMap.get(data.user);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create username label
|
||||||
|
var userLabel = document.createElement('p');
|
||||||
|
userLabel.classList.add("chat-panel-buffer", "chat-entry-username", );
|
||||||
|
|
||||||
|
//Create color span
|
||||||
|
var flairSpan = document.createElement('span');
|
||||||
|
flairSpan.classList.add("chat-entry-flair-span", flair);
|
||||||
|
flairSpan.innerHTML = data.user;
|
||||||
|
|
||||||
|
//Inject flair span into user label before the colon
|
||||||
|
userLabel.innerHTML = `${flairSpan.outerHTML}: `;
|
||||||
|
|
||||||
|
//Append user label
|
||||||
|
chatEntry.appendChild(userLabel);
|
||||||
|
|
||||||
|
//Create chat body
|
||||||
|
var chatBody = document.createElement('p');
|
||||||
|
chatBody.classList.add("chat-panel-buffer","chat-entry-body");
|
||||||
|
chatEntry.appendChild(chatBody);
|
||||||
|
|
||||||
|
//Append the post-processed chat-body to the chat buffer
|
||||||
|
this.chatBuffer.appendChild(this.chatPostprocessor.postprocess(chatEntry, data));
|
||||||
|
|
||||||
|
//Set size to aspect on launch
|
||||||
|
this.resizeAspect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatinate Text into Chat Prompt
|
||||||
|
* @param {String} text - Text to Concatinate
|
||||||
|
*/
|
||||||
|
catChat(text){
|
||||||
|
this.chatPrompt.value += text;
|
||||||
|
this.displayAutocomplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls a toke command out with a specified user
|
||||||
|
* @param {String} user - User to toke with
|
||||||
|
*/
|
||||||
|
tokeWith(user){
|
||||||
|
this.commandPreprocessor.preprocess(user == this.client.user.user ? "!toke up fuckers" : `!toke up ${user}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-processes and sends text from chat prompt to server
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
|
send(event){
|
||||||
|
if((!event || !event.key || event.key == "Enter") && this.chatPrompt.value){
|
||||||
|
this.commandPreprocessor.preprocess(this.chatPrompt.value);
|
||||||
|
//Clear our prompt and autocomplete nodes
|
||||||
|
this.chatPrompt.value = "";
|
||||||
|
this.autocompletePlaceholder.innerHTML = '';
|
||||||
|
this.autocompleteDisplay.innerHTML = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays auto-complete text against current prompt input
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
|
displayAutocomplete(event){
|
||||||
|
//Find current match
|
||||||
|
const match = this.checkAutocomplete();
|
||||||
|
|
||||||
|
//Set placeholder to space out the autocomplete display
|
||||||
|
//Use text content because it's unescaped, and while this only effects local users, it'll keep someone from noticing and whinging about it
|
||||||
|
this.autocompletePlaceholder.textContent = this.chatPrompt.value;
|
||||||
|
//Set the autocomplete display
|
||||||
|
this.autocompleteDisplay.textContent = match.match.replace(match.word, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called upon tab-complete
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
|
tabComplete(event){
|
||||||
|
//If we hit tab or this isn't a keyboard event
|
||||||
|
if(event.key == "Tab" || event.key == null){
|
||||||
|
//Prevent default action
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
//return focus to the chat prompt
|
||||||
|
this.chatPrompt.focus();
|
||||||
|
|
||||||
|
//Grab autocompletion match
|
||||||
|
const match = this.checkAutocomplete();
|
||||||
|
|
||||||
|
//If we have a match
|
||||||
|
if(match.match != ''){
|
||||||
|
//Autocomplete the current word
|
||||||
|
this.chatPrompt.value += match.match.replace(match.word, '');
|
||||||
|
|
||||||
|
//Clear out the autocomplete display
|
||||||
|
this.autocompleteDisplay.innerHTML = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks string input against auto-complete dictionary to generate the best guess as to what the user is typing
|
||||||
|
* @param {String} input - Current input from Chat Prompt
|
||||||
|
* @returns {Object} Object containing word we where handed and the match we found
|
||||||
|
*/
|
||||||
|
checkAutocomplete(input = this.chatPrompt.value){
|
||||||
|
//Rebuild this fucker every time because it really doesn't take that much compute power and emotes/used tokes change
|
||||||
|
//Worst case we could store it persistantly and update as needed but I think that might be much
|
||||||
|
const dictionary = this.commandPreprocessor.buildAutocompleteDictionary();
|
||||||
|
|
||||||
|
//Split our input by whitespace
|
||||||
|
const splitInput = input.split(/\s/g);
|
||||||
|
//Get the current word we're working on
|
||||||
|
const word = splitInput[splitInput.length - 1];
|
||||||
|
let matches = [];
|
||||||
|
|
||||||
|
|
||||||
|
//Run through dictionary sets
|
||||||
|
for(let set of Object.keys(dictionary)){
|
||||||
|
//Go through the current definitions of the current dictionary set
|
||||||
|
//I went with a for loop instead of a filter beacuse I wanted to pull the processed definition with pre/postfix
|
||||||
|
//and also directly push it into a shared array :P
|
||||||
|
for(let cmd of dictionary[set].cmds){
|
||||||
|
|
||||||
|
//Append the proper prefix/postfix to the current command
|
||||||
|
const definition = (`${dictionary[set].prefix}${cmd[0]}${dictionary[set].postfix}`);
|
||||||
|
|
||||||
|
//if definition starts with the current word and the command is enabled
|
||||||
|
if((word == '' ? false : definition.indexOf(word) == 0) && cmd[1]){
|
||||||
|
//Add definition to match list
|
||||||
|
matches.push(definition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we found jack shit
|
||||||
|
if(matches.length == 0){
|
||||||
|
//Return jack shit
|
||||||
|
return {
|
||||||
|
match: '',
|
||||||
|
word
|
||||||
|
};
|
||||||
|
//If we got something
|
||||||
|
}else{
|
||||||
|
//return our top match
|
||||||
|
return {
|
||||||
|
match: matches[0],
|
||||||
|
word
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles initial client meta-data dump from server upon connection
|
||||||
|
* @param {Object} data - Data dump from server
|
||||||
|
*/
|
||||||
|
handleClientInfo(data){
|
||||||
|
this.updateFlairSelect(data.flairList, data.user.flair);
|
||||||
|
this.updateHighSelect(data.user.highLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets user high-level
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
|
setHighLevel(event){
|
||||||
|
const highLevel = event.target.value;
|
||||||
|
|
||||||
|
this.client.socket.emit("setHighLevel", {highLevel});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets user flair
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
|
setFlair(event){
|
||||||
|
const flair = event.target.value;
|
||||||
|
|
||||||
|
this.client.socket.emit("setFlair", {flair});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles High-Level updates from the server
|
||||||
|
* @param {Number} highLevel - High Level to Set
|
||||||
|
*/
|
||||||
|
updateHighSelect(highLevel){
|
||||||
|
this.highSelect.value = highLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles flair updates from the server
|
||||||
|
* @param {Array} fliarList - List of flairs to put into flair select
|
||||||
|
* @param {String} fliar - Flair to set
|
||||||
|
*/
|
||||||
|
updateFlairSelect(flairList, flair){
|
||||||
|
//clear current flair select
|
||||||
|
this.flairSelect.innerHTML = "";
|
||||||
|
|
||||||
|
//For each flair in flairlist
|
||||||
|
flairList.forEach((flair) => {
|
||||||
|
//Create an option
|
||||||
|
var flairOption = document.createElement('option');
|
||||||
|
//Set the name and innerHTML
|
||||||
|
flairOption.value = flair.name;
|
||||||
|
flairOption.textContent = utils.unescapeEntities(flair.displayName);
|
||||||
|
|
||||||
|
//Append it to the select
|
||||||
|
this.flairSelect.appendChild(flairOption);
|
||||||
|
});
|
||||||
|
|
||||||
|
//Set the selected flair in the UI
|
||||||
|
this.flairSelect.value = flair;
|
||||||
|
//Re-style the UI, do this in two seperate steps in-case we're running for the first time and have nothing to replace.
|
||||||
|
this.flairSelect.className = this.flairSelect.className.replace(/flair-\S*/, "");
|
||||||
|
this.flairSelect.classList.add(`flair-${flair}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locks chat-size to aspect ratio of media
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
|
lockAspect(event){
|
||||||
|
//prevent the user from breaking shit :P
|
||||||
|
if(this.chatPanel.style.display != "none"){
|
||||||
|
this.aspectLock = true;
|
||||||
|
this.aspectLockIcon.style.display = "none";
|
||||||
|
this.sizeToAspect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un-locks chat-size to aspect ratio of media
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
|
unlockAspect(event){
|
||||||
|
//Disable aspect lock
|
||||||
|
this.aspectLock = false;
|
||||||
|
|
||||||
|
//Show aspect lock icon
|
||||||
|
this.aspectLockIcon.style.display = "inline";
|
||||||
|
}
|
||||||
|
|
||||||
|
L /**
|
||||||
|
* Re-sizes chat back to aspect ratio on window re-size when chat box is aspect locked
|
||||||
|
* Also prevents horizontal scroll-bars from chat/window resizing
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
|
resizeAspect(event){
|
||||||
|
const playerHidden = this.client.player.playerDiv.style.display == "none";
|
||||||
|
|
||||||
|
//If the aspect is locked and the player is hidden
|
||||||
|
if(this.aspectLock && !playerHidden){
|
||||||
|
this.sizeToAspect();
|
||||||
|
//Otherwise
|
||||||
|
}else{
|
||||||
|
//Fix the clickDragger on userlist
|
||||||
|
this.client.userList.clickDragger.fixCutoff();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Autoscroll chat in-case we fucked it up
|
||||||
|
this.handleAutoScroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
L /**
|
||||||
|
* Re-sizes chat box relative to media aspect ratio
|
||||||
|
*/
|
||||||
|
sizeToAspect(){
|
||||||
|
if(this.chatPanel.style.display != "none"){
|
||||||
|
var targetVidWidth = this.client.player.getRatio() * this.chatPanel.getBoundingClientRect().height;
|
||||||
|
const targetChatWidth = window.innerWidth - targetVidWidth;
|
||||||
|
//This should be changeable in settings later on, for now it defaults to 20%
|
||||||
|
const limit = window.innerWidth * .2;
|
||||||
|
|
||||||
|
//Set width to target or 20vh depending on whether or not we've hit the width limit
|
||||||
|
this.chatPanel.style.flexBasis = targetChatWidth > limit ? `${targetChatWidth}px` : '20vh';
|
||||||
|
|
||||||
|
//Fix busted layout
|
||||||
|
var pageBreak = document.body.scrollWidth - document.body.getBoundingClientRect().width;
|
||||||
|
this.chatPanel.style.flexBasis = `${this.chatPanel.getBoundingClientRect().width + pageBreak}px`;
|
||||||
|
//This sometimes gets called before userList ahs been initiated :p
|
||||||
|
if(this.client.userList != null){
|
||||||
|
this.client.userList.clickDragger.fixCutoff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles Chat Box UX
|
||||||
|
* @param {Boolean} show - Whether or not to show Chat Box UX
|
||||||
|
*/
|
||||||
|
toggleUI(show = !this.chatPanel.checkVisibility()){
|
||||||
|
if(show){
|
||||||
|
this.chatPanel.style.display = "flex";
|
||||||
|
this.showChatIcon.style.display = "none";
|
||||||
|
this.client.player.hideVideoIcon.style.display = "flex";
|
||||||
|
this.client.userList.clickDragger.fixCutoff();
|
||||||
|
}else{
|
||||||
|
this.chatPanel.style.display = "none";
|
||||||
|
this.showChatIcon.style.display = "flex";
|
||||||
|
this.client.player.hideVideoIcon.style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Video Toggling
|
||||||
|
* @param {Boolean} show - Whether or not the video is currently being hidden
|
||||||
|
*/
|
||||||
|
handleVideoToggle(show){
|
||||||
|
//If we're enabling the video
|
||||||
|
if(show){
|
||||||
|
//Show hide chat icon
|
||||||
|
this.hideChatIcon.style.display = "flex";
|
||||||
|
|
||||||
|
//Re-enable the click dragger
|
||||||
|
this.clickDragger.enabled = true;
|
||||||
|
|
||||||
|
//Lock the chat to aspect ratio of the video, to make sure the chat width isn't breaking shit
|
||||||
|
this.lockAspect();
|
||||||
|
//If we're disabling the video
|
||||||
|
}else{
|
||||||
|
//Hide hide hide hide hide hide chat icon
|
||||||
|
this.hideChatIcon.style.display = "none";
|
||||||
|
|
||||||
|
//Need to clear the width from the split, or else it doesn't display properly
|
||||||
|
this.chatPanel.style.flexBasis = "100%";
|
||||||
|
|
||||||
|
//Disable the click dragger
|
||||||
|
this.clickDragger.enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles scrolling within the chat buffer
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
|
scrollHandler(event){
|
||||||
|
//If we're just starting out
|
||||||
|
if(this.lastPos == 0){
|
||||||
|
//Set last pos for the first time
|
||||||
|
this.lastPos = this.chatBuffer.scrollTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Calculate scroll delta
|
||||||
|
const deltaY = this.chatBuffer.scrollTop - this.lastPos;
|
||||||
|
|
||||||
|
//Grab visible bounding rect so we don't have to do it again (can't use offset because someone might zoom in :P)
|
||||||
|
const bufferRect = this.chatBuffer.getBoundingClientRect();
|
||||||
|
const bufferHeight = Math.round(bufferRect.height);
|
||||||
|
const bufferWidth = Math.round(bufferRect.width);
|
||||||
|
|
||||||
|
if(this.lastHeight == 0){
|
||||||
|
this.lastHeight = bufferHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.lastWidth == 0){
|
||||||
|
this.lastWidth = bufferWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we're scrolling up
|
||||||
|
if(deltaY < 0){
|
||||||
|
//If we have room to scroll, and we didn't resize
|
||||||
|
if(this.chatBuffer.scrollHeight > bufferHeight && (this.lastWidth == bufferWidth && this.lastHeight == bufferHeight)){
|
||||||
|
//Disable auto scrolling
|
||||||
|
this.autoScroll = false;
|
||||||
|
}else{
|
||||||
|
this.handleAutoScroll();
|
||||||
|
}
|
||||||
|
//Otherwise if the difference between the chat buffers scroll height and offset height is equal to the scroll top
|
||||||
|
//(Because it is scrolled all the way down)
|
||||||
|
}else if((this.chatBuffer.scrollHeight - bufferHeight) == this.chatBuffer.scrollTop){
|
||||||
|
this.autoScroll = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set last post/size for next the run
|
||||||
|
this.lastPos = this.chatBuffer.scrollTop;
|
||||||
|
this.lastHeight = bufferHeight;
|
||||||
|
this.lastWidth = bufferWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-scrolls chat buffer when new chats are entered.
|
||||||
|
*/
|
||||||
|
handleAutoScroll(){
|
||||||
|
//If autoscroll is enabled
|
||||||
|
if(this.autoScroll){
|
||||||
|
//Set chatBuffer scrollTop to the difference between scrollHeight and buffer height (scroll to the bottom)
|
||||||
|
this.chatBuffer.scrollTop = this.chatBuffer.scrollHeight - Math.round(this.chatBuffer.getBoundingClientRect().height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}</code></pre>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<br class="clear">
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script> prettyPrint(); </script>
|
||||||
|
<script src="scripts/linenumber.js"> </script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4659
www/doc/client/chatBox.html
Normal file
4659
www/doc/client/chatBox.html
Normal file
File diff suppressed because it is too large
Load diff
1803
www/doc/client/chatPostprocessor.html
Normal file
1803
www/doc/client/chatPostprocessor.html
Normal file
File diff suppressed because it is too large
Load diff
680
www/doc/client/chatPostprocessor.js.html
Normal file
680
www/doc/client/chatPostprocessor.js.html
Normal file
|
|
@ -0,0 +1,680 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>JSDoc: Source: chatPostprocessor.js</title>
|
||||||
|
|
||||||
|
<script src="scripts/prettify/prettify.js"> </script>
|
||||||
|
<script src="scripts/prettify/lang-css.js"> </script>
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
<h1 class="page-title">Source: chatPostprocessor.js</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<article>
|
||||||
|
<pre class="prettyprint source linenums"><code>/*Canopy - The next generation of stoner streaming software
|
||||||
|
Copyright (C) 2024-2025 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/>.*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class contianing client-side message post-processing code
|
||||||
|
*/
|
||||||
|
class chatPostprocessor{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Chat Post-Processor object
|
||||||
|
* @param {channel} client - Parent client Management Object
|
||||||
|
*/
|
||||||
|
constructor(client){
|
||||||
|
/**
|
||||||
|
* Parent Client Management Object
|
||||||
|
*/
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post-Processes a single message from the server and returns a presntable DOM Node
|
||||||
|
* @param {Node} chatEntry - Chat entry generated by initial chatBox method
|
||||||
|
* @param {Object} rawData - Raw data from server
|
||||||
|
* @returns {Node} Post-Processed Chat Entry
|
||||||
|
*/
|
||||||
|
postprocess(chatEntry, rawData){
|
||||||
|
//Create empty array to hold filter spans
|
||||||
|
this.filterSpans = [];
|
||||||
|
//Set raw message data
|
||||||
|
this.rawData = rawData;
|
||||||
|
//Set current chat nodes
|
||||||
|
this.chatEntry = chatEntry;
|
||||||
|
this.chatBody = this.chatEntry.querySelector(".chat-entry-body");
|
||||||
|
|
||||||
|
//Split the chat message into an array of objects representing each word/chunk
|
||||||
|
this.splitMessage();
|
||||||
|
|
||||||
|
//Process Qoutes
|
||||||
|
this.processQoute();
|
||||||
|
|
||||||
|
//Re-Hydrate and Inject links and embedded media into un-processed placeholders
|
||||||
|
this.processLinks();
|
||||||
|
|
||||||
|
//Inject clickable command examples
|
||||||
|
this.processCommandExamples();
|
||||||
|
|
||||||
|
//Inject clickable channel names
|
||||||
|
this.processChannelNames();
|
||||||
|
|
||||||
|
//Inject clickable usernames
|
||||||
|
this.processUsernames();
|
||||||
|
|
||||||
|
//Detect inline spoilers
|
||||||
|
this.processSpoilers();
|
||||||
|
|
||||||
|
//Detect inline strikethrough
|
||||||
|
this.processStrikethrough();
|
||||||
|
|
||||||
|
//Detect inline bold text
|
||||||
|
this.processBold();
|
||||||
|
|
||||||
|
//Detect inline italics
|
||||||
|
this.processItalics();
|
||||||
|
|
||||||
|
//Inject whitespace into long ass-words
|
||||||
|
this.addWhitespace();
|
||||||
|
|
||||||
|
//Handle non-standard chat types
|
||||||
|
this.handleChatType();
|
||||||
|
|
||||||
|
//Inject the pre-processed chat hyper-text into the chatEntry node
|
||||||
|
this.injectBody();
|
||||||
|
|
||||||
|
//Return the pre-processed node
|
||||||
|
return this.chatEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits message into an array of Word Objects for further processing
|
||||||
|
*/
|
||||||
|
splitMessage(){
|
||||||
|
//Create an empty array to hold the body
|
||||||
|
this.messageArray = [];
|
||||||
|
|
||||||
|
//Unescape any sanatized char codes as we use .textContent for double-safety, and to prevent splitting of char codes
|
||||||
|
//Split string by word-boundries on words and non-word boundries around whitespace, with negative lookaheads to exclude file seperators so we don't split link placeholders, and dashes so we dont split usernames and other things
|
||||||
|
//Also split by any invisble whitespace as a crutch to handle mushed links/emotes
|
||||||
|
//If we can one day figure out how to split non-repeating special chars instead of special chars with whitespace, that would be perf, unfortunately my brain hasn't rotted enough to understand regex like that just yet.
|
||||||
|
const splitString = utils.unescapeEntities(this.rawData.msg).split(/(?<!-)(?<!␜)(?=\w)\b|(?!-)(?<=\w)\b|(?=\s)\B|(?<=\s)\B|ㅤ/g);
|
||||||
|
|
||||||
|
//for each word in the splitstring
|
||||||
|
splitString.forEach((string) => {
|
||||||
|
//create a word object
|
||||||
|
const wordObj = {
|
||||||
|
string: string,
|
||||||
|
filterClasses: [],
|
||||||
|
type: "word"
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add it to our body array
|
||||||
|
this.messageArray.push(wordObj);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects word objects into chat-entry as proper DOM Nodes
|
||||||
|
*/
|
||||||
|
injectBody(){
|
||||||
|
//Create an empty array to hold the objects to inject
|
||||||
|
const injectionArray = [];
|
||||||
|
|
||||||
|
//For each word object
|
||||||
|
this.messageArray.forEach((wordObj) => {
|
||||||
|
if(wordObj.type == 'word'){
|
||||||
|
//Create span node
|
||||||
|
const span = document.createElement('span');
|
||||||
|
|
||||||
|
//Set span filter classes
|
||||||
|
span.classList.add(...wordObj.filterClasses);
|
||||||
|
|
||||||
|
//Set span text
|
||||||
|
span.textContent = wordObj.string;
|
||||||
|
|
||||||
|
//Inject node into array
|
||||||
|
injectionArray.push(span);
|
||||||
|
}else if(wordObj.type == 'link'){
|
||||||
|
//Create a link node from our link
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.classList.add('chat-link', ...wordObj.filterClasses);
|
||||||
|
link.href = wordObj.link;
|
||||||
|
link.target = "_blank";
|
||||||
|
//Use textContent to be safe since links can't be escaped serverside
|
||||||
|
link.textContent = wordObj.link;
|
||||||
|
|
||||||
|
//Append node to chatBody
|
||||||
|
combineNode(wordObj, link);
|
||||||
|
}else if(wordObj.type == 'deadLink'){
|
||||||
|
//Create a text span node from our link
|
||||||
|
const badLink = document.createElement('a');
|
||||||
|
badLink.classList.add('chat-dead-link', 'danger-link', ...wordObj.filterClasses);
|
||||||
|
badLink.href = wordObj.link;
|
||||||
|
badLink.target = "_blank";
|
||||||
|
//Use textContent to be safe since links can't be escaped serverside
|
||||||
|
badLink.textContent = wordObj.link;
|
||||||
|
|
||||||
|
//Append node to chatBody
|
||||||
|
combineNode(wordObj, badLink);
|
||||||
|
}else if(wordObj.type == 'malformedLink'){
|
||||||
|
//Create a text span node from our link
|
||||||
|
const malformedLink = document.createElement('span');
|
||||||
|
malformedLink.classList.add('chat-malformed-link', ...wordObj.filterClasses);
|
||||||
|
//Use textContent to be safe since links can't be escaped (this is why we don't just add it using injectString)
|
||||||
|
//arguably we could sanatize malformed links serverside since they're never actually used as links
|
||||||
|
malformedLink.textContent = wordObj.link;
|
||||||
|
|
||||||
|
//Append node to chatBody
|
||||||
|
combineNode(wordObj, malformedLink);
|
||||||
|
}else if(wordObj.type == 'image'){
|
||||||
|
//Create an img node from our link
|
||||||
|
const img = document.createElement('img');
|
||||||
|
img.classList.add('chat-img', ...wordObj.filterClasses);
|
||||||
|
img.src = wordObj.link;
|
||||||
|
|
||||||
|
//Look for an emote by link since emotes are tx'd as bare links
|
||||||
|
const emote = this.client.chatBox.commandPreprocessor.getEmoteByLink(wordObj.link);
|
||||||
|
|
||||||
|
//If this is a known emote
|
||||||
|
if(emote != null){
|
||||||
|
//Set the hover text to the emote's name
|
||||||
|
img.title = `[${emote.name}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Append node to chatBody
|
||||||
|
combineNode(wordObj, img);
|
||||||
|
}else if(wordObj.type == 'video'){
|
||||||
|
//Create a video node from our link
|
||||||
|
const vid = document.createElement('video');
|
||||||
|
vid.classList.add('chat-video', ...wordObj.filterClasses);
|
||||||
|
vid.src = wordObj.link;
|
||||||
|
vid.controls = false;
|
||||||
|
vid.autoplay = true;
|
||||||
|
vid.loop = true;
|
||||||
|
vid.muted = true;
|
||||||
|
|
||||||
|
//Look for an emote by link since emotes are tx'd as bare links
|
||||||
|
const emote = this.client.chatBox.commandPreprocessor.getEmoteByLink(wordObj.link);
|
||||||
|
|
||||||
|
//If this is a known emote
|
||||||
|
if(emote != null){
|
||||||
|
//Set the hover text to the emote's name
|
||||||
|
vid.title = `[${emote.name}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
combineNode(wordObj, vid);
|
||||||
|
}else if(wordObj.type == 'command'){
|
||||||
|
//Create link node
|
||||||
|
const link = document.createElement('a');
|
||||||
|
//Set class
|
||||||
|
link.classList.add('chat-link', ...wordObj.filterClasses);
|
||||||
|
//Set href and inner text
|
||||||
|
link.href = "javascript:";
|
||||||
|
link.textContent = wordObj.command;
|
||||||
|
|
||||||
|
//Add chatbox functionality
|
||||||
|
link.addEventListener('click', () => {this.client.chatBox.commandPreprocessor.preprocess(wordObj.command)});
|
||||||
|
|
||||||
|
//We don't have to worry about injecting this into whitespace since there shouldn't be any here.
|
||||||
|
injectionArray.push(link);
|
||||||
|
}else if(wordObj.type == "username"){
|
||||||
|
//Create link node
|
||||||
|
const link = document.createElement('a');
|
||||||
|
//set class
|
||||||
|
link.classList.add(wordObj.color, ...wordObj.filterClasses);
|
||||||
|
//Set href and inner text
|
||||||
|
link.href = "javascript:";
|
||||||
|
link.textContent = wordObj.string;
|
||||||
|
|
||||||
|
//add chatbox functionality
|
||||||
|
link.addEventListener('click', () => {this.client.chatBox.chatPrompt.value += `${wordObj.string} `});
|
||||||
|
|
||||||
|
//We don't have to worry about injecting this into whitespace since there shouldn't be any here.
|
||||||
|
injectionArray.push(link);
|
||||||
|
}else if(wordObj.type == "channel"){
|
||||||
|
//Create link node
|
||||||
|
const link = document.createElement('a');
|
||||||
|
//set class
|
||||||
|
link.classList.add('chat-link', ...wordObj.filterClasses);
|
||||||
|
//Set href and inner text
|
||||||
|
link.href = `/c/${wordObj.chan}`;
|
||||||
|
link.target = "_blank"
|
||||||
|
link.textContent = wordObj.string;
|
||||||
|
|
||||||
|
//We don't have to worry about injecting this into whitespace since there shouldn't be any here.
|
||||||
|
injectionArray.push(link);
|
||||||
|
}else{
|
||||||
|
console.warn("Unknown chat postprocessor word type:");
|
||||||
|
console.warn(wordObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//For each item found in the injection array
|
||||||
|
for(let itemIndex in injectionArray){
|
||||||
|
const item = injectionArray[itemIndex];
|
||||||
|
|
||||||
|
//Currently this doesnt support multiple overlapping span-type filters
|
||||||
|
//not a huge deal since we only have once (spoiler)
|
||||||
|
//All others can be applied per-node without any usability side effects
|
||||||
|
const curFilter = this.filterSpans.filter(filterFilters)[0];
|
||||||
|
let appendBody = this.chatBody;
|
||||||
|
|
||||||
|
//If we have a filter span
|
||||||
|
if(curFilter != null){
|
||||||
|
//If we're beggining the array
|
||||||
|
if(itemIndex == curFilter.index[0]){
|
||||||
|
//Create the span
|
||||||
|
appendBody = document.createElement('span');
|
||||||
|
//Label it for what it is
|
||||||
|
appendBody.classList.add(curFilter.class);
|
||||||
|
//Add it to the chat body
|
||||||
|
this.chatBody.appendChild(appendBody);
|
||||||
|
//Otherwise
|
||||||
|
}else{
|
||||||
|
//Use the existing span
|
||||||
|
appendBody = (this.chatBody.children[this.chatBody.children.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Append the node to our chat body
|
||||||
|
appendBody.appendChild(item);
|
||||||
|
|
||||||
|
function filterFilters(filter){
|
||||||
|
//If the index is within the filter span
|
||||||
|
return filter.index[0] <= itemIndex && filter.index[1] >= itemIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Like string.replace except it actually injects the node so we can keep things like event handlers
|
||||||
|
function combineNode(wordObj, node, placeholder = '␜'){
|
||||||
|
//Split string by the placeholder so we can keep surrounding whitespace
|
||||||
|
const splitWord = wordObj.string.split(placeholder, 2);
|
||||||
|
|
||||||
|
//Create combined node
|
||||||
|
const combinedSpan = document.createElement('span');
|
||||||
|
|
||||||
|
//Add the first part of the text
|
||||||
|
combinedSpan.textContent = splitWord[0];
|
||||||
|
|
||||||
|
//Add in the requestd node
|
||||||
|
combinedSpan.appendChild(node);
|
||||||
|
|
||||||
|
//Finish it off with the last bit of text
|
||||||
|
combinedSpan.insertAdjacentText('beforeend', splitWord[1]);
|
||||||
|
|
||||||
|
//Add to injection array as three nested items to keep arrays lined up
|
||||||
|
injectionArray.push(combinedSpan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes qouted text in chat
|
||||||
|
*/
|
||||||
|
processQoute(){
|
||||||
|
//If the message starts off with '>'
|
||||||
|
if(this.messageArray[0].string[0] == '>'){
|
||||||
|
this.chatBody.classList.add("qoute");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes clickable command examples in chat
|
||||||
|
*/
|
||||||
|
processCommandExamples(){
|
||||||
|
//for each word object in the body
|
||||||
|
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||||
|
//if the word object hasn't been pre-processed elsewhere
|
||||||
|
if(wordObj.type == "word"){
|
||||||
|
//Get last char of current word
|
||||||
|
const lastChar = wordObj.string[wordObj.string.length - 1];
|
||||||
|
|
||||||
|
//if the last char is !
|
||||||
|
if(lastChar == '!' || lastChar == '/'){
|
||||||
|
//get next word
|
||||||
|
const nextWord = this.messageArray[wordIndex + 1];
|
||||||
|
//if we have another word
|
||||||
|
if(nextWord != null){
|
||||||
|
const command = lastChar + nextWord.string;
|
||||||
|
//Take out the command marker
|
||||||
|
this.messageArray[wordIndex].string = wordObj.string.slice(0,-1);
|
||||||
|
|
||||||
|
const commandObj = {
|
||||||
|
type: "command",
|
||||||
|
string: nextWord.string,
|
||||||
|
filterClasses: [],
|
||||||
|
command: command
|
||||||
|
}
|
||||||
|
|
||||||
|
this.messageArray[wordIndex + 1] = commandObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes clickable channel names in chat
|
||||||
|
*/
|
||||||
|
processChannelNames(){
|
||||||
|
//for each word object in the body
|
||||||
|
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||||
|
//if the word object hasn't been pre-processed elsewhere
|
||||||
|
if(wordObj.type == "word"){
|
||||||
|
//Get last char of current word with slashes pounds
|
||||||
|
const lastChar = wordObj.string[wordObj.string.length - 1];
|
||||||
|
const secondLastChar = wordObj.string[wordObj.string.length - 2];
|
||||||
|
|
||||||
|
//if the last char is # and the second to last char isn't & or # (avoid spoilers)
|
||||||
|
if(lastChar == '#' && secondLastChar != '#'){
|
||||||
|
//get next word
|
||||||
|
const nextWord = this.messageArray[wordIndex + 1];
|
||||||
|
//if we have another word
|
||||||
|
if(nextWord != null){
|
||||||
|
//Take out the chan marker
|
||||||
|
this.messageArray[wordIndex].string = wordObj.string.slice(0,-1);
|
||||||
|
|
||||||
|
const commandObj = {
|
||||||
|
type: "channel",
|
||||||
|
string: lastChar + nextWord.string,
|
||||||
|
filterClasses: [],
|
||||||
|
chan: nextWord.string
|
||||||
|
}
|
||||||
|
|
||||||
|
this.messageArray[wordIndex + 1] = commandObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes clickable username callouts in chat
|
||||||
|
*/
|
||||||
|
processUsernames(){
|
||||||
|
//for each word object in the body
|
||||||
|
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||||
|
//if the word object hasn't been pre-processed elsewhere
|
||||||
|
if(wordObj.type == "word"){
|
||||||
|
//Check for user and get their color
|
||||||
|
const color = this.client.userList.colorMap.get(wordObj.string);
|
||||||
|
|
||||||
|
//If the current word is the username of a connected user
|
||||||
|
if(color != null){
|
||||||
|
//Mark it as so
|
||||||
|
this.messageArray[wordIndex].type = "username";
|
||||||
|
//Store their color
|
||||||
|
this.messageArray[wordIndex].color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects invisible whitespace in long-ass words to prevent fucking up the chat buffer size
|
||||||
|
*/
|
||||||
|
addWhitespace(){
|
||||||
|
//for each word object in the body
|
||||||
|
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||||
|
//if the word object hasn't been pre-processed elsewhere
|
||||||
|
if(wordObj.type == "word"){
|
||||||
|
//Create an empty array to hold our word
|
||||||
|
var wordArray = [];
|
||||||
|
//For each character in the string of the current word object
|
||||||
|
this.messageArray[wordIndex].string.split("").forEach((char, charIndex) => {
|
||||||
|
//push the current character to the wordArray
|
||||||
|
wordArray.push(char);
|
||||||
|
//After eight characters
|
||||||
|
if(charIndex > 8){
|
||||||
|
//Push an invisible line-break character between every character
|
||||||
|
wordArray.push("ㅤ");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//Join the wordArray into a single string, and use it to set the current wordObject's string
|
||||||
|
this.messageArray[wordIndex].string = wordArray.join("");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for text in-between a specific delimiter and runs a given callback against it
|
||||||
|
*
|
||||||
|
* Internal command used by several text filters to prevent code re-writes
|
||||||
|
* @param {String} delimiter - delimiter to search string by
|
||||||
|
* @param {Function} cb - Callback function to run against found strings
|
||||||
|
* @returns {Array} - list of found instances of filter
|
||||||
|
*/
|
||||||
|
processFilter(delimiter, cb){
|
||||||
|
//Create empty array to hold spoilers (keep this seperate at first for internal function use)
|
||||||
|
const foundFilters = [];
|
||||||
|
//Spoiler detection stage
|
||||||
|
//For each word object in the message array
|
||||||
|
main: for(let wordIndex = 0; wordIndex < this.messageArray.length; wordIndex++){
|
||||||
|
//Get the current word object
|
||||||
|
const wordObj = this.messageArray[wordIndex];
|
||||||
|
|
||||||
|
//If its a regular word and contains '##'
|
||||||
|
if(wordObj.type == 'word' && wordObj.string.match(utils.escapeRegex(delimiter))){
|
||||||
|
|
||||||
|
//Crawl through detected spoilers
|
||||||
|
for(let spoiler of foundFilters){
|
||||||
|
//If the current word object is part of a detected spoiler
|
||||||
|
if(wordIndex == spoiler[0] || wordIndex == spoiler[1]){
|
||||||
|
//ignore it and continue on to the next word object
|
||||||
|
continue main;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Crawl throw word objects after the current one
|
||||||
|
for(let endIndex = (wordIndex + 1); endIndex < this.messageArray.length; endIndex++){
|
||||||
|
//Get the current end object
|
||||||
|
const endObj = this.messageArray[endIndex];
|
||||||
|
|
||||||
|
//If its a regular word and contains '##'
|
||||||
|
if(endObj.type == 'word' && endObj.string.match(utils.escapeRegex(delimiter))){
|
||||||
|
//Setup the found filter array
|
||||||
|
const foundFilter = [wordIndex, endIndex];
|
||||||
|
|
||||||
|
//Scrape out delimiters
|
||||||
|
wordObj.string = wordObj.string.replaceAll(delimiter,'');
|
||||||
|
endObj.string = endObj.string.replaceAll(delimiter,'');
|
||||||
|
|
||||||
|
//Add it to the list of detected filters
|
||||||
|
foundFilters.push(foundFilter);
|
||||||
|
|
||||||
|
//Run the filter callback
|
||||||
|
cb(foundFilter)
|
||||||
|
|
||||||
|
//Break the nested end-detection loop
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundFilters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes in-line spoilers
|
||||||
|
*/
|
||||||
|
processSpoilers(){
|
||||||
|
//Process spoilers using '##' delimiter
|
||||||
|
this.processFilter('##', (foundSpoiler)=>{
|
||||||
|
//For each found spoiler add it to the list of found filter spans
|
||||||
|
this.filterSpans.push({class: "spoiler", index: [foundSpoiler[0] + 1, foundSpoiler[1] - 1], delimiters: [foundSpoiler[0], foundSpoiler[1]]});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes in-line Strike-through
|
||||||
|
*/
|
||||||
|
processStrikethrough(){
|
||||||
|
//Process strikethrough's using '~~' delimiter
|
||||||
|
this.processFilter('~~', (foundStrikethrough)=>{
|
||||||
|
for(let wordIndex = foundStrikethrough[0]; wordIndex < foundStrikethrough[1]; wordIndex++){
|
||||||
|
this.messageArray[wordIndex].filterClasses.push("strikethrough");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes in-line Bold/Strong text
|
||||||
|
*/
|
||||||
|
processBold(){
|
||||||
|
//Process strong text using '*' delimiter
|
||||||
|
this.processFilter('**', (foundStrikethrough)=>{
|
||||||
|
for(let wordIndex = foundStrikethrough[0]; wordIndex < foundStrikethrough[1]; wordIndex++){
|
||||||
|
this.messageArray[wordIndex].filterClasses.push("bold");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes in-line Italics
|
||||||
|
*/
|
||||||
|
processItalics(){
|
||||||
|
//Process italics using '__' delimiter
|
||||||
|
this.processFilter('*', (foundStrikethrough)=>{
|
||||||
|
for(let wordIndex = foundStrikethrough[0]; wordIndex < foundStrikethrough[1]; wordIndex++){
|
||||||
|
this.messageArray[wordIndex].filterClasses.push("italics");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes clickable links and embedded media
|
||||||
|
*/
|
||||||
|
processLinks(){
|
||||||
|
//If we don't have links
|
||||||
|
if(this.rawData.links == null){
|
||||||
|
//Don't bother
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//For every link received in this message
|
||||||
|
this.rawData.links.forEach((link, linkIndex) => {
|
||||||
|
//For every word obj in the message array
|
||||||
|
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||||
|
//Check current wordobj for link (placeholder may contain whitespace with it)
|
||||||
|
if(wordObj.string.match(`␜${linkIndex}`)){
|
||||||
|
//Set current word object in the body array to the new link object
|
||||||
|
this.messageArray[wordIndex] = {
|
||||||
|
//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
|
||||||
|
string: wordObj.string.replace(`␜${linkIndex}`, '␜'),
|
||||||
|
link: link.link,
|
||||||
|
type: link.type,
|
||||||
|
filterClasses: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks chat nodes in-case of non-standard chat types
|
||||||
|
*/
|
||||||
|
handleChatType(){
|
||||||
|
if(this.rawData.type == "whisper"){
|
||||||
|
//add whisper class
|
||||||
|
this.chatBody.classList.add('whisper');
|
||||||
|
}else if(this.rawData.type == "announcement"){
|
||||||
|
//Squash the high-level
|
||||||
|
this.chatEntry.querySelector('.high-level').remove();
|
||||||
|
|
||||||
|
//Get the username and make it into an announcement title (little hacky but this *IS* postprocessing)
|
||||||
|
const userNode = this.chatEntry.querySelector('.chat-entry-username');
|
||||||
|
userNode.textContent = `${userNode.textContent.slice(0,-2)} Announcement`;
|
||||||
|
|
||||||
|
//Add/remove relevant classes
|
||||||
|
userNode.classList.remove('chat-entry-username');
|
||||||
|
userNode.classList.add('announcement-title');
|
||||||
|
this.chatBody.classList.add('announcement-body');
|
||||||
|
this.chatEntry.classList.add('announcement');
|
||||||
|
}else if(this.rawData.type == "toke"){
|
||||||
|
//Squash the high-level
|
||||||
|
this.chatEntry.querySelector('.high-level').remove();
|
||||||
|
|
||||||
|
//remove the username
|
||||||
|
this.chatEntry.querySelector('.chat-entry-username').remove();
|
||||||
|
|
||||||
|
//Add toke/tokewhisper class
|
||||||
|
this.chatBody.classList.add("toke");
|
||||||
|
}else if(this.rawData.type == "tokewhisper"){
|
||||||
|
//Squash the high-level
|
||||||
|
this.chatEntry.querySelector('.high-level').remove();
|
||||||
|
|
||||||
|
//remove the username
|
||||||
|
this.chatEntry.querySelector('.chat-entry-username').remove();
|
||||||
|
|
||||||
|
//Add toke/tokewhisper class
|
||||||
|
this.chatBody.classList.add("tokewhisper","serverwhisper");
|
||||||
|
}else if(this.rawData.type == "spoiler"){
|
||||||
|
//Set whole-body spoiler
|
||||||
|
this.chatBody.classList.add("spoiler");
|
||||||
|
}else if(this.rawData.type == "strikethrough"){
|
||||||
|
//Set whole-body spoiler
|
||||||
|
this.chatBody.classList.add("strikethrough");
|
||||||
|
}else if(this.rawData.type == "bold"){
|
||||||
|
//Set whole-body spoiler
|
||||||
|
this.chatBody.classList.add("bold");
|
||||||
|
}else if(this.rawData.type == "italics"){
|
||||||
|
//Set whole-body spoiler
|
||||||
|
this.chatBody.classList.add("italics");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}</code></pre>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<br class="clear">
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script> prettyPrint(); </script>
|
||||||
|
<script src="scripts/linenumber.js"> </script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
<h2><span class="attribs"><span class="type-signature"></span></span>commandPreprocessor<span class="signature">(client)</span><span class="type-signature"></span></h2>
|
<h2><span class="attribs"><span class="type-signature"></span></span>commandPreprocessor<span class="signature">(client)</span><span class="type-signature"></span></h2>
|
||||||
|
|
||||||
<div class="class-description">Class for object containing chat and command pre-processing logic</div>
|
<div class="class-description">Class containing chat and command pre-processing logic</div>
|
||||||
|
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
|
|
@ -105,7 +105,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td class="description last">Parent client mgmt object</td>
|
<td class="description last">Parent client Management Object</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1906,13 +1906,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="channel.html">channel</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="userList.html">userList</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:53 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -43,12 +43,12 @@ 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/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for object containing chat and command pre-processing logic
|
* Class containing chat and command pre-processing logic
|
||||||
*/
|
*/
|
||||||
class commandPreprocessor{
|
class commandPreprocessor{
|
||||||
/**
|
/**
|
||||||
* Instantiates a new commandPreprocessor object
|
* Instantiates a new commandPreprocessor object
|
||||||
* @param {channel} client - Parent client mgmt object
|
* @param {channel} client - Parent client Management Object
|
||||||
*/
|
*/
|
||||||
constructor(client){
|
constructor(client){
|
||||||
/**
|
/**
|
||||||
|
|
@ -328,7 +328,7 @@ class commandPreprocessor{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for Object which contains logic for client-side commands
|
* Class which contains logic for client-side commands
|
||||||
*/
|
*/
|
||||||
class commandProcessor{
|
class commandProcessor{
|
||||||
/**
|
/**
|
||||||
|
|
@ -365,13 +365,13 @@ class commandProcessor{
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="channel.html">channel</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="userList.html">userList</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:53 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
<h2><span class="attribs"><span class="type-signature"></span></span>commandProcessor<span class="signature">(client)</span><span class="type-signature"></span></h2>
|
<h2><span class="attribs"><span class="type-signature"></span></span>commandProcessor<span class="signature">(client)</span><span class="type-signature"></span></h2>
|
||||||
|
|
||||||
<div class="class-description">Class for Object which contains logic for client-side commands</div>
|
<div class="class-description">Class which contains logic for client-side commands</div>
|
||||||
|
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
|
|
@ -415,13 +415,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="channel.html">channel</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="userList.html">userList</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:53 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
524
www/doc/client/cpanel.js.html
Normal file
524
www/doc/client/cpanel.js.html
Normal file
|
|
@ -0,0 +1,524 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>JSDoc: Source: cpanel.js</title>
|
||||||
|
|
||||||
|
<script src="scripts/prettify/prettify.js"> </script>
|
||||||
|
<script src="scripts/prettify/lang-css.js"> </script>
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
<h1 class="page-title">Source: cpanel.js</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<article>
|
||||||
|
<pre class="prettyprint source linenums"><code>/*Canopy - The next generation of stoner streaming software
|
||||||
|
Copyright (C) 2024-2025 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/>.*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing code for managing the Canopy Panel UX
|
||||||
|
*/
|
||||||
|
class cPanel{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Canopy Panel Management object
|
||||||
|
* @param {channel} client - Parent client Management Object
|
||||||
|
*/
|
||||||
|
constructor(client){
|
||||||
|
/**
|
||||||
|
* Parent Client Management object
|
||||||
|
*/
|
||||||
|
this.client = client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active Panel Object
|
||||||
|
*/
|
||||||
|
this.activePanel = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pinned Panel Object
|
||||||
|
*/
|
||||||
|
this.pinnedPanel = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Popped Panel Objects
|
||||||
|
*/
|
||||||
|
this.poppedPanels = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Click-Dragger object for re-sizable active panel
|
||||||
|
*/
|
||||||
|
this.activePanelDragger = new canopyUXUtils.clickDragger("#cpanel-active-drag-handle", "#cpanel-active-div", false, null, false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Click-Dragger object for re-sizable pinned panel
|
||||||
|
*/
|
||||||
|
this.pinnedPanelDragger = new canopyUXUtils.clickDragger("#cpanel-pinned-drag-handle", "#cpanel-pinned-div", false, this.client.chatBox.clickDragger);
|
||||||
|
|
||||||
|
//Element Nodes
|
||||||
|
//Active Panel
|
||||||
|
/**
|
||||||
|
* Active Panel Container
|
||||||
|
*/
|
||||||
|
this.activePanelDiv = document.querySelector("#cpanel-active-div");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active Panel Title
|
||||||
|
*/
|
||||||
|
this.activePanelTitle = document.querySelector("#cpanel-active-title");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active Title Document Div
|
||||||
|
*/
|
||||||
|
this.activePanelDoc = document.querySelector("#cpanel-active-doc");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active Panel Pin Icon
|
||||||
|
*/
|
||||||
|
this.activePanelPinIcon = document.querySelector("#cpanel-active-pin-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active Panel Pop-Out Icon
|
||||||
|
*/
|
||||||
|
this.activePanelPopoutIcon = document.querySelector("#cpanel-active-popout-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active Panel Close Icon
|
||||||
|
*/
|
||||||
|
this.activePanelCloseIcon = document.querySelector("#cpanel-active-close-icon");
|
||||||
|
|
||||||
|
//Pinned Panel
|
||||||
|
/**
|
||||||
|
* Pinned Panel Contianer
|
||||||
|
*/
|
||||||
|
this.pinnedPanelDiv = document.querySelector("#cpanel-pinned-div");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pinned Panel Title
|
||||||
|
*/
|
||||||
|
this.pinnedPanelTitle = document.querySelector("#cpanel-pinned-title");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pinned Panel Document Div
|
||||||
|
*/
|
||||||
|
this.pinnedPanelDoc = document.querySelector("#cpanel-pinned-doc");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pinned Panel Un-Pin Icon
|
||||||
|
*/
|
||||||
|
this.pinnedPanelUnpinIcon = document.querySelector("#cpanel-pinned-unpin-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pinned Panel Pop-Out Icon
|
||||||
|
*/
|
||||||
|
this.pinnedPanelPopoutIcon = document.querySelector("#cpanel-pinned-popout-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pinned Panel Close Icon
|
||||||
|
*/
|
||||||
|
this.pinnedPanelCloseIcon = document.querySelector("#cpanel-pinned-close-icon");
|
||||||
|
|
||||||
|
this.setupInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines input-related event listeners
|
||||||
|
*/
|
||||||
|
setupInput(){
|
||||||
|
this.activePanelCloseIcon.addEventListener("click", this.hideActivePanel.bind(this));
|
||||||
|
this.activePanelPinIcon.addEventListener("click", this.pinPanel.bind(this));
|
||||||
|
this.activePanelPopoutIcon.addEventListener("click", this.popActivePanel.bind(this));
|
||||||
|
this.pinnedPanelCloseIcon.addEventListener("click", this.hidePinnedPanel.bind(this));
|
||||||
|
this.pinnedPanelUnpinIcon.addEventListener("click", this.unpinPanel.bind(this));
|
||||||
|
this.pinnedPanelPopoutIcon.addEventListener("click", this.popPinnedPanel.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets Active Panel
|
||||||
|
* @param {panelObj} panel - Panel Object to set as active
|
||||||
|
* @param {String} panelBody - innerHTML of Panel, pulls from panelObj.getPage() if empty
|
||||||
|
*/
|
||||||
|
async setActivePanel(panel, panelBody){
|
||||||
|
//Set active panel
|
||||||
|
this.activePanel = panel;
|
||||||
|
|
||||||
|
//Grab panel hypertext content and load it into div
|
||||||
|
this.activePanelDoc.innerHTML = (panelBody == null || panelBody == "") ? await this.activePanel.getPage() : panelBody;
|
||||||
|
|
||||||
|
|
||||||
|
//Display panel
|
||||||
|
this.activePanelDiv.style.display = "flex";
|
||||||
|
this.activePanelTitle.textContent = this.activePanel.name;
|
||||||
|
|
||||||
|
//Call panel initialization function
|
||||||
|
this.activePanel.panelDocument = this.activePanelDoc;
|
||||||
|
this.activePanel.docSwitch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides active panel
|
||||||
|
* @param {Event} event - Event passed down from Input Handler
|
||||||
|
* @param {Boolean} keepAlive - Prevents closing panel if true
|
||||||
|
*/
|
||||||
|
hideActivePanel(event, keepAlive = false){
|
||||||
|
if(!keepAlive){
|
||||||
|
this.activePanel.closer();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Hide the panel
|
||||||
|
this.activePanelDiv.style.display = "none";
|
||||||
|
//Clear out the panel
|
||||||
|
this.activePanelDoc.innerHTML = '';
|
||||||
|
//Set active panel to null
|
||||||
|
this.activePanel = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pins active panel
|
||||||
|
*/
|
||||||
|
pinPanel(){
|
||||||
|
this.setPinnedPanel(this.activePanel, this.activePanelDoc.innerHTML);
|
||||||
|
this.hideActivePanel(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pop's out active panel
|
||||||
|
*/
|
||||||
|
popActivePanel(){
|
||||||
|
this.popPanel(this.activePanel, this.activePanelDoc.innerHTML);
|
||||||
|
this.hideActivePanel(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets pinned panel
|
||||||
|
* @param {panelObj} panel - Panel Object to apply to panel
|
||||||
|
* @param {String} panelBody - Raw HTML to inject into panel body, defaults to panel page if null
|
||||||
|
*/
|
||||||
|
async setPinnedPanel(panel, panelBody){
|
||||||
|
//Set pinned panel
|
||||||
|
this.pinnedPanel = panel;
|
||||||
|
|
||||||
|
//Set Title
|
||||||
|
this.pinnedPanelTitle.textContent = this.pinnedPanel.name;
|
||||||
|
|
||||||
|
//Grab panel hypertext content and load it into div
|
||||||
|
this.pinnedPanelDoc.innerHTML = (panelBody == null || panelBody == "") ? await this.pinnedPanel.getPage() : panelBody;
|
||||||
|
|
||||||
|
//Display panel
|
||||||
|
this.pinnedPanelDiv.style.display = "flex";
|
||||||
|
|
||||||
|
//Call panel initialization function
|
||||||
|
this.pinnedPanel.panelDocument = this.pinnedPanelDoc;
|
||||||
|
this.pinnedPanel.docSwitch();
|
||||||
|
|
||||||
|
//Resize to window/content
|
||||||
|
this.pinnedPanelDragger.fixCutoff();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides pinned panel
|
||||||
|
* @param {Event} event - Passed down input event
|
||||||
|
* @param {Boolean} keepAlive - Prevents panel.closer() from running if true
|
||||||
|
*/
|
||||||
|
hidePinnedPanel(event, keepAlive = false){
|
||||||
|
this.pinnedPanelDiv.style.display = "none";
|
||||||
|
|
||||||
|
if(!keepAlive){
|
||||||
|
this.pinnedPanel.closer();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pinnedPanel = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets pinned panel to active
|
||||||
|
*/
|
||||||
|
unpinPanel(){
|
||||||
|
this.setActivePanel(this.pinnedPanel, this.pinnedPanelDoc.innerHTML);
|
||||||
|
this.hidePinnedPanel(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pops pinned panel
|
||||||
|
*/
|
||||||
|
popPinnedPanel(){
|
||||||
|
this.popPanel(this.pinnedPanel, this.pinnedPanelDoc.innerHTML);
|
||||||
|
this.hidePinnedPanel(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pops a new pop-out panel
|
||||||
|
* @param {panelObj} panel - panelObj to apply to the panel
|
||||||
|
* @param {String} panelBody - Raw HTML to inject into panel body, injects panel default if left to null
|
||||||
|
*/
|
||||||
|
popPanel(panel, panelBody){
|
||||||
|
var newPanel = new poppedPanel(panel, panelBody, this)
|
||||||
|
|
||||||
|
this.poppedPanels.push(newPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template Class for other Classes for Objects which represent a single Canopy Panel
|
||||||
|
*/
|
||||||
|
class panelObj{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Panel Object
|
||||||
|
* @param {channel} client - Parent client Management Object
|
||||||
|
* @param {String} name - Panel Name
|
||||||
|
* @param {String} pageURL - Panel Default Page URL
|
||||||
|
* @param {Document} panelDocument - Panel Document
|
||||||
|
*/
|
||||||
|
constructor(client, name = "Placeholder Panel", pageURL = "/panel/placeholder", panelDocument = window.document){
|
||||||
|
/**
|
||||||
|
* Panel Name
|
||||||
|
*/
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Panel Default Page URL
|
||||||
|
*/
|
||||||
|
this.pageURL = pageURL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Panel Document
|
||||||
|
*/
|
||||||
|
this.panelDocument = panelDocument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current root document panel doc lives within
|
||||||
|
*/
|
||||||
|
this.ownerDoc = this.panelDocument.ownerDocument == null ? this.panelDocument : this.panelDocument.ownerDocument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent Client Management object
|
||||||
|
*/
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches panel page from the server
|
||||||
|
* @returns {String} Raw panel doc HTML
|
||||||
|
*/
|
||||||
|
async getPage(){
|
||||||
|
var response = await fetch(this.pageURL,{
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
|
||||||
|
return await response.text();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Document/Panel Changes
|
||||||
|
*/
|
||||||
|
docSwitch(){
|
||||||
|
//Set owner doc
|
||||||
|
this.ownerDoc = this.panelDocument.ownerDocument == null ? this.panelDocument : this.panelDocument.ownerDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called upon panel close/exit
|
||||||
|
*/
|
||||||
|
closer(){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which represents a single instance of a popped-out panel
|
||||||
|
*/
|
||||||
|
class poppedPanel{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Popped Panel Object
|
||||||
|
* @param {panelObj} panel - Panel Object to apply to Popped Panel
|
||||||
|
* @param {String} panelBody - Raw HTML to inject into panel body, defaults to panel page if null
|
||||||
|
* @param {cPanel} cPanel - Parent Canopy Panel Management Object
|
||||||
|
*/
|
||||||
|
constructor(panel, panelBody, cPanel){
|
||||||
|
/**
|
||||||
|
* Panel Object to apply to Popped Panel
|
||||||
|
*/
|
||||||
|
this.panel = panel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw HTML to inject into panel body, defaults to panel page if null
|
||||||
|
*/
|
||||||
|
this.panelBody = panelBody;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Browser Window taken up by the Popped Panel
|
||||||
|
*/
|
||||||
|
this.window = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Popped Panel Container Div
|
||||||
|
*/
|
||||||
|
this.pinnedPanelDiv = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Popped Panel Title
|
||||||
|
*/
|
||||||
|
this.pinnedPanelTitle = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Popped Panel Document Div
|
||||||
|
*/
|
||||||
|
this.pinnedPanelDoc = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Popped Panel Close Icon
|
||||||
|
*/
|
||||||
|
this.pinnedPanelCloseIcon = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent Canopy Panel Management Object
|
||||||
|
*/
|
||||||
|
this.cPanel = cPanel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables this.panel.closer() calls from this.closer()
|
||||||
|
*/
|
||||||
|
this.keepAlive = false;
|
||||||
|
|
||||||
|
//Continue constructor asynchrnously
|
||||||
|
this.asyncConstructor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Continuation of constructor method for asynchronous function calls
|
||||||
|
*/
|
||||||
|
async asyncConstructor(){
|
||||||
|
//Set panel body properly
|
||||||
|
this.panelBody = (this.panelBody == null || this.panelBody == "") ? await this.panel.getPage() : this.panelBody;
|
||||||
|
|
||||||
|
//Pop the panel
|
||||||
|
this.popContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pops/Opens container window upon start
|
||||||
|
*/
|
||||||
|
popContainer(){
|
||||||
|
//Set Window Object
|
||||||
|
this.window = window.open("/panel/popoutContainer","",`menubar=no,height=850,width=600`);
|
||||||
|
this.window.addEventListener("load", this.fillContainer.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills container window with Popped Panel container elements
|
||||||
|
*/
|
||||||
|
fillContainer(){
|
||||||
|
//Set Element Nodes
|
||||||
|
this.panelDiv = this.window.document.querySelector("#cpanel-div");
|
||||||
|
this.panelTitle = this.window.document.querySelector("#cpanel-title");
|
||||||
|
this.panelDoc = this.window.document.querySelector("#cpanel-doc");
|
||||||
|
this.panelPopinIcon = this.window.document.querySelector("#cpanel-popin-icon");
|
||||||
|
this.panelPinIcon = this.window.document.querySelector("#cpanel-pin-icon");
|
||||||
|
|
||||||
|
//Set Window Title
|
||||||
|
this.window.document.title = this.window.document.title.replace("NULL_POPOUT", `${this.panel.name} (${client.channelName})`);
|
||||||
|
|
||||||
|
//Set Panel Content
|
||||||
|
this.panelTitle.innerText = this.panel.name;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines default input-related popped-panel Event Listeners
|
||||||
|
*/
|
||||||
|
setupInput(){
|
||||||
|
this.panelPopinIcon.addEventListener("click", this.unpop.bind(this));
|
||||||
|
this.panelPinIcon.addEventListener("click", this.pin.bind(this));
|
||||||
|
this.window.addEventListener("unload", this.closer.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called upon close/exit of panel
|
||||||
|
*/
|
||||||
|
closer(){
|
||||||
|
if(!this.keepAlive){
|
||||||
|
this.panel.closer();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cPanel.poppedPanels.splice(this.cPanel.poppedPanels.indexOf(this),1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un-pops panel into active-panel slot
|
||||||
|
*/
|
||||||
|
unpop(){
|
||||||
|
//Set active panel
|
||||||
|
this.cPanel.setActivePanel(this.panel, this.panelDoc.innerHTML);
|
||||||
|
|
||||||
|
this.keepAlive = true;
|
||||||
|
|
||||||
|
//Close the popped window
|
||||||
|
this.window.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pins panel next to chat
|
||||||
|
*/
|
||||||
|
pin(){
|
||||||
|
this.cPanel.setPinnedPanel(this.panel, this.panelDoc.innerHTML);
|
||||||
|
|
||||||
|
this.keepAlive = true;
|
||||||
|
|
||||||
|
this.window.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}</code></pre>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<br class="clear">
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script> prettyPrint(); </script>
|
||||||
|
<script src="scripts/linenumber.js"> </script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -202,13 +202,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="channel.html">channel</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="userList.html">userList</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:53 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
2928
www/doc/client/hlsBase.html
Normal file
2928
www/doc/client/hlsBase.html
Normal file
File diff suppressed because it is too large
Load diff
2905
www/doc/client/hlsLiveStreamHandler.html
Normal file
2905
www/doc/client/hlsLiveStreamHandler.html
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -81,13 +81,13 @@ This new codebase intends to solve the following issues with the current CyTube
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="channel.html">channel</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="userList.html">userList</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:53 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
2710
www/doc/client/mediaHandler.html
Normal file
2710
www/doc/client/mediaHandler.html
Normal file
File diff suppressed because it is too large
Load diff
844
www/doc/client/mediaHandler.js.html
Normal file
844
www/doc/client/mediaHandler.js.html
Normal file
|
|
@ -0,0 +1,844 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>JSDoc: Source: mediaHandler.js</title>
|
||||||
|
|
||||||
|
<script src="scripts/prettify/prettify.js"> </script>
|
||||||
|
<script src="scripts/prettify/lang-css.js"> </script>
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
<h1 class="page-title">Source: mediaHandler.js</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<article>
|
||||||
|
<pre class="prettyprint source linenums"><code>/*Canopy - The next generation of stoner streaming software
|
||||||
|
Copyright (C) 2024-2025 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/>.*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Base class for all Canopy Media Handlers
|
||||||
|
*
|
||||||
|
* This is little more than a interface class
|
||||||
|
*/
|
||||||
|
class mediaHandler{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Media Handler object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
* @param {Object} media - De-hydrated media object from server
|
||||||
|
* @param {String} type - Media Handler Source Type
|
||||||
|
*/
|
||||||
|
constructor(client, player, media, type){
|
||||||
|
/**
|
||||||
|
* Parent Client Management Object
|
||||||
|
*/
|
||||||
|
this.client = client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent Canopy Player Object
|
||||||
|
*/
|
||||||
|
this.player = player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Media Handler Source Type
|
||||||
|
*/
|
||||||
|
this.type = type
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Denotes wether a seek call was made by the syncing function
|
||||||
|
*/
|
||||||
|
this.selfAct = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains the last received time stamp
|
||||||
|
*/
|
||||||
|
this.lastTimestamp = 0;
|
||||||
|
|
||||||
|
//Ingest media object from server
|
||||||
|
this.startMedia(media);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ingests media nd starts playback
|
||||||
|
* @param {Object} media - Media object from server
|
||||||
|
*/
|
||||||
|
startMedia(media){
|
||||||
|
//If we properly ingested the media
|
||||||
|
if(this.ingestMedia(media)){
|
||||||
|
//Build the video player
|
||||||
|
this.buildPlayer();
|
||||||
|
|
||||||
|
//Call the start function
|
||||||
|
this.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds video player element
|
||||||
|
*/
|
||||||
|
buildPlayer(){
|
||||||
|
//Reset player lock
|
||||||
|
this.lock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys video player element
|
||||||
|
*/
|
||||||
|
destroyPlayer(){
|
||||||
|
//Null out video property
|
||||||
|
this.video = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ingests media object from server
|
||||||
|
* @param {Object} media - Media object from the server
|
||||||
|
* @returns {Boolean} True upon success
|
||||||
|
*/
|
||||||
|
ingestMedia(media){
|
||||||
|
//Set now playing
|
||||||
|
this.nowPlaying = media;
|
||||||
|
|
||||||
|
//return true to signify success
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts video playback
|
||||||
|
*/
|
||||||
|
start(){
|
||||||
|
this.setVideoTitle(this.nowPlaying.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syncronizes timestamp based on timestamp received from server
|
||||||
|
* @param {Number} timestamp - Current video timestamp in seconds
|
||||||
|
*/
|
||||||
|
sync(timestamp = this.lastTimestamp){
|
||||||
|
//Skip sync calls that won't seek so we don't pointlessly throw selfAct
|
||||||
|
if(timestamp != this.video.currentTime){
|
||||||
|
//Set self act flag
|
||||||
|
this.selfAct = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads media player
|
||||||
|
*/
|
||||||
|
reload(){
|
||||||
|
//Get current timestamp
|
||||||
|
const timestamp = this.video.currentTime;
|
||||||
|
|
||||||
|
//Throw self act flag to make sure we don't un-sync the player
|
||||||
|
this.selfAct = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles media end
|
||||||
|
*/
|
||||||
|
end(){
|
||||||
|
//Null out current media
|
||||||
|
this.nowPlaying = null;
|
||||||
|
|
||||||
|
//Throw self act to prevent unlock on video end
|
||||||
|
this.selfAct = true;
|
||||||
|
|
||||||
|
//Destroy the player
|
||||||
|
this.destroyPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plays video
|
||||||
|
*/
|
||||||
|
play(){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pauses video
|
||||||
|
*/
|
||||||
|
pause(){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles player control lockout
|
||||||
|
* @param {Boolean} lock - Whether or not to lock-out user control of video
|
||||||
|
*/
|
||||||
|
setPlayerLock(lock){
|
||||||
|
//set lock property
|
||||||
|
this.lock = lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates Aspect Ratio of media
|
||||||
|
* @returns {Number} Media Aspect Ratio as Floating Point number
|
||||||
|
*/
|
||||||
|
getRatio(){
|
||||||
|
return 4/3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets current timestamp from video
|
||||||
|
* @returns {Number} Media Timestamp in seconds
|
||||||
|
*/
|
||||||
|
getTimestamp(){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets player title
|
||||||
|
* @param {String} title - Title to set
|
||||||
|
*/
|
||||||
|
setVideoTitle(title){
|
||||||
|
this.player.title.textContent = `Currently Playing: ${title}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called once all video metadata has properly been fetched
|
||||||
|
* @param {Event} event - Event passed down by event handler
|
||||||
|
*/
|
||||||
|
onMetadataLoad(event){
|
||||||
|
//Resize aspect (if locked), since the video doesn't properly report it's resolution until it's been loaded
|
||||||
|
this.client.chatBox.resizeAspect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on media pause
|
||||||
|
* @param {Event} event - Event passed down by event handler
|
||||||
|
*/
|
||||||
|
onPause(event){
|
||||||
|
//If the video was paused out-side of code
|
||||||
|
if(!this.selfAct){
|
||||||
|
this.player.unlockSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selfAct = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on media volume change
|
||||||
|
* @param {Event} event - Event passed down by event handler
|
||||||
|
*/
|
||||||
|
onVolumeChange(event){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on media seek
|
||||||
|
* @param {Event} event - Event passed down by event handler
|
||||||
|
*/
|
||||||
|
onSeek(event){
|
||||||
|
//If the video was seeked out-side of code
|
||||||
|
if(!this.selfAct){
|
||||||
|
this.player.unlockSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
//reset self act flag
|
||||||
|
this.selfAct = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on media buffer
|
||||||
|
* @param {Event} event - Event passed down by event handler
|
||||||
|
*/
|
||||||
|
onBuffer(){
|
||||||
|
this.selfAct = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing basic building blocks for anything that touches a <video> tag
|
||||||
|
* @extends mediaHandler
|
||||||
|
*/
|
||||||
|
class rawFileBase extends mediaHandler{
|
||||||
|
/**
|
||||||
|
* Instantiates a new rawFileBase object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
* @param {Object} media - De-hydrated media object from server
|
||||||
|
* @param {String} type - Media Handler Source Type
|
||||||
|
*/
|
||||||
|
constructor(client, player, media, type){
|
||||||
|
super(client, player, media, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines input-related event listeners
|
||||||
|
*/
|
||||||
|
defineListeners(){
|
||||||
|
//Resize to aspect on metadata load
|
||||||
|
this.video.addEventListener('loadedmetadata', this.onMetadataLoad.bind(this));
|
||||||
|
this.video.addEventListener('volumechange', this.onVolumeChange.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
buildPlayer(){
|
||||||
|
//Create player
|
||||||
|
this.video = document.createElement('video');
|
||||||
|
|
||||||
|
//Enable controls
|
||||||
|
this.video.controls = true;
|
||||||
|
|
||||||
|
//Append it to page
|
||||||
|
this.player.videoContainer.appendChild(this.video);
|
||||||
|
|
||||||
|
//Run derived method
|
||||||
|
super.buildPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyPlayer(){
|
||||||
|
//Stops playback
|
||||||
|
this.video.pause();
|
||||||
|
//Remove player from page
|
||||||
|
this.video.remove();
|
||||||
|
//Run derived method
|
||||||
|
super.destroyPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
reload(){
|
||||||
|
//Call derived method
|
||||||
|
super.reload();
|
||||||
|
|
||||||
|
//Load video from source
|
||||||
|
this.video.load();
|
||||||
|
|
||||||
|
//Set it back to the proper time
|
||||||
|
this.video.currentTime = this.lastTimestamp;
|
||||||
|
|
||||||
|
//Play the video
|
||||||
|
this.video.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
setPlayerLock(lock){
|
||||||
|
//toggle controls
|
||||||
|
this.video.controls = !lock;
|
||||||
|
//Only toggle mute if we're locking, or if we're unlocking after being locked
|
||||||
|
//If this is ran twice without locking we don't want to surprise unmute on the user
|
||||||
|
if(lock || this.lock){
|
||||||
|
//toggle mute
|
||||||
|
this.video.muted = lock;
|
||||||
|
}
|
||||||
|
//toggle looping
|
||||||
|
this.video.loop = lock;
|
||||||
|
|
||||||
|
//Run derived method
|
||||||
|
super.setPlayerLock(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRatio(){
|
||||||
|
return this.video.videoWidth / this.video.videoHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
onVolumeChange(event){
|
||||||
|
//Pull volume from video
|
||||||
|
this.player.volume = this.video.volume;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Off air static 'player'
|
||||||
|
* @extends rawFileBase
|
||||||
|
*/
|
||||||
|
class nullHandler extends rawFileBase{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Null Handler object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
*/
|
||||||
|
constructor(client, player){
|
||||||
|
//Call derived constructor
|
||||||
|
super(client, player, {}, null);
|
||||||
|
|
||||||
|
this.defineListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
defineListeners(){
|
||||||
|
//Run derived method
|
||||||
|
super.defineListeners();
|
||||||
|
|
||||||
|
//Disable right clicking
|
||||||
|
this.video.addEventListener('contextmenu', (e)=>{e.preventDefault()});
|
||||||
|
}
|
||||||
|
|
||||||
|
start(){
|
||||||
|
//call derived start function
|
||||||
|
super.start();
|
||||||
|
|
||||||
|
//Lock the player
|
||||||
|
this.setPlayerLock(true);
|
||||||
|
|
||||||
|
//Set the static placeholder
|
||||||
|
this.video.src = '/video/static.webm';
|
||||||
|
|
||||||
|
//play the placeholder video
|
||||||
|
this.video.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
setVideoTitle(title){
|
||||||
|
this.player.title.textContent = `Channel Off Air`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic building blocks needed for proper time-synchronized raw-file playback
|
||||||
|
* @extends rawFileBase
|
||||||
|
*/
|
||||||
|
class rawFileHandler extends rawFileBase{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Null Handler object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
* @param {Object} media - De-hydrated media object from server
|
||||||
|
*/
|
||||||
|
constructor(client, player, media){
|
||||||
|
//Call derived constructor
|
||||||
|
super(client, player, media, 'raw');
|
||||||
|
|
||||||
|
//Define listeners
|
||||||
|
this.defineListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
defineListeners(){
|
||||||
|
//Run derived method
|
||||||
|
super.defineListeners();
|
||||||
|
|
||||||
|
this.video.addEventListener('pause', this.onPause.bind(this));
|
||||||
|
this.video.addEventListener('seeked', this.onSeek.bind(this));
|
||||||
|
this.video.addEventListener('waiting', this.onBuffer.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
start(){
|
||||||
|
//Call derived start
|
||||||
|
super.start();
|
||||||
|
|
||||||
|
//Set video
|
||||||
|
this.video.src = this.nowPlaying.rawLink;
|
||||||
|
|
||||||
|
//Set video volume
|
||||||
|
this.video.volume = this.player.volume;
|
||||||
|
|
||||||
|
//Unlock player
|
||||||
|
this.setPlayerLock(false);
|
||||||
|
|
||||||
|
//play video
|
||||||
|
this.video.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
play(){
|
||||||
|
this.video.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
pause(){
|
||||||
|
this.video.pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
sync(timestamp = this.lastTimestamp){
|
||||||
|
//Call derived sync
|
||||||
|
super.sync(timestamp);
|
||||||
|
|
||||||
|
//Skip sync calls that won't seek so we don't pointlessly throw selfAct
|
||||||
|
if(timestamp != this.video.currentTime){
|
||||||
|
//Set current video time based on timestamp received from server
|
||||||
|
this.video.currentTime = timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getTimestamp(){
|
||||||
|
//Return current timestamp
|
||||||
|
return this.video.currentTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Youtube playback via the official YT embed (gross)
|
||||||
|
* @extends mediaHandler
|
||||||
|
*/
|
||||||
|
class youtubeEmbedHandler extends mediaHandler{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Youtube Embed Handler object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
* @param {Object} media - De-hydrated media object from server
|
||||||
|
*/
|
||||||
|
constructor(client, player, media){
|
||||||
|
//Call derived constructor
|
||||||
|
super(client, player, media, 'ytEmbed');
|
||||||
|
|
||||||
|
//Set flag to notify functions when the player is actually ready
|
||||||
|
this.ready = false;
|
||||||
|
|
||||||
|
//Create property to hold video iframe for easy access
|
||||||
|
this.iframe = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//custom start media function since we want the youtube player to call the start function once it's ready
|
||||||
|
startMedia(media){
|
||||||
|
//If we properly ingested the media
|
||||||
|
if(this.ingestMedia(media)){
|
||||||
|
//Build the video player
|
||||||
|
this.buildPlayer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildPlayer(){
|
||||||
|
//If the embed API hasn't loaded
|
||||||
|
if(!this.client.ytEmbedAPILoaded){
|
||||||
|
//Complain and stop
|
||||||
|
return console.warn("youtubeEmbedHandler.buildPlayer() Called before YT Iframe API Loaded, waiting on refresh to rebuild...");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create temp div for yt api to replace
|
||||||
|
const tempDiv = document.createElement('div');
|
||||||
|
//Name the div
|
||||||
|
tempDiv.id = "youtube-embed-player"
|
||||||
|
//Append it to the video container
|
||||||
|
this.player.videoContainer.appendChild(tempDiv);
|
||||||
|
|
||||||
|
//Create a new youtube player using the official YT iframe-embed api
|
||||||
|
this.video = new YT.Player('youtube-embed-player', {
|
||||||
|
//Inject video id
|
||||||
|
videoId: this.nowPlaying.id,
|
||||||
|
events: {
|
||||||
|
'onReady': this.start.bind(this),
|
||||||
|
'onStateChange': this.onStateChange.bind(this)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Call derived function
|
||||||
|
super.buildPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
start(){
|
||||||
|
//Call derived start function
|
||||||
|
super.start();
|
||||||
|
|
||||||
|
//Set volume based on player volume
|
||||||
|
this.video.setVolume(this.player.volume * 100);
|
||||||
|
|
||||||
|
//Kick the video off
|
||||||
|
this.video.playVideo();
|
||||||
|
|
||||||
|
//Pull iframe
|
||||||
|
this.iframe = this.video.getIframe()
|
||||||
|
|
||||||
|
//Throw the ready flag
|
||||||
|
this.ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyPlayer(){
|
||||||
|
//If we've had enough time to create a player frame
|
||||||
|
if(this.ready){
|
||||||
|
//Pull volume from player before destroying since google didn't give us a volume change event like a bunch of dicks
|
||||||
|
this.player.volume = (this.video.getVolume() / 100);
|
||||||
|
|
||||||
|
//Use the embed api's built in destroy function
|
||||||
|
this.video.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check the f̶r̶i̶d̶g̶e video container for leftovers
|
||||||
|
const leftovers = this.player.videoContainer.querySelector("#youtube-embed-player");
|
||||||
|
|
||||||
|
//If we have any leftovers
|
||||||
|
if(leftovers != null){
|
||||||
|
//Nukem like last nights chicken
|
||||||
|
leftovers.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Call derived destroy function
|
||||||
|
super.destroyPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
sync(timestamp = this.lastTimestamp){
|
||||||
|
//If we're not ready
|
||||||
|
if(!this.ready){
|
||||||
|
//Kick off a timer to wait it out and try again l8r
|
||||||
|
setTimeout(this.sync.bind(this), 100);
|
||||||
|
|
||||||
|
//If it failed, tell randy to fuck off
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Seek to timestamp, allow buffering
|
||||||
|
this.video.seekTo(timestamp, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
reload(){
|
||||||
|
//if we're ready
|
||||||
|
if(this.ready){
|
||||||
|
//re-load the video by id
|
||||||
|
this.video.loadVideoById(this.nowPlaying.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
play(){
|
||||||
|
//If we're ready
|
||||||
|
if(this.ready){
|
||||||
|
//play the video
|
||||||
|
this.video.playVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pause(){
|
||||||
|
//If we're ready
|
||||||
|
if(this.ready){
|
||||||
|
//pause the video
|
||||||
|
this.video.pauseVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getRatio(){
|
||||||
|
//TODO: Implement a type-specific metadata property object in the media class to hold type-sepecifc meta-data
|
||||||
|
//Alternatively we could fill in resolution information from the raw link
|
||||||
|
//However keeping embedded functionality dependant on raw-links seems like bad practice
|
||||||
|
}
|
||||||
|
|
||||||
|
getTimestamp(){
|
||||||
|
//If we're ready
|
||||||
|
if(this.ready){
|
||||||
|
//Return the timestamp
|
||||||
|
return this.video.getCurrentTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we fall through, simply report that the video hasn't gone anywhere yet
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
setVideoTitle(){
|
||||||
|
//Clear out the player title so that youtube's baked in title can do it's thing.
|
||||||
|
//This will be replaced once we complete the full player control and remove the defualt youtube UI
|
||||||
|
this.player.title.textContent = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic handler for state changes since google is a dick
|
||||||
|
*/
|
||||||
|
onStateChange(event){
|
||||||
|
switch(event.data){
|
||||||
|
//video unstarted
|
||||||
|
case -1:
|
||||||
|
return;
|
||||||
|
//video ended
|
||||||
|
case 0:
|
||||||
|
return;
|
||||||
|
//video playing
|
||||||
|
case 1:
|
||||||
|
return;
|
||||||
|
//video paused
|
||||||
|
case 2:
|
||||||
|
super.onPause(event);
|
||||||
|
return;
|
||||||
|
//video buffering
|
||||||
|
case 3:
|
||||||
|
//There is no good way to tell slow connections apart from user seeking
|
||||||
|
//This will be easier to implement once we get custom player controls up
|
||||||
|
//super.onSeek(event);
|
||||||
|
return;
|
||||||
|
//video queued
|
||||||
|
case 5:
|
||||||
|
return;
|
||||||
|
//bad status code
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setPlayerLock(lock){
|
||||||
|
super.setPlayerLock(lock);
|
||||||
|
|
||||||
|
if(this.ready){
|
||||||
|
this.iframe.style.pointerEvents = (lock ? "none" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base HLS Media handler for handling all HLS related media
|
||||||
|
* @extends rawFileBase
|
||||||
|
*/
|
||||||
|
class hlsBase extends rawFileBase{
|
||||||
|
/**
|
||||||
|
* Instantiates a new HLS Base object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
* @param {Object} media - De-hydrated media object from server
|
||||||
|
* @param {String} type - Media Handler Source Type
|
||||||
|
*/
|
||||||
|
constructor(client, player, media, type){
|
||||||
|
//Call derived constructor
|
||||||
|
super(client, player, media, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
buildPlayer(){
|
||||||
|
//Call derived buildPlayer function
|
||||||
|
super.buildPlayer();
|
||||||
|
|
||||||
|
//Instantiate HLS object
|
||||||
|
this.hls = new Hls();
|
||||||
|
|
||||||
|
//Load HLS Stream
|
||||||
|
this.hls.loadSource(this.nowPlaying.url);
|
||||||
|
|
||||||
|
//Attatch hls object to video element
|
||||||
|
this.hls.attachMedia(this.video);
|
||||||
|
|
||||||
|
//Bind onMetadataLoad to MANIFEST_PARSED
|
||||||
|
this.hls.on(Hls.Events.MANIFEST_PARSED, this.onMetadataLoad.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
end(){
|
||||||
|
//Stop hls.js from loading any more of the stream
|
||||||
|
this.hls.stopLoad();
|
||||||
|
|
||||||
|
//Call derived method
|
||||||
|
super.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMetadataLoad(){
|
||||||
|
//Call derived method
|
||||||
|
super.onMetadataLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
start(){
|
||||||
|
//Call derived method
|
||||||
|
super.start();
|
||||||
|
|
||||||
|
//Start the video
|
||||||
|
this.video.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HLS Livestream Handler
|
||||||
|
* @extends hlsBase
|
||||||
|
*/
|
||||||
|
class hlsLiveStreamHandler extends hlsBase{
|
||||||
|
/**
|
||||||
|
* Instantiates a new HLS Live Stream Handler object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
* @param {Object} media - De-hydrated media object from server
|
||||||
|
*/
|
||||||
|
constructor(client, player, media){
|
||||||
|
//Call derived constructor
|
||||||
|
super(client, player, media, "livehls");
|
||||||
|
|
||||||
|
//Create variable to determine if we need to resync after next seek
|
||||||
|
this.reSync = false;
|
||||||
|
|
||||||
|
this.video.addEventListener('pause', this.onPause.bind(this));
|
||||||
|
this.video.addEventListener('seeked', this.onSeek.bind(this));
|
||||||
|
this.video.addEventListener('waiting', this.onBuffer.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
sync(){
|
||||||
|
//Kick the video back on if it was paused
|
||||||
|
this.video.play();
|
||||||
|
|
||||||
|
//Pull video duration
|
||||||
|
const duration = this.video.duration;
|
||||||
|
|
||||||
|
//Ignore bad timestamps
|
||||||
|
if(duration > 0){
|
||||||
|
//Seek to the end to sync up w/ the livestream
|
||||||
|
this.video.currentTime = duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setVideoTitle(title){
|
||||||
|
//Add title as text content for security :P
|
||||||
|
this.player.title.textContent = `: ${title}`;
|
||||||
|
|
||||||
|
//Create glow span
|
||||||
|
const glowSpan = document.createElement('span');
|
||||||
|
//Fill glow span content
|
||||||
|
glowSpan.textContent = "🔴LIVE";
|
||||||
|
//Set glowspan class
|
||||||
|
glowSpan.classList.add('critical-danger-text');
|
||||||
|
|
||||||
|
//Inject glowspan into title in a way that allows it to be easily replaced
|
||||||
|
this.player.title.prepend(glowSpan);
|
||||||
|
}
|
||||||
|
|
||||||
|
onBuffer(event){
|
||||||
|
//Call derived function
|
||||||
|
super.onBuffer(event);
|
||||||
|
|
||||||
|
|
||||||
|
//If we're synced by the end of buffering
|
||||||
|
if(this.player.syncLock){
|
||||||
|
//Throw flag to manually sync since this works entirely differently from literally every other fucking media source
|
||||||
|
this.reSync = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSeek(event){
|
||||||
|
//Call derived method
|
||||||
|
super.onSeek(event);
|
||||||
|
|
||||||
|
//If we stopped playing the video
|
||||||
|
if(this.video == null){
|
||||||
|
//Don't worry about it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Calculate distance to end of stream
|
||||||
|
const difference = this.video.duration - this.video.currentTime;
|
||||||
|
|
||||||
|
//If we where buffering under sync lock
|
||||||
|
if(this.reSync){
|
||||||
|
//Set reSync to false
|
||||||
|
this.reSync = false;
|
||||||
|
|
||||||
|
//If the difference is bigger than streamSyncTolerance
|
||||||
|
if(difference > this.player.streamSyncTolerance){
|
||||||
|
//Sync manually since we have no timestamp, and therefore the player won't do it for us
|
||||||
|
this.sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}</code></pre>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<br class="clear">
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script> prettyPrint(); </script>
|
||||||
|
<script src="scripts/linenumber.js"> </script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
2882
www/doc/client/nullHandler.html
Normal file
2882
www/doc/client/nullHandler.html
Normal file
File diff suppressed because it is too large
Load diff
918
www/doc/client/panelObj.html
Normal file
918
www/doc/client/panelObj.html
Normal file
|
|
@ -0,0 +1,918 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>JSDoc: Class: panelObj</title>
|
||||||
|
|
||||||
|
<script src="scripts/prettify/prettify.js"> </script>
|
||||||
|
<script src="scripts/prettify/lang-css.js"> </script>
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
<h1 class="page-title">Class: panelObj</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section>
|
||||||
|
|
||||||
|
<header>
|
||||||
|
|
||||||
|
<h2><span class="attribs"><span class="type-signature"></span></span>panelObj<span class="signature">(client, name, pageURL, panelDocument)</span><span class="type-signature"></span></h2>
|
||||||
|
|
||||||
|
<div class="class-description">Template Class for other Classes for Objects which represent a single Canopy Panel</div>
|
||||||
|
|
||||||
|
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<div class="container-overview">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Constructor</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="panelObj"><span class="type-signature"></span>new panelObj<span class="signature">(client, name, pageURL, panelDocument)</span><span class="type-signature"></span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Instantiates a new Panel Object
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h5>Parameters:</h5>
|
||||||
|
|
||||||
|
|
||||||
|
<table class="params">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<th>Name</th>
|
||||||
|
|
||||||
|
|
||||||
|
<th>Type</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<th>Default</th>
|
||||||
|
|
||||||
|
|
||||||
|
<th class="last">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td class="name"><code>client</code></td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="type">
|
||||||
|
|
||||||
|
|
||||||
|
<span class="param-type"><a href="channel.html">channel</a></span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="default">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="description last">Parent client Management Object</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td class="name"><code>name</code></td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="type">
|
||||||
|
|
||||||
|
|
||||||
|
<span class="param-type">String</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="default">
|
||||||
|
|
||||||
|
Placeholder Panel
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="description last">Panel Name</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td class="name"><code>pageURL</code></td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="type">
|
||||||
|
|
||||||
|
|
||||||
|
<span class="param-type">String</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="default">
|
||||||
|
|
||||||
|
/panel/placeholder
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="description last">Panel Default Page URL</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td class="name"><code>panelDocument</code></td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="type">
|
||||||
|
|
||||||
|
|
||||||
|
<span class="param-type">Document</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="default">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="description last">Panel Document</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="cpanel.js.html">cpanel.js</a>, <a href="cpanel.js.html#line263">line 263</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="subsection-title">Members</h3>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="client"><span class="type-signature"></span>client<span class="type-signature"></span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Parent Client Management object
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="cpanel.js.html">cpanel.js</a>, <a href="cpanel.js.html#line295">line 295</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="name"><span class="type-signature"></span>name<span class="type-signature"></span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Panel Name
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="cpanel.js.html">cpanel.js</a>, <a href="cpanel.js.html#line275">line 275</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="ownerDoc"><span class="type-signature"></span>ownerDoc<span class="type-signature"></span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Current root document panel doc lives within
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="cpanel.js.html">cpanel.js</a>, <a href="cpanel.js.html#line290">line 290</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="pageURL"><span class="type-signature"></span>pageURL<span class="type-signature"></span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Panel Default Page URL
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="cpanel.js.html">cpanel.js</a>, <a href="cpanel.js.html#line280">line 280</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="panelDocument"><span class="type-signature"></span>panelDocument<span class="type-signature"></span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Panel Document
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="cpanel.js.html">cpanel.js</a>, <a href="cpanel.js.html#line285">line 285</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="subsection-title">Methods</h3>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="closer"><span class="type-signature"></span>closer<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Called upon panel close/exit
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="cpanel.js.html">cpanel.js</a>, <a href="cpanel.js.html#line321">line 321</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="docSwitch"><span class="type-signature"></span>docSwitch<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Handles Document/Panel Changes
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="cpanel.js.html">cpanel.js</a>, <a href="cpanel.js.html#line313">line 313</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="getPage"><span class="type-signature">(async) </span>getPage<span class="signature">()</span><span class="type-signature"> → {String}</span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Fetches panel page from the server
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="cpanel.js.html">cpanel.js</a>, <a href="cpanel.js.html#line302">line 302</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h5>Returns:</h5>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="param-desc">
|
||||||
|
Raw panel doc HTML
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>
|
||||||
|
Type
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<span class="param-type">String</span>
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</article>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<br class="clear">
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script> prettyPrint(); </script>
|
||||||
|
<script src="scripts/linenumber.js"> </script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
3383
www/doc/client/player.html
Normal file
3383
www/doc/client/player.html
Normal file
File diff suppressed because it is too large
Load diff
483
www/doc/client/player.js.html
Normal file
483
www/doc/client/player.js.html
Normal file
|
|
@ -0,0 +1,483 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>JSDoc: Source: player.js</title>
|
||||||
|
|
||||||
|
<script src="scripts/prettify/prettify.js"> </script>
|
||||||
|
<script src="scripts/prettify/lang-css.js"> </script>
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
<h1 class="page-title">Source: player.js</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<article>
|
||||||
|
<pre class="prettyprint source linenums"><code>/*Canopy - The next generation of stoner streaming software
|
||||||
|
Copyright (C) 2024-2025 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/>.*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which represents Canopy Player UX
|
||||||
|
*/
|
||||||
|
class player{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Canopy Player object
|
||||||
|
* @param {channel} client - Parent client Management Object
|
||||||
|
*/
|
||||||
|
constructor (client){
|
||||||
|
/**
|
||||||
|
* Parent CLient Management Object
|
||||||
|
*/
|
||||||
|
this.client = client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the mouse cursor is floating over player UX
|
||||||
|
*/
|
||||||
|
this.onUI = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not player scrub is locked to sync signal from the server
|
||||||
|
*/
|
||||||
|
this.syncLock = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player UX Stow-Away timer
|
||||||
|
*/
|
||||||
|
this.uiTimer = setTimeout(this.toggleUI.bind(this), 1500, false);
|
||||||
|
|
||||||
|
//elements
|
||||||
|
/**
|
||||||
|
* Top-Level Player Container Div
|
||||||
|
*/
|
||||||
|
this.playerDiv = document.querySelector("#media-panel-div");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player Element Container Div
|
||||||
|
*/
|
||||||
|
this.videoContainer = document.querySelector("#media-panel-video-container")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page Nav-Par
|
||||||
|
*/
|
||||||
|
this.navBar = document.querySelector("#navbar");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-Hiding Player UI
|
||||||
|
*/
|
||||||
|
this.uiBar = document.querySelector("#media-panel-head-div");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player Title Label
|
||||||
|
*/
|
||||||
|
this.title = document.querySelector("#media-panel-title-paragraph");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player Show Video Icon
|
||||||
|
*/
|
||||||
|
this.showVideoIcon = document.querySelector("#chat-panel-show-video-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player Hide Video Icon
|
||||||
|
*/
|
||||||
|
this.hideVideoIcon = document.querySelector("#media-panel-div-toggle-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player Syncronization Icon
|
||||||
|
*/
|
||||||
|
this.syncIcon = document.querySelector("#media-panel-sync-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player Cinema-Mode Icon
|
||||||
|
*/
|
||||||
|
this.cinemaModeIcon = document.querySelector("#media-panel-cinema-mode-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player Filp Video Y Icon
|
||||||
|
*/
|
||||||
|
this.flipYIcon = document.querySelector("#media-panel-flip-vertical-icon")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player Flip Video X Icon
|
||||||
|
*/
|
||||||
|
this.flipXIcon = document.querySelector("#media-panel-flip-horizontal-icon")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player Media Reload Icon
|
||||||
|
*/
|
||||||
|
this.reloadIcon = document.querySelector("#media-panel-reload-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tolerance between timestamp from server and actual media before corrective seek for pre-recorded media
|
||||||
|
*/
|
||||||
|
this.syncTolerance = 0.4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tolerance in livestream delay before corrective seek to live.
|
||||||
|
*
|
||||||
|
* Might seem weird to keep this here instead of the HLS handler, but remember we may want to support other livestream services in the future...
|
||||||
|
*/
|
||||||
|
this.streamSyncTolerance = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forced time to wait between sync checks, heavily decreases chance of seek-banging without reducing syncornization accuracy
|
||||||
|
*/
|
||||||
|
this.syncDelta = 6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current Player Volume
|
||||||
|
*/
|
||||||
|
this.volume = 1;
|
||||||
|
|
||||||
|
//run setup functions
|
||||||
|
this.setupInput();
|
||||||
|
this.defineListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines Input-Related Event Listeners for the player
|
||||||
|
*/
|
||||||
|
setupInput(){
|
||||||
|
//UIBar Movement Detection
|
||||||
|
this.playerDiv.addEventListener("mousemove", this.popUI.bind(this));
|
||||||
|
this.uiBar.addEventListener("mouseenter", ()=>{this.setOnUI(true)});
|
||||||
|
this.uiBar.addEventListener("mouseleave", ()=>{this.setOnUI(false)});
|
||||||
|
|
||||||
|
//UIBar/header icons
|
||||||
|
//Don't bind these, they want an argument that isn't an event :P
|
||||||
|
this.showVideoIcon.addEventListener("click", ()=>{this.toggleVideo()});
|
||||||
|
this.hideVideoIcon.addEventListener("click", ()=>{this.toggleVideo()});
|
||||||
|
this.syncIcon.addEventListener("click", this.lockSync.bind(this));
|
||||||
|
this.cinemaModeIcon.addEventListener("click", ()=>{this.toggleCinemaMode()});
|
||||||
|
this.flipYIcon.addEventListener('click', this.flipY.bind(this));
|
||||||
|
this.flipXIcon.addEventListener('click', this.flipX.bind(this));
|
||||||
|
this.reloadIcon.addEventListener("click", this.reload.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define Network-Related Event Listeners for the player
|
||||||
|
*/
|
||||||
|
defineListeners(){
|
||||||
|
this.client.socket.on("start", this.start.bind(this));
|
||||||
|
this.client.socket.on("sync", this.sync.bind(this));
|
||||||
|
this.client.socket.on("end", this.end.bind(this));
|
||||||
|
this.client.socket.on("updateCurrentRawFile", this.updateCurrentRawFile.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles command from server to start media
|
||||||
|
* @param {Object} data - Media Metadata from server
|
||||||
|
*/
|
||||||
|
start(data){
|
||||||
|
//If we have an active media handler
|
||||||
|
if(this.mediaHandler != null){
|
||||||
|
//End the media handler
|
||||||
|
this.mediaHandler.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Ignore null media
|
||||||
|
if(data.media == null){
|
||||||
|
//Set null handler
|
||||||
|
this.mediaHandler = new nullHandler(client, this);
|
||||||
|
//Otherwise
|
||||||
|
}else{
|
||||||
|
//If we have a youtube video and the official embedded iframe player is selected
|
||||||
|
if(data.media.type == 'yt' && localStorage.getItem("ytPlayerType") == 'embed'){
|
||||||
|
//Create a new yt handler for it
|
||||||
|
this.mediaHandler = new youtubeEmbedHandler(this.client, this, data.media);
|
||||||
|
//Sync to time stamp
|
||||||
|
this.mediaHandler.sync(data.timestamp);
|
||||||
|
//If we have an HLS Livestream
|
||||||
|
}else if(data.media.type == "livehls"){
|
||||||
|
//Create a new HLS Livestream Handler for it
|
||||||
|
this.mediaHandler = new hlsLiveStreamHandler(this.client, this, data.media);
|
||||||
|
}else if(data.media.type == 'dm'){
|
||||||
|
this.mediaHandler = new hlsDailymotionHandler(this.client, this, data.media);
|
||||||
|
//Otherwise, if we have a raw-file compatible source
|
||||||
|
}else if(data.media.type == 'ia' || data.media.type == 'raw' || data.media.type == 'yt' || data.media.type == 'dm'){
|
||||||
|
//Create a new raw file handler for it
|
||||||
|
this.mediaHandler = new rawFileHandler(client, this, data.media);
|
||||||
|
//Sync to time stamp
|
||||||
|
this.mediaHandler.sync(data.timestamp);
|
||||||
|
}else{
|
||||||
|
this.mediaHandler = new nullHandler(client, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Lock synchronization since everyone starts at 0, and update the UI
|
||||||
|
this.lockSync();
|
||||||
|
|
||||||
|
//Re-size to aspect since video may now be a different size
|
||||||
|
this.client.chatBox.resizeAspect();
|
||||||
|
|
||||||
|
//Sync off of starter time stamp
|
||||||
|
this.mediaHandler.sync(data.timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles synchronization command from server
|
||||||
|
* @param {Object} data - Syncrhonization Data from Server
|
||||||
|
*/
|
||||||
|
sync(data){
|
||||||
|
if(this.mediaHandler != null){
|
||||||
|
//Get timestamp
|
||||||
|
const timestamp = data.timestamp;
|
||||||
|
//Get difference between server and local timestamp
|
||||||
|
const difference = Math.abs(timestamp - this.mediaHandler.getTimestamp());
|
||||||
|
|
||||||
|
//Check if timestamp evenly devides into sync delta, effectively only checking for sync every X seconds
|
||||||
|
//Check if the difference between timestamps is larger than the sync tolerance
|
||||||
|
//Lastly, check to make sure we have sync lock
|
||||||
|
if(timestamp % this.syncDelta == 0 && difference > this.syncTolerance && this.syncLock){
|
||||||
|
//If we need to sync, then sync the video!
|
||||||
|
this.mediaHandler.sync(timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Collect last timestamp
|
||||||
|
this.mediaHandler.lastTimestamp = timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads the media player
|
||||||
|
*/
|
||||||
|
reload(){
|
||||||
|
if(this.mediaHandler != null){
|
||||||
|
this.mediaHandler.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles End-Media Commands from the Server
|
||||||
|
*/
|
||||||
|
end(){
|
||||||
|
//Call the media handler finisher
|
||||||
|
this.mediaHandler.end();
|
||||||
|
|
||||||
|
//Replace it with a null handler
|
||||||
|
this.mediaHandler = new nullHandler(client, this);
|
||||||
|
|
||||||
|
//Re-lock sync since we're probably gonna start new media soon anywho, and we need to update the UI anywho
|
||||||
|
this.lockSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Raw-File Metadata Updates from the Server
|
||||||
|
* @param {Object} data - Updadated Raw-File link from Server
|
||||||
|
*/
|
||||||
|
updateCurrentRawFile(data){
|
||||||
|
//typecheck the media handler to see if we really need to do any of this shit, if not...
|
||||||
|
if(this.mediaHandler.type == 'ytEmbed'){
|
||||||
|
//Ignore it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Grab current item from media handler
|
||||||
|
const currentItem = this.mediaHandler.nowPlaying;
|
||||||
|
|
||||||
|
//Update raw link
|
||||||
|
currentItem.rawLink = data.file;
|
||||||
|
|
||||||
|
//Re-start the item
|
||||||
|
this.start({media: currentItem});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locks player seek to synced timestamp from the server
|
||||||
|
*/
|
||||||
|
lockSync(){
|
||||||
|
//Enable syncing
|
||||||
|
this.syncLock = true;
|
||||||
|
|
||||||
|
if(this.mediaHandler != null && this.mediaHandler.type != null){
|
||||||
|
//Light up the sync icon to show that we're actively synchronized
|
||||||
|
this.syncIcon.classList.add('positive');
|
||||||
|
|
||||||
|
//Sync to last timestamp
|
||||||
|
this.mediaHandler.sync();
|
||||||
|
|
||||||
|
//Play
|
||||||
|
this.mediaHandler.play();
|
||||||
|
}else{
|
||||||
|
//Unlight the sync icon since there is nothing to sync
|
||||||
|
this.syncIcon.classList.remove('positive');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un-locks player seek to synced timestamp from the server
|
||||||
|
*/
|
||||||
|
unlockSync(){
|
||||||
|
//Unlight the sync icon since we're no longer actively synced
|
||||||
|
this.syncIcon.classList.remove('positive');
|
||||||
|
|
||||||
|
//Disable syncing
|
||||||
|
this.syncLock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flips the video horizontally
|
||||||
|
*/
|
||||||
|
flipX(){
|
||||||
|
//I'm lazy
|
||||||
|
const transform = this.videoContainer.style.transform;
|
||||||
|
|
||||||
|
//If we we're specifically set to un-mirrored
|
||||||
|
if(transform.match("scaleX(1)")){
|
||||||
|
//mirror it
|
||||||
|
this.videoContainer.style.transfrom = transform.replace('scaleX(1)', 'scaleX(-1)');
|
||||||
|
//If we're currently mirrored
|
||||||
|
}else if(transform.match("scaleX(-1)")){
|
||||||
|
//Un-mirror
|
||||||
|
this.videoContainer.style.transfrom = transform.replace('scaleX(-1)', 'scaleX(1)');
|
||||||
|
//Otherwise, if it's untouched
|
||||||
|
}else{
|
||||||
|
//Mirror it
|
||||||
|
this.videoContainer.style.transform += 'scaleX(-1)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flips the video vertically
|
||||||
|
*/
|
||||||
|
flipY(){
|
||||||
|
//I'm lazy
|
||||||
|
const transform = this.videoContainer.style.transform;
|
||||||
|
|
||||||
|
//If we we're specifically set to un-mirrored
|
||||||
|
if(transform.match("scaleY(1)")){
|
||||||
|
//mirror it
|
||||||
|
this.videoContainer.style.transfrom = transform.replace('scaleY(1)', 'scaleY(-1)');
|
||||||
|
//If we're currently mirrored
|
||||||
|
}else if(transform.match("scaleY(-1)")){
|
||||||
|
//Un-mirror
|
||||||
|
this.videoContainer.style.transfrom = transform.replace('scaleY(-1)', 'scaleY(1)');
|
||||||
|
//Otherwise, if it's untouched
|
||||||
|
}else{
|
||||||
|
//Mirror it
|
||||||
|
this.videoContainer.style.transform += 'scaleY(-1)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays UI after player-related input
|
||||||
|
* @param {Event} event - Event passed through by event handler
|
||||||
|
*/
|
||||||
|
popUI(event){
|
||||||
|
this.toggleUI(true);
|
||||||
|
clearTimeout(this.uiTimer);
|
||||||
|
if(!this.onUI){
|
||||||
|
this.uiTimer = setTimeout(this.toggleUI.bind(this), 1500, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles UI-Bar on or off
|
||||||
|
* @param {Boolean} show - Whether or not to show the UI-Bar. Defaults to toggle if left unspecified.
|
||||||
|
*/
|
||||||
|
toggleUI(show = this.uiBar.style.display == "none"){
|
||||||
|
this.uiBar.style.display = show ? "flex" : "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles video on or off
|
||||||
|
* @param {Boolean} show - Whether or not to show the video player. Defaults to toggle if left unspecified
|
||||||
|
*/
|
||||||
|
toggleVideo(show = !this.playerDiv.checkVisibility()){
|
||||||
|
if(show){
|
||||||
|
this.playerDiv.style.display = "flex";
|
||||||
|
this.showVideoIcon.style.display = "none";
|
||||||
|
}else{
|
||||||
|
this.playerDiv.style.display = "none";
|
||||||
|
this.showVideoIcon.style.display = "flex";
|
||||||
|
}
|
||||||
|
|
||||||
|
//Tell chatbox to handle this shit
|
||||||
|
this.client.chatBox.handleVideoToggle(show);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles Cinema Mode on or off
|
||||||
|
* @param {Boolean} cinema - Whether or not to enter Cinema Mode. Defaults to toggle if left unspecified
|
||||||
|
*/
|
||||||
|
toggleCinemaMode(cinema = !this.navBar.checkVisibility()){
|
||||||
|
if(cinema){
|
||||||
|
this.navBar.style.display = "flex";
|
||||||
|
}else{
|
||||||
|
this.navBar.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
//Resize the video if we're aspect locked
|
||||||
|
this.client.chatBox.resizeAspect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs the class when the user's mouse curosr enters and leaves the UI area
|
||||||
|
* @param {Boolean} onUI - Whether or not onUI should be toggled true
|
||||||
|
*/
|
||||||
|
setOnUI(onUI){
|
||||||
|
this.onUI = onUI;
|
||||||
|
this.popUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates ratio of current media object
|
||||||
|
* @returns {Number} Current media aspect ratio as a single floating point number
|
||||||
|
*/
|
||||||
|
getRatio(){
|
||||||
|
//If we have no media handler
|
||||||
|
if(this.mediaHandler == null){
|
||||||
|
//Return a 4/3 aspect to get a decent chat size
|
||||||
|
return 4/3;
|
||||||
|
}else{
|
||||||
|
return this.mediaHandler.getRatio();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}</code></pre>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<br class="clear">
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script> prettyPrint(); </script>
|
||||||
|
<script src="scripts/linenumber.js"> </script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1451
www/doc/client/poppedPanel.html
Normal file
1451
www/doc/client/poppedPanel.html
Normal file
File diff suppressed because it is too large
Load diff
2923
www/doc/client/rawFileBase.html
Normal file
2923
www/doc/client/rawFileBase.html
Normal file
File diff suppressed because it is too large
Load diff
2905
www/doc/client/rawFileHandler.html
Normal file
2905
www/doc/client/rawFileHandler.html
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
<h2><span class="attribs"><span class="type-signature"></span></span>userList<span class="signature">(client)</span><span class="type-signature"></span></h2>
|
<h2><span class="attribs"><span class="type-signature"></span></span>userList<span class="signature">(client)</span><span class="type-signature"></span></h2>
|
||||||
|
|
||||||
<div class="class-description">Class for object containing logic behind userlist UX</div>
|
<div class="class-description">Class containing logic behind userlist UX</div>
|
||||||
|
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
|
|
@ -1185,13 +1185,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="channel.html">channel</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="userList.html">userList</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:53 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ 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/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for object containing logic behind userlist UX
|
* Class containing logic behind userlist UX
|
||||||
*/
|
*/
|
||||||
class userList{
|
class userList{
|
||||||
/**
|
/**
|
||||||
|
|
@ -246,13 +246,13 @@ class userList{
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="channel.html">channel</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="userList.html">userList</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="cPanel.html">cPanel</a></li><li><a href="channel.html">channel</a></li><li><a href="chatBox.html">chatBox</a></li><li><a href="chatPostprocessor.html">chatPostprocessor</a></li><li><a href="commandPreprocessor.html">commandPreprocessor</a></li><li><a href="commandProcessor.html">commandProcessor</a></li><li><a href="hlsBase.html">hlsBase</a></li><li><a href="hlsLiveStreamHandler.html">hlsLiveStreamHandler</a></li><li><a href="mediaHandler.html">mediaHandler</a></li><li><a href="nullHandler.html">nullHandler</a></li><li><a href="panelObj.html">panelObj</a></li><li><a href="player.html">player</a></li><li><a href="poppedPanel.html">poppedPanel</a></li><li><a href="rawFileBase.html">rawFileBase</a></li><li><a href="rawFileHandler.html">rawFileHandler</a></li><li><a href="userList.html">userList</a></li><li><a href="youtubeEmbedHandler.html">youtubeEmbedHandler</a></li></ul><h3>Global</h3><ul><li><a href="global.html#onYouTubeIframeAPIReady">onYouTubeIframeAPIReady</a></li></ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:53 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:44 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
2900
www/doc/client/youtubeEmbedHandler.html
Normal file
2900
www/doc/client/youtubeEmbedHandler.html
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -786,7 +786,7 @@
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,7 @@ module.exports = activeChannel;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -347,7 +347,7 @@ module.exports = channelManager;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ module.exports = chat;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ module.exports = chatBuffer;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -376,7 +376,7 @@ module.exports = chatHandler;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -473,7 +473,7 @@ module.exports = commandPreprocessor;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,7 @@ module.exports = connectedUser;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ module.exports = media;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -1180,7 +1180,7 @@ module.exports = playlistHandler;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -1795,7 +1795,7 @@ module.exports = queue;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ module.exports = queuedMedia;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,7 @@ module.exports = tokebot;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -1991,7 +1991,7 @@
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -329,7 +329,7 @@
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -829,7 +829,7 @@ Left here since it seems like good form anywho, since this would be a private, o
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -3686,7 +3686,7 @@
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -1246,7 +1246,7 @@ These arrays are used to handle further command/chat processing
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -1831,7 +1831,7 @@
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -1879,7 +1879,7 @@ Having to crawl through these sockets is that. Because the other ways seem more
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -7377,7 +7377,7 @@ Warns server admin against unsafe config options.
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ This new codebase intends to solve the following issues with the current CyTube
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -352,7 +352,7 @@
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -5108,7 +5108,7 @@
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -5805,7 +5805,7 @@ Called auto-magically by the Synchronization Timer
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -936,7 +936,7 @@
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ module.exports = channelBanSchema;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ module.exports = channelPermissionSchema;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -934,7 +934,7 @@ module.exports = mongoose.model("channel", channelSchema);</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ module.exports = chatSchema;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ module.exports = mediaSchema;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ module.exports = mediaSchema.discriminator('saved', playlistMediaProperties);</c
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ module.exports = playlistSchema;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ module.exports = mediaSchema.discriminator('queued', queuedProperties);</code></
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@ module.exports = mongoose.model("emote", emoteSchema);</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ module.exports = mongoose.model("flair", flairSchema);</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@ module.exports = mongoose.model("permissions", permissionSchema);</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,7 @@ module.exports = mongoose.model("statistics", statSchema);</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ module.exports = mongoose.model("tokeCommand", tokeCommandSchema);</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ module.exports = mongoose.model("emailChange", emailChangeSchema);
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ module.exports = mongoose.model("passwordReset", passwordResetSchema);
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -521,7 +521,7 @@ module.exports = mongoose.model("userBan", userBanSchema);</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -888,7 +888,7 @@ module.exports.userModel = mongoose.model("user", userSchema);</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -841,7 +841,7 @@ I would now, but I don't want to break shit in a comment-only commit.
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ module.exports.verify = async function(payload, uniqueSecret = ''){
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ module.exports.securityCheck = function(){
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ module.exports.hashIP = function(ip){
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ module.exports.markLink = async function(link){
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ module.exports.errorMiddleware = function(err, req, res, next){
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ module.exports.sendAddressVerification = async function(requestDB, userDB, newEm
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ module.exports.fetchMetadata = async function(fullID, title){
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ module.exports.getMediaType = async function(url){
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ async function ytdlpFetch(link, format = 'b'){
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ module.exports.escapeRegex = function(string){
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ module.exports.kickoff = function(){
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -236,7 +236,7 @@ module.exports.maxAttempts = maxAttempts;</code></pre>
|
||||||
<br class="clear">
|
<br class="clear">
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Wed Sep 03 2025 07:51:51 GMT-0400 (Eastern Daylight Time)
|
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Thu Sep 04 2025 20:09:42 GMT-0400 (Eastern Daylight Time)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script> prettyPrint(); </script>
|
<script> prettyPrint(); </script>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ 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/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for object containing base code for the Canopy channel client.
|
* Class containing base code for the Canopy channel client.
|
||||||
*/
|
*/
|
||||||
class channel{
|
class channel{
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ 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/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for Object which represents Canopy Chat Box UI
|
* Class which represents Canopy Chat Box UI
|
||||||
*/
|
*/
|
||||||
class chatBox{
|
class chatBox{
|
||||||
/**
|
/**
|
||||||
|
|
@ -24,7 +24,7 @@ class chatBox{
|
||||||
*/
|
*/
|
||||||
constructor(client){
|
constructor(client){
|
||||||
/**
|
/**
|
||||||
* Parent CLient Management Object
|
* Parent Client Management Object
|
||||||
*/
|
*/
|
||||||
this.client = client
|
this.client = client
|
||||||
|
|
||||||
|
|
@ -69,20 +69,75 @@ class chatBox{
|
||||||
this.chatPostprocessor = new chatPostprocessor(client);
|
this.chatPostprocessor = new chatPostprocessor(client);
|
||||||
|
|
||||||
//Element Nodes
|
//Element Nodes
|
||||||
|
/**
|
||||||
|
* Chat Panel Container Div
|
||||||
|
*/
|
||||||
this.chatPanel = document.querySelector("#chat-panel-div");
|
this.chatPanel = document.querySelector("#chat-panel-div");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* High Level Selector
|
||||||
|
*/
|
||||||
this.highSelect = document.querySelector("#chat-panel-high-level-select");
|
this.highSelect = document.querySelector("#chat-panel-high-level-select");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flair Selector
|
||||||
|
*/
|
||||||
this.flairSelect = document.querySelector("#chat-panel-flair-select");
|
this.flairSelect = document.querySelector("#chat-panel-flair-select");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat Buffer Div
|
||||||
|
*/
|
||||||
this.chatBuffer = document.querySelector("#chat-panel-buffer-div");
|
this.chatBuffer = document.querySelector("#chat-panel-buffer-div");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat Prompt
|
||||||
|
*/
|
||||||
this.chatPrompt = document.querySelector("#chat-panel-prompt");
|
this.chatPrompt = document.querySelector("#chat-panel-prompt");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-Complete Placeholder
|
||||||
|
*/
|
||||||
this.autocompletePlaceholder = document.querySelector("#chat-panel-prompt-autocomplete-filler");
|
this.autocompletePlaceholder = document.querySelector("#chat-panel-prompt-autocomplete-filler");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-Complete Display
|
||||||
|
*/
|
||||||
this.autocompleteDisplay = document.querySelector("#chat-panel-prompt-autocomplete-display");
|
this.autocompleteDisplay = document.querySelector("#chat-panel-prompt-autocomplete-display");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings Panel Icon
|
||||||
|
*/
|
||||||
this.settingsIcon = document.querySelector("#chat-panel-settings-icon");
|
this.settingsIcon = document.querySelector("#chat-panel-settings-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Admin Panel Icon
|
||||||
|
*/
|
||||||
this.adminIcon = document.querySelector("#chat-panel-admin-icon");
|
this.adminIcon = document.querySelector("#chat-panel-admin-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emote Icon
|
||||||
|
*/
|
||||||
this.emoteIcon = document.querySelector("#chat-panel-emote-icon");
|
this.emoteIcon = document.querySelector("#chat-panel-emote-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send Chat/Command Button
|
||||||
|
*/
|
||||||
this.sendButton = document.querySelector("#chat-panel-send-button");
|
this.sendButton = document.querySelector("#chat-panel-send-button");
|
||||||
//Seems weird to stick this in here, but the split is dictated by chat width :P
|
|
||||||
|
/**
|
||||||
|
* Aspect Lock Icon
|
||||||
|
* Seems weird to stick this in here, but the split is dictated by chat width :P
|
||||||
|
*/
|
||||||
this.aspectLockIcon = document.querySelector("#media-panel-aspect-lock-icon");
|
this.aspectLockIcon = document.querySelector("#media-panel-aspect-lock-icon");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide Chat Icon
|
||||||
|
*/
|
||||||
this.hideChatIcon = document.querySelector("#chat-panel-div-hide");
|
this.hideChatIcon = document.querySelector("#chat-panel-div-hide");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show Chat Icon
|
||||||
|
*/
|
||||||
this.showChatIcon = document.querySelector("#media-panel-show-chat-icon");
|
this.showChatIcon = document.querySelector("#media-panel-show-chat-icon");
|
||||||
|
|
||||||
//Setup functions
|
//Setup functions
|
||||||
|
|
@ -91,6 +146,9 @@ class chatBox{
|
||||||
this.sizeToAspect();
|
this.sizeToAspect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines input-related event listeners
|
||||||
|
*/
|
||||||
setupInput(){
|
setupInput(){
|
||||||
//Chat bar
|
//Chat bar
|
||||||
this.chatPrompt.addEventListener("keydown", this.send.bind(this));
|
this.chatPrompt.addEventListener("keydown", this.send.bind(this));
|
||||||
|
|
@ -118,11 +176,18 @@ class chatBox{
|
||||||
this.chatBuffer.addEventListener('scroll', this.scrollHandler.bind(this));
|
this.chatBuffer.addEventListener('scroll', this.scrollHandler.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines network-related event listners
|
||||||
|
*/
|
||||||
defineListeners(){
|
defineListeners(){
|
||||||
this.client.socket.on("chatMessage", this.displayChat.bind(this));
|
this.client.socket.on("chatMessage", this.displayChat.bind(this));
|
||||||
this.client.socket.on("clearChat", this.clearChat.bind(this));
|
this.client.socket.on("clearChat", this.clearChat.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears chat on command from server
|
||||||
|
* @param {Object} data - Data from server
|
||||||
|
*/
|
||||||
clearChat(data){
|
clearChat(data){
|
||||||
//If we where passed a user to check
|
//If we where passed a user to check
|
||||||
if(data.user != null){
|
if(data.user != null){
|
||||||
|
|
@ -138,6 +203,10 @@ class chatBox{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives, Post-Processes, and Displays chat messages from server
|
||||||
|
* @param {Object} data De-hydrated chat object from server
|
||||||
|
*/
|
||||||
displayChat(data){
|
displayChat(data){
|
||||||
//Create chat-entry span
|
//Create chat-entry span
|
||||||
var chatEntry = document.createElement('span');
|
var chatEntry = document.createElement('span');
|
||||||
|
|
@ -186,15 +255,27 @@ class chatBox{
|
||||||
this.resizeAspect();
|
this.resizeAspect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatinate Text into Chat Prompt
|
||||||
|
* @param {String} text - Text to Concatinate
|
||||||
|
*/
|
||||||
catChat(text){
|
catChat(text){
|
||||||
this.chatPrompt.value += text;
|
this.chatPrompt.value += text;
|
||||||
this.displayAutocomplete();
|
this.displayAutocomplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls a toke command out with a specified user
|
||||||
|
* @param {String} user - User to toke with
|
||||||
|
*/
|
||||||
tokeWith(user){
|
tokeWith(user){
|
||||||
this.commandPreprocessor.preprocess(user == this.client.user.user ? "!toke up fuckers" : `!toke up ${user}`);
|
this.commandPreprocessor.preprocess(user == this.client.user.user ? "!toke up fuckers" : `!toke up ${user}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-processes and sends text from chat prompt to server
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
send(event){
|
send(event){
|
||||||
if((!event || !event.key || event.key == "Enter") && this.chatPrompt.value){
|
if((!event || !event.key || event.key == "Enter") && this.chatPrompt.value){
|
||||||
this.commandPreprocessor.preprocess(this.chatPrompt.value);
|
this.commandPreprocessor.preprocess(this.chatPrompt.value);
|
||||||
|
|
@ -205,6 +286,10 @@ class chatBox{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays auto-complete text against current prompt input
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
displayAutocomplete(event){
|
displayAutocomplete(event){
|
||||||
//Find current match
|
//Find current match
|
||||||
const match = this.checkAutocomplete();
|
const match = this.checkAutocomplete();
|
||||||
|
|
@ -216,6 +301,10 @@ class chatBox{
|
||||||
this.autocompleteDisplay.textContent = match.match.replace(match.word, '');
|
this.autocompleteDisplay.textContent = match.match.replace(match.word, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called upon tab-complete
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
tabComplete(event){
|
tabComplete(event){
|
||||||
//If we hit tab or this isn't a keyboard event
|
//If we hit tab or this isn't a keyboard event
|
||||||
if(event.key == "Tab" || event.key == null){
|
if(event.key == "Tab" || event.key == null){
|
||||||
|
|
@ -239,6 +328,11 @@ class chatBox{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks string input against auto-complete dictionary to generate the best guess as to what the user is typing
|
||||||
|
* @param {String} input - Current input from Chat Prompt
|
||||||
|
* @returns {Object} Object containing word we where handed and the match we found
|
||||||
|
*/
|
||||||
checkAutocomplete(input = this.chatPrompt.value){
|
checkAutocomplete(input = this.chatPrompt.value){
|
||||||
//Rebuild this fucker every time because it really doesn't take that much compute power and emotes/used tokes change
|
//Rebuild this fucker every time because it really doesn't take that much compute power and emotes/used tokes change
|
||||||
//Worst case we could store it persistantly and update as needed but I think that might be much
|
//Worst case we could store it persistantly and update as needed but I think that might be much
|
||||||
|
|
@ -287,27 +381,48 @@ class chatBox{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles initial client meta-data dump from server upon connection
|
||||||
|
* @param {Object} data - Data dump from server
|
||||||
|
*/
|
||||||
handleClientInfo(data){
|
handleClientInfo(data){
|
||||||
this.updateFlairSelect(data.flairList, data.user.flair);
|
this.updateFlairSelect(data.flairList, data.user.flair);
|
||||||
this.updateHighSelect(data.user.highLevel);
|
this.updateHighSelect(data.user.highLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets user high-level
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
setHighLevel(event){
|
setHighLevel(event){
|
||||||
const highLevel = event.target.value;
|
const highLevel = event.target.value;
|
||||||
|
|
||||||
this.client.socket.emit("setHighLevel", {highLevel});
|
this.client.socket.emit("setHighLevel", {highLevel});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets user flair
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
setFlair(event){
|
setFlair(event){
|
||||||
const flair = event.target.value;
|
const flair = event.target.value;
|
||||||
|
|
||||||
this.client.socket.emit("setFlair", {flair});
|
this.client.socket.emit("setFlair", {flair});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles High-Level updates from the server
|
||||||
|
* @param {Number} highLevel - High Level to Set
|
||||||
|
*/
|
||||||
updateHighSelect(highLevel){
|
updateHighSelect(highLevel){
|
||||||
this.highSelect.value = highLevel;
|
this.highSelect.value = highLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles flair updates from the server
|
||||||
|
* @param {Array} fliarList - List of flairs to put into flair select
|
||||||
|
* @param {String} fliar - Flair to set
|
||||||
|
*/
|
||||||
updateFlairSelect(flairList, flair){
|
updateFlairSelect(flairList, flair){
|
||||||
//clear current flair select
|
//clear current flair select
|
||||||
this.flairSelect.innerHTML = "";
|
this.flairSelect.innerHTML = "";
|
||||||
|
|
@ -331,6 +446,10 @@ class chatBox{
|
||||||
this.flairSelect.classList.add(`flair-${flair}`);
|
this.flairSelect.classList.add(`flair-${flair}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locks chat-size to aspect ratio of media
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
lockAspect(event){
|
lockAspect(event){
|
||||||
//prevent the user from breaking shit :P
|
//prevent the user from breaking shit :P
|
||||||
if(this.chatPanel.style.display != "none"){
|
if(this.chatPanel.style.display != "none"){
|
||||||
|
|
@ -340,6 +459,10 @@ class chatBox{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un-locks chat-size to aspect ratio of media
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
unlockAspect(event){
|
unlockAspect(event){
|
||||||
//Disable aspect lock
|
//Disable aspect lock
|
||||||
this.aspectLock = false;
|
this.aspectLock = false;
|
||||||
|
|
@ -348,6 +471,11 @@ class chatBox{
|
||||||
this.aspectLockIcon.style.display = "inline";
|
this.aspectLockIcon.style.display = "inline";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
L /**
|
||||||
|
* Re-sizes chat back to aspect ratio on window re-size when chat box is aspect locked
|
||||||
|
* Also prevents horizontal scroll-bars from chat/window resizing
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
resizeAspect(event){
|
resizeAspect(event){
|
||||||
const playerHidden = this.client.player.playerDiv.style.display == "none";
|
const playerHidden = this.client.player.playerDiv.style.display == "none";
|
||||||
|
|
||||||
|
|
@ -364,6 +492,9 @@ class chatBox{
|
||||||
this.handleAutoScroll();
|
this.handleAutoScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
L /**
|
||||||
|
* Re-sizes chat box relative to media aspect ratio
|
||||||
|
*/
|
||||||
sizeToAspect(){
|
sizeToAspect(){
|
||||||
if(this.chatPanel.style.display != "none"){
|
if(this.chatPanel.style.display != "none"){
|
||||||
var targetVidWidth = this.client.player.getRatio() * this.chatPanel.getBoundingClientRect().height;
|
var targetVidWidth = this.client.player.getRatio() * this.chatPanel.getBoundingClientRect().height;
|
||||||
|
|
@ -384,6 +515,10 @@ class chatBox{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles Chat Box UX
|
||||||
|
* @param {Boolean} show - Whether or not to show Chat Box UX
|
||||||
|
*/
|
||||||
toggleUI(show = !this.chatPanel.checkVisibility()){
|
toggleUI(show = !this.chatPanel.checkVisibility()){
|
||||||
if(show){
|
if(show){
|
||||||
this.chatPanel.style.display = "flex";
|
this.chatPanel.style.display = "flex";
|
||||||
|
|
@ -397,6 +532,10 @@ class chatBox{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Video Toggling
|
||||||
|
* @param {Boolean} show - Whether or not the video is currently being hidden
|
||||||
|
*/
|
||||||
handleVideoToggle(show){
|
handleVideoToggle(show){
|
||||||
//If we're enabling the video
|
//If we're enabling the video
|
||||||
if(show){
|
if(show){
|
||||||
|
|
@ -421,6 +560,10 @@ class chatBox{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles scrolling within the chat buffer
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
scrollHandler(event){
|
scrollHandler(event){
|
||||||
//If we're just starting out
|
//If we're just starting out
|
||||||
if(this.lastPos == 0){
|
if(this.lastPos == 0){
|
||||||
|
|
@ -465,6 +608,9 @@ class chatBox{
|
||||||
this.lastWidth = bufferWidth;
|
this.lastWidth = bufferWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-scrolls chat buffer when new chats are entered.
|
||||||
|
*/
|
||||||
handleAutoScroll(){
|
handleAutoScroll(){
|
||||||
//If autoscroll is enabled
|
//If autoscroll is enabled
|
||||||
if(this.autoScroll){
|
if(this.autoScroll){
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,28 @@ GNU Affero General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class contianing client-side message post-processing code
|
||||||
|
*/
|
||||||
class chatPostprocessor{
|
class chatPostprocessor{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Chat Post-Processor object
|
||||||
|
* @param {channel} client - Parent client Management Object
|
||||||
|
*/
|
||||||
constructor(client){
|
constructor(client){
|
||||||
|
/**
|
||||||
|
* Parent Client Management Object
|
||||||
|
*/
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post-Processes a single message from the server and returns a presntable DOM Node
|
||||||
|
* @param {Node} chatEntry - Chat entry generated by initial chatBox method
|
||||||
|
* @param {Object} rawData - Raw data from server
|
||||||
|
* @returns {Node} Post-Processed Chat Entry
|
||||||
|
*/
|
||||||
postprocess(chatEntry, rawData){
|
postprocess(chatEntry, rawData){
|
||||||
//Create empty array to hold filter spans
|
//Create empty array to hold filter spans
|
||||||
this.filterSpans = [];
|
this.filterSpans = [];
|
||||||
|
|
@ -30,6 +47,7 @@ class chatPostprocessor{
|
||||||
//Split the chat message into an array of objects representing each word/chunk
|
//Split the chat message into an array of objects representing each word/chunk
|
||||||
this.splitMessage();
|
this.splitMessage();
|
||||||
|
|
||||||
|
//Process Qoutes
|
||||||
this.processQoute();
|
this.processQoute();
|
||||||
|
|
||||||
//Re-Hydrate and Inject links and embedded media into un-processed placeholders
|
//Re-Hydrate and Inject links and embedded media into un-processed placeholders
|
||||||
|
|
@ -62,13 +80,16 @@ class chatPostprocessor{
|
||||||
//Handle non-standard chat types
|
//Handle non-standard chat types
|
||||||
this.handleChatType();
|
this.handleChatType();
|
||||||
|
|
||||||
//Inject the pre-processed chat into the chatEntry node
|
//Inject the pre-processed chat hyper-text into the chatEntry node
|
||||||
this.injectBody();
|
this.injectBody();
|
||||||
|
|
||||||
//Return the pre-processed node
|
//Return the pre-processed node
|
||||||
return this.chatEntry;
|
return this.chatEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits message into an array of Word Objects for further processing
|
||||||
|
*/
|
||||||
splitMessage(){
|
splitMessage(){
|
||||||
//Create an empty array to hold the body
|
//Create an empty array to hold the body
|
||||||
this.messageArray = [];
|
this.messageArray = [];
|
||||||
|
|
@ -93,6 +114,9 @@ class chatPostprocessor{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects word objects into chat-entry as proper DOM Nodes
|
||||||
|
*/
|
||||||
injectBody(){
|
injectBody(){
|
||||||
//Create an empty array to hold the objects to inject
|
//Create an empty array to hold the objects to inject
|
||||||
const injectionArray = [];
|
const injectionArray = [];
|
||||||
|
|
@ -285,6 +309,9 @@ class chatPostprocessor{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes qouted text in chat
|
||||||
|
*/
|
||||||
processQoute(){
|
processQoute(){
|
||||||
//If the message starts off with '>'
|
//If the message starts off with '>'
|
||||||
if(this.messageArray[0].string[0] == '>'){
|
if(this.messageArray[0].string[0] == '>'){
|
||||||
|
|
@ -292,6 +319,9 @@ class chatPostprocessor{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes clickable command examples in chat
|
||||||
|
*/
|
||||||
processCommandExamples(){
|
processCommandExamples(){
|
||||||
//for each word object in the body
|
//for each word object in the body
|
||||||
this.messageArray.forEach((wordObj, wordIndex) => {
|
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||||
|
|
@ -324,6 +354,9 @@ class chatPostprocessor{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes clickable channel names in chat
|
||||||
|
*/
|
||||||
processChannelNames(){
|
processChannelNames(){
|
||||||
//for each word object in the body
|
//for each word object in the body
|
||||||
this.messageArray.forEach((wordObj, wordIndex) => {
|
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||||
|
|
@ -356,6 +389,9 @@ class chatPostprocessor{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes clickable username callouts in chat
|
||||||
|
*/
|
||||||
processUsernames(){
|
processUsernames(){
|
||||||
//for each word object in the body
|
//for each word object in the body
|
||||||
this.messageArray.forEach((wordObj, wordIndex) => {
|
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||||
|
|
@ -375,6 +411,9 @@ class chatPostprocessor{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects invisible whitespace in long-ass words to prevent fucking up the chat buffer size
|
||||||
|
*/
|
||||||
addWhitespace(){
|
addWhitespace(){
|
||||||
//for each word object in the body
|
//for each word object in the body
|
||||||
this.messageArray.forEach((wordObj, wordIndex) => {
|
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||||
|
|
@ -400,6 +439,14 @@ class chatPostprocessor{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for text in-between a specific delimiter and runs a given callback against it
|
||||||
|
*
|
||||||
|
* Internal command used by several text filters to prevent code re-writes
|
||||||
|
* @param {String} delimiter - delimiter to search string by
|
||||||
|
* @param {Function} cb - Callback function to run against found strings
|
||||||
|
* @returns {Array} - list of found instances of filter
|
||||||
|
*/
|
||||||
processFilter(delimiter, cb){
|
processFilter(delimiter, cb){
|
||||||
//Create empty array to hold spoilers (keep this seperate at first for internal function use)
|
//Create empty array to hold spoilers (keep this seperate at first for internal function use)
|
||||||
const foundFilters = [];
|
const foundFilters = [];
|
||||||
|
|
@ -451,6 +498,9 @@ class chatPostprocessor{
|
||||||
return foundFilters;
|
return foundFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes in-line spoilers
|
||||||
|
*/
|
||||||
processSpoilers(){
|
processSpoilers(){
|
||||||
//Process spoilers using '##' delimiter
|
//Process spoilers using '##' delimiter
|
||||||
this.processFilter('##', (foundSpoiler)=>{
|
this.processFilter('##', (foundSpoiler)=>{
|
||||||
|
|
@ -459,6 +509,9 @@ class chatPostprocessor{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes in-line Strike-through
|
||||||
|
*/
|
||||||
processStrikethrough(){
|
processStrikethrough(){
|
||||||
//Process strikethrough's using '~~' delimiter
|
//Process strikethrough's using '~~' delimiter
|
||||||
this.processFilter('~~', (foundStrikethrough)=>{
|
this.processFilter('~~', (foundStrikethrough)=>{
|
||||||
|
|
@ -468,6 +521,9 @@ class chatPostprocessor{
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes in-line Bold/Strong text
|
||||||
|
*/
|
||||||
processBold(){
|
processBold(){
|
||||||
//Process strong text using '*' delimiter
|
//Process strong text using '*' delimiter
|
||||||
this.processFilter('**', (foundStrikethrough)=>{
|
this.processFilter('**', (foundStrikethrough)=>{
|
||||||
|
|
@ -477,6 +533,9 @@ class chatPostprocessor{
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes in-line Italics
|
||||||
|
*/
|
||||||
processItalics(){
|
processItalics(){
|
||||||
//Process italics using '__' delimiter
|
//Process italics using '__' delimiter
|
||||||
this.processFilter('*', (foundStrikethrough)=>{
|
this.processFilter('*', (foundStrikethrough)=>{
|
||||||
|
|
@ -486,6 +545,9 @@ class chatPostprocessor{
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes clickable links and embedded media
|
||||||
|
*/
|
||||||
processLinks(){
|
processLinks(){
|
||||||
//If we don't have links
|
//If we don't have links
|
||||||
if(this.rawData.links == null){
|
if(this.rawData.links == null){
|
||||||
|
|
@ -513,6 +575,9 @@ class chatPostprocessor{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks chat nodes in-case of non-standard chat types
|
||||||
|
*/
|
||||||
handleChatType(){
|
handleChatType(){
|
||||||
if(this.rawData.type == "whisper"){
|
if(this.rawData.type == "whisper"){
|
||||||
//add whisper class
|
//add whisper class
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ 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/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for object containing chat and command pre-processing logic
|
* Class containing chat and command pre-processing logic
|
||||||
*/
|
*/
|
||||||
class commandPreprocessor{
|
class commandPreprocessor{
|
||||||
/**
|
/**
|
||||||
|
|
@ -300,7 +300,7 @@ class commandPreprocessor{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for Object which contains logic for client-side commands
|
* Class which contains logic for client-side commands
|
||||||
*/
|
*/
|
||||||
class commandProcessor{
|
class commandProcessor{
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ 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/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for Object containing code for managing the Canopy Panel UX
|
* Class containing code for managing the Canopy Panel UX
|
||||||
*/
|
*/
|
||||||
class cPanel{
|
class cPanel{
|
||||||
/**
|
/**
|
||||||
|
|
@ -323,7 +323,7 @@ class panelObj{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for Objects which represent a single instance of a popped-out panel
|
* Class which represents a single instance of a popped-out panel
|
||||||
*/
|
*/
|
||||||
class poppedPanel{
|
class poppedPanel{
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -14,26 +14,53 @@ GNU Affero General Public License for more details.
|
||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
//This is little more than a interface class
|
/*
|
||||||
|
* Base class for all Canopy Media Handlers
|
||||||
|
*
|
||||||
|
* This is little more than a interface class
|
||||||
|
*/
|
||||||
class mediaHandler{
|
class mediaHandler{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Media Handler object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
* @param {Object} media - De-hydrated media object from server
|
||||||
|
* @param {String} type - Media Handler Source Type
|
||||||
|
*/
|
||||||
constructor(client, player, media, type){
|
constructor(client, player, media, type){
|
||||||
//Get parents
|
/**
|
||||||
|
* Parent Client Management Object
|
||||||
|
*/
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent Canopy Player Object
|
||||||
|
*/
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
|
||||||
//Set handler type
|
/**
|
||||||
|
* Media Handler Source Type
|
||||||
|
*/
|
||||||
this.type = type
|
this.type = type
|
||||||
|
|
||||||
//Denotes wether a seek call was made by the syncing function
|
/*
|
||||||
|
* Denotes wether a seek call was made by the syncing function
|
||||||
|
*/
|
||||||
this.selfAct = false;
|
this.selfAct = false;
|
||||||
|
|
||||||
//Set last received timestamp to 0
|
/*
|
||||||
|
* Contains the last received time stamp
|
||||||
|
*/
|
||||||
this.lastTimestamp = 0;
|
this.lastTimestamp = 0;
|
||||||
|
|
||||||
//Ingest media object from server
|
//Ingest media object from server
|
||||||
this.startMedia(media);
|
this.startMedia(media);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ingests media nd starts playback
|
||||||
|
* @param {Object} media - Media object from server
|
||||||
|
*/
|
||||||
startMedia(media){
|
startMedia(media){
|
||||||
//If we properly ingested the media
|
//If we properly ingested the media
|
||||||
if(this.ingestMedia(media)){
|
if(this.ingestMedia(media)){
|
||||||
|
|
@ -45,16 +72,27 @@ class mediaHandler{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds video player element
|
||||||
|
*/
|
||||||
buildPlayer(){
|
buildPlayer(){
|
||||||
//Reset player lock
|
//Reset player lock
|
||||||
this.lock = false;
|
this.lock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys video player element
|
||||||
|
*/
|
||||||
destroyPlayer(){
|
destroyPlayer(){
|
||||||
//Null out video property
|
//Null out video property
|
||||||
this.video = null;
|
this.video = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ingests media object from server
|
||||||
|
* @param {Object} media - Media object from the server
|
||||||
|
* @returns {Boolean} True upon success
|
||||||
|
*/
|
||||||
ingestMedia(media){
|
ingestMedia(media){
|
||||||
//Set now playing
|
//Set now playing
|
||||||
this.nowPlaying = media;
|
this.nowPlaying = media;
|
||||||
|
|
@ -63,10 +101,17 @@ class mediaHandler{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts video playback
|
||||||
|
*/
|
||||||
start(){
|
start(){
|
||||||
this.setVideoTitle(this.nowPlaying.title);
|
this.setVideoTitle(this.nowPlaying.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syncronizes timestamp based on timestamp received from server
|
||||||
|
* @param {Number} timestamp - Current video timestamp in seconds
|
||||||
|
*/
|
||||||
sync(timestamp = this.lastTimestamp){
|
sync(timestamp = this.lastTimestamp){
|
||||||
//Skip sync calls that won't seek so we don't pointlessly throw selfAct
|
//Skip sync calls that won't seek so we don't pointlessly throw selfAct
|
||||||
if(timestamp != this.video.currentTime){
|
if(timestamp != this.video.currentTime){
|
||||||
|
|
@ -75,6 +120,9 @@ class mediaHandler{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads media player
|
||||||
|
*/
|
||||||
reload(){
|
reload(){
|
||||||
//Get current timestamp
|
//Get current timestamp
|
||||||
const timestamp = this.video.currentTime;
|
const timestamp = this.video.currentTime;
|
||||||
|
|
@ -83,6 +131,9 @@ class mediaHandler{
|
||||||
this.selfAct = true;
|
this.selfAct = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles media end
|
||||||
|
*/
|
||||||
end(){
|
end(){
|
||||||
//Null out current media
|
//Null out current media
|
||||||
this.nowPlaying = null;
|
this.nowPlaying = null;
|
||||||
|
|
@ -94,32 +145,64 @@ class mediaHandler{
|
||||||
this.destroyPlayer();
|
this.destroyPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plays video
|
||||||
|
*/
|
||||||
play(){
|
play(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pauses video
|
||||||
|
*/
|
||||||
pause(){
|
pause(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles player control lockout
|
||||||
|
* @param {Boolean} lock - Whether or not to lock-out user control of video
|
||||||
|
*/
|
||||||
setPlayerLock(lock){
|
setPlayerLock(lock){
|
||||||
//set lock property
|
//set lock property
|
||||||
this.lock = lock;
|
this.lock = lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates Aspect Ratio of media
|
||||||
|
* @returns {Number} Media Aspect Ratio as Floating Point number
|
||||||
|
*/
|
||||||
getRatio(){
|
getRatio(){
|
||||||
|
return 4/3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets current timestamp from video
|
||||||
|
* @returns {Number} Media Timestamp in seconds
|
||||||
|
*/
|
||||||
getTimestamp(){
|
getTimestamp(){
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets player title
|
||||||
|
* @param {String} title - Title to set
|
||||||
|
*/
|
||||||
setVideoTitle(title){
|
setVideoTitle(title){
|
||||||
this.player.title.textContent = `Currently Playing: ${title}`;
|
this.player.title.textContent = `Currently Playing: ${title}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called once all video metadata has properly been fetched
|
||||||
|
* @param {Event} event - Event passed down by event handler
|
||||||
|
*/
|
||||||
onMetadataLoad(event){
|
onMetadataLoad(event){
|
||||||
//Resize aspect (if locked), since the video doesn't properly report it's resolution until it's been loaded
|
//Resize aspect (if locked), since the video doesn't properly report it's resolution until it's been loaded
|
||||||
this.client.chatBox.resizeAspect();
|
this.client.chatBox.resizeAspect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on media pause
|
||||||
|
* @param {Event} event - Event passed down by event handler
|
||||||
|
*/
|
||||||
onPause(event){
|
onPause(event){
|
||||||
//If the video was paused out-side of code
|
//If the video was paused out-side of code
|
||||||
if(!this.selfAct){
|
if(!this.selfAct){
|
||||||
|
|
@ -129,9 +212,17 @@ class mediaHandler{
|
||||||
this.selfAct = false;
|
this.selfAct = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on media volume change
|
||||||
|
* @param {Event} event - Event passed down by event handler
|
||||||
|
*/
|
||||||
onVolumeChange(event){
|
onVolumeChange(event){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on media seek
|
||||||
|
* @param {Event} event - Event passed down by event handler
|
||||||
|
*/
|
||||||
onSeek(event){
|
onSeek(event){
|
||||||
//If the video was seeked out-side of code
|
//If the video was seeked out-side of code
|
||||||
if(!this.selfAct){
|
if(!this.selfAct){
|
||||||
|
|
@ -142,17 +233,34 @@ class mediaHandler{
|
||||||
this.selfAct = false;
|
this.selfAct = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on media buffer
|
||||||
|
* @param {Event} event - Event passed down by event handler
|
||||||
|
*/
|
||||||
onBuffer(){
|
onBuffer(){
|
||||||
this.selfAct = true;
|
this.selfAct = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Basic building blocks for anything that touches a <video> tag
|
/**
|
||||||
|
* Class containing basic building blocks for anything that touches a <video> tag
|
||||||
|
* @extends mediaHandler
|
||||||
|
*/
|
||||||
class rawFileBase extends mediaHandler{
|
class rawFileBase extends mediaHandler{
|
||||||
|
/**
|
||||||
|
* Instantiates a new rawFileBase object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
* @param {Object} media - De-hydrated media object from server
|
||||||
|
* @param {String} type - Media Handler Source Type
|
||||||
|
*/
|
||||||
constructor(client, player, media, type){
|
constructor(client, player, media, type){
|
||||||
super(client, player, media, type);
|
super(client, player, media, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines input-related event listeners
|
||||||
|
*/
|
||||||
defineListeners(){
|
defineListeners(){
|
||||||
//Resize to aspect on metadata load
|
//Resize to aspect on metadata load
|
||||||
this.video.addEventListener('loadedmetadata', this.onMetadataLoad.bind(this));
|
this.video.addEventListener('loadedmetadata', this.onMetadataLoad.bind(this));
|
||||||
|
|
@ -222,8 +330,16 @@ class rawFileBase extends mediaHandler{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Off air static 'player'
|
/**
|
||||||
|
* Off air static 'player'
|
||||||
|
* @extends rawFileBase
|
||||||
|
*/
|
||||||
class nullHandler extends rawFileBase{
|
class nullHandler extends rawFileBase{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Null Handler object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
*/
|
||||||
constructor(client, player){
|
constructor(client, player){
|
||||||
//Call derived constructor
|
//Call derived constructor
|
||||||
super(client, player, {}, null);
|
super(client, player, {}, null);
|
||||||
|
|
@ -258,8 +374,17 @@ class nullHandler extends rawFileBase{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Basic building blocks needed for proper time-synchronized raw-file playback
|
/**
|
||||||
|
* Basic building blocks needed for proper time-synchronized raw-file playback
|
||||||
|
* @extends rawFileBase
|
||||||
|
*/
|
||||||
class rawFileHandler extends rawFileBase{
|
class rawFileHandler extends rawFileBase{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Null Handler object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
* @param {Object} media - De-hydrated media object from server
|
||||||
|
*/
|
||||||
constructor(client, player, media){
|
constructor(client, player, media){
|
||||||
//Call derived constructor
|
//Call derived constructor
|
||||||
super(client, player, media, 'raw');
|
super(client, player, media, 'raw');
|
||||||
|
|
@ -319,7 +444,17 @@ class rawFileHandler extends rawFileBase{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Youtube playback via the official YT embed (gross)
|
||||||
|
* @extends mediaHandler
|
||||||
|
*/
|
||||||
class youtubeEmbedHandler extends mediaHandler{
|
class youtubeEmbedHandler extends mediaHandler{
|
||||||
|
/**
|
||||||
|
* Instantiates a new Youtube Embed Handler object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
* @param {Object} media - De-hydrated media object from server
|
||||||
|
*/
|
||||||
constructor(client, player, media){
|
constructor(client, player, media){
|
||||||
//Call derived constructor
|
//Call derived constructor
|
||||||
super(client, player, media, 'ytEmbed');
|
super(client, player, media, 'ytEmbed');
|
||||||
|
|
@ -469,7 +604,9 @@ class youtubeEmbedHandler extends mediaHandler{
|
||||||
this.player.title.textContent = "";
|
this.player.title.textContent = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
//Generic handler for state changes since google is a dick
|
/**
|
||||||
|
* Generic handler for state changes since google is a dick
|
||||||
|
*/
|
||||||
onStateChange(event){
|
onStateChange(event){
|
||||||
switch(event.data){
|
switch(event.data){
|
||||||
//video unstarted
|
//video unstarted
|
||||||
|
|
@ -509,7 +646,18 @@ class youtubeEmbedHandler extends mediaHandler{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base HLS Media handler for handling all HLS related media
|
||||||
|
* @extends rawFileBase
|
||||||
|
*/
|
||||||
class hlsBase extends rawFileBase{
|
class hlsBase extends rawFileBase{
|
||||||
|
/**
|
||||||
|
* Instantiates a new HLS Base object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
* @param {Object} media - De-hydrated media object from server
|
||||||
|
* @param {String} type - Media Handler Source Type
|
||||||
|
*/
|
||||||
constructor(client, player, media, type){
|
constructor(client, player, media, type){
|
||||||
//Call derived constructor
|
//Call derived constructor
|
||||||
super(client, player, media, type);
|
super(client, player, media, type);
|
||||||
|
|
@ -554,7 +702,17 @@ class hlsBase extends rawFileBase{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HLS Livestream Handler
|
||||||
|
* @extends hlsBase
|
||||||
|
*/
|
||||||
class hlsLiveStreamHandler extends hlsBase{
|
class hlsLiveStreamHandler extends hlsBase{
|
||||||
|
/**
|
||||||
|
* Instantiates a new HLS Live Stream Handler object
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {player} player - Parent Canopy Player Object
|
||||||
|
* @param {Object} media - De-hydrated media object from server
|
||||||
|
*/
|
||||||
constructor(client, player, media){
|
constructor(client, player, media){
|
||||||
//Call derived constructor
|
//Call derived constructor
|
||||||
super(client, player, media, "livehls");
|
super(client, player, media, "livehls");
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ 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/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for objects which represent Canopy Player UX
|
* Class which represents Canopy Player UX
|
||||||
*/
|
*/
|
||||||
class player{
|
class player{
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ 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/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for object containing logic behind userlist UX
|
* Class containing logic behind userlist UX
|
||||||
*/
|
*/
|
||||||
class userList{
|
class userList{
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue