JSDoc for www/js/channel/*.js complete. Just need to hadnle ww/js/channel/panels.
This commit is contained in:
parent
ac06f839ea
commit
c0f219276f
91 changed files with 38653 additions and 104 deletions
|
|
@ -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/>.*/
|
||||
|
||||
/**
|
||||
* Class for object containing base code for the Canopy channel client.
|
||||
* Class containing base code for the Canopy channel client.
|
||||
*/
|
||||
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/>.*/
|
||||
|
||||
/**
|
||||
* Class for Object which represents Canopy Chat Box UI
|
||||
* Class which represents Canopy Chat Box UI
|
||||
*/
|
||||
class chatBox{
|
||||
/**
|
||||
|
|
@ -24,7 +24,7 @@ class chatBox{
|
|||
*/
|
||||
constructor(client){
|
||||
/**
|
||||
* Parent CLient Management Object
|
||||
* Parent Client Management Object
|
||||
*/
|
||||
this.client = client
|
||||
|
||||
|
|
@ -69,20 +69,75 @@ class chatBox{
|
|||
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");
|
||||
//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");
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
@ -91,6 +146,9 @@ class chatBox{
|
|||
this.sizeToAspect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines input-related event listeners
|
||||
*/
|
||||
setupInput(){
|
||||
//Chat bar
|
||||
this.chatPrompt.addEventListener("keydown", this.send.bind(this));
|
||||
|
|
@ -118,11 +176,18 @@ class chatBox{
|
|||
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){
|
||||
|
|
@ -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){
|
||||
//Create chat-entry span
|
||||
var chatEntry = document.createElement('span');
|
||||
|
|
@ -186,15 +255,27 @@ class chatBox{
|
|||
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);
|
||||
|
|
@ -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){
|
||||
//Find current match
|
||||
const match = this.checkAutocomplete();
|
||||
|
|
@ -216,6 +301,10 @@ class chatBox{
|
|||
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){
|
||||
|
|
@ -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){
|
||||
//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
|
||||
|
|
@ -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){
|
||||
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 = "";
|
||||
|
|
@ -331,6 +446,10 @@ class chatBox{
|
|||
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"){
|
||||
|
|
@ -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){
|
||||
//Disable aspect lock
|
||||
this.aspectLock = false;
|
||||
|
|
@ -348,6 +471,11 @@ class chatBox{
|
|||
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";
|
||||
|
||||
|
|
@ -364,6 +492,9 @@ class chatBox{
|
|||
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;
|
||||
|
|
@ -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()){
|
||||
if(show){
|
||||
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){
|
||||
//If we're enabling the video
|
||||
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){
|
||||
//If we're just starting out
|
||||
if(this.lastPos == 0){
|
||||
|
|
@ -465,6 +608,9 @@ class chatBox{
|
|||
this.lastWidth = bufferWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-scrolls chat buffer when new chats are entered.
|
||||
*/
|
||||
handleAutoScroll(){
|
||||
//If autoscroll is enabled
|
||||
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
|
||||
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 = [];
|
||||
|
|
@ -30,6 +47,7 @@ class chatPostprocessor{
|
|||
//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
|
||||
|
|
@ -62,13 +80,16 @@ class chatPostprocessor{
|
|||
//Handle non-standard chat types
|
||||
this.handleChatType();
|
||||
|
||||
//Inject the pre-processed chat into the chatEntry node
|
||||
//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 = [];
|
||||
|
|
@ -93,6 +114,9 @@ class chatPostprocessor{
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects word objects into chat-entry as proper DOM Nodes
|
||||
*/
|
||||
injectBody(){
|
||||
//Create an empty array to hold the objects to inject
|
||||
const injectionArray = [];
|
||||
|
|
@ -285,6 +309,9 @@ class chatPostprocessor{
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes qouted text in chat
|
||||
*/
|
||||
processQoute(){
|
||||
//If the message starts off with '>'
|
||||
if(this.messageArray[0].string[0] == '>'){
|
||||
|
|
@ -292,6 +319,9 @@ class chatPostprocessor{
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes clickable command examples in chat
|
||||
*/
|
||||
processCommandExamples(){
|
||||
//for each word object in the body
|
||||
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||
|
|
@ -324,6 +354,9 @@ class chatPostprocessor{
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes clickable channel names in chat
|
||||
*/
|
||||
processChannelNames(){
|
||||
//for each word object in the body
|
||||
this.messageArray.forEach((wordObj, wordIndex) => {
|
||||
|
|
@ -356,6 +389,9 @@ class chatPostprocessor{
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes clickable username callouts in chat
|
||||
*/
|
||||
processUsernames(){
|
||||
//for each word object in the body
|
||||
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(){
|
||||
//for each word object in the body
|
||||
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){
|
||||
//Create empty array to hold spoilers (keep this seperate at first for internal function use)
|
||||
const foundFilters = [];
|
||||
|
|
@ -451,6 +498,9 @@ class chatPostprocessor{
|
|||
return foundFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes in-line spoilers
|
||||
*/
|
||||
processSpoilers(){
|
||||
//Process spoilers using '##' delimiter
|
||||
this.processFilter('##', (foundSpoiler)=>{
|
||||
|
|
@ -459,6 +509,9 @@ class chatPostprocessor{
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes in-line Strike-through
|
||||
*/
|
||||
processStrikethrough(){
|
||||
//Process strikethrough's using '~~' delimiter
|
||||
this.processFilter('~~', (foundStrikethrough)=>{
|
||||
|
|
@ -468,6 +521,9 @@ class chatPostprocessor{
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes in-line Bold/Strong text
|
||||
*/
|
||||
processBold(){
|
||||
//Process strong text using '*' delimiter
|
||||
this.processFilter('**', (foundStrikethrough)=>{
|
||||
|
|
@ -477,6 +533,9 @@ class chatPostprocessor{
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes in-line Italics
|
||||
*/
|
||||
processItalics(){
|
||||
//Process italics using '__' delimiter
|
||||
this.processFilter('*', (foundStrikethrough)=>{
|
||||
|
|
@ -486,6 +545,9 @@ class chatPostprocessor{
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes clickable links and embedded media
|
||||
*/
|
||||
processLinks(){
|
||||
//If we don't have links
|
||||
if(this.rawData.links == null){
|
||||
|
|
@ -513,6 +575,9 @@ class chatPostprocessor{
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks chat nodes in-case of non-standard chat types
|
||||
*/
|
||||
handleChatType(){
|
||||
if(this.rawData.type == "whisper"){
|
||||
//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/>.*/
|
||||
|
||||
/**
|
||||
* Class for object containing chat and command pre-processing logic
|
||||
* Class containing chat and command pre-processing logic
|
||||
*/
|
||||
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{
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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/>.*/
|
||||
|
||||
/**
|
||||
* Class for Object containing code for managing the Canopy Panel UX
|
||||
* Class containing code for managing the Canopy Panel UX
|
||||
*/
|
||||
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{
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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{
|
||||
/**
|
||||
* 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){
|
||||
//Get parents
|
||||
/**
|
||||
* Parent Client Management Object
|
||||
*/
|
||||
this.client = client;
|
||||
|
||||
/**
|
||||
* Parent Canopy Player Object
|
||||
*/
|
||||
this.player = player;
|
||||
|
||||
//Set handler type
|
||||
/**
|
||||
* Media Handler Source 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;
|
||||
|
||||
//Set last received timestamp to 0
|
||||
/*
|
||||
* 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)){
|
||||
|
|
@ -45,16 +72,27 @@ class mediaHandler{
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
|
@ -63,10 +101,17 @@ class mediaHandler{
|
|||
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){
|
||||
|
|
@ -75,6 +120,9 @@ class mediaHandler{
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads media player
|
||||
*/
|
||||
reload(){
|
||||
//Get current timestamp
|
||||
const timestamp = this.video.currentTime;
|
||||
|
|
@ -83,6 +131,9 @@ class mediaHandler{
|
|||
this.selfAct = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles media end
|
||||
*/
|
||||
end(){
|
||||
//Null out current media
|
||||
this.nowPlaying = null;
|
||||
|
|
@ -94,32 +145,64 @@ class mediaHandler{
|
|||
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){
|
||||
|
|
@ -129,9 +212,17 @@ class mediaHandler{
|
|||
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){
|
||||
|
|
@ -142,17 +233,34 @@ class mediaHandler{
|
|||
this.selfAct = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on media buffer
|
||||
* @param {Event} event - Event passed down by event handler
|
||||
*/
|
||||
onBuffer(){
|
||||
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{
|
||||
/**
|
||||
* 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));
|
||||
|
|
@ -222,8 +330,16 @@ class rawFileBase extends mediaHandler{
|
|||
}
|
||||
}
|
||||
|
||||
//Off air static 'player'
|
||||
/**
|
||||
* 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);
|
||||
|
|
@ -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{
|
||||
/**
|
||||
* 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');
|
||||
|
|
@ -319,7 +444,17 @@ class rawFileHandler extends rawFileBase{
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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');
|
||||
|
|
@ -469,7 +604,9 @@ class youtubeEmbedHandler extends mediaHandler{
|
|||
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){
|
||||
switch(event.data){
|
||||
//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{
|
||||
/**
|
||||
* 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);
|
||||
|
|
@ -554,7 +702,17 @@ class hlsBase extends rawFileBase{
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
|
|
|
|||
|
|
@ -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/>.*/
|
||||
|
||||
/**
|
||||
* Class for objects which represent Canopy Player UX
|
||||
* Class which represents Canopy Player UX
|
||||
*/
|
||||
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/>.*/
|
||||
|
||||
/**
|
||||
* Class for object containing logic behind userlist UX
|
||||
* Class containing logic behind userlist UX
|
||||
*/
|
||||
class userList{
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue