Finished JSDoc for all of www/js/channel except for www/js/channel/queuePanel.js

This commit is contained in:
rainbow napkin 2025-09-05 05:53:33 -04:00
parent c0f219276f
commit 0e1b48c02c
97 changed files with 12323 additions and 135 deletions

View file

@ -256,8 +256,8 @@ class chatBox{
}
/**
* Concatinate Text into Chat Prompt
* @param {String} text - Text to Concatinate
* Concatenate Text into Chat Prompt
* @param {String} text - Text to Concatenate
*/
catChat(text){
this.chatPrompt.value += text;

View file

@ -13,7 +13,17 @@ 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 representing Emote Panel UX
* @extends panelObj
*/
class emotePanel extends panelObj{
/**
* Instantiates a new Panel Object
* @param {channel} client - Parent client Management Object
* @param {Document} panelDocument - Panel Document
*/
constructor(client, panelDocument){
super(client, "Emote Palette", "/panel/emote", panelDocument);
@ -49,6 +59,9 @@ class emotePanel extends panelObj{
this.renderEmoteLists();
}
/**
* Defines input-related event handlers
*/
setupInput(){
//Make sure to remove any event listeners in-case we moving an already instantiated panel
this.siteEmoteToggle.removeEventListener("click", this.toggleSiteEmotes.bind(this));
@ -76,18 +89,35 @@ class emotePanel extends panelObj{
this.personalEmoteAddButton.addEventListener("click", this.addPersonalEmote.bind(this));
}
/**
* Toggles Site emote display
* @param {Event} event - Event passed down by event listener
*/
toggleSiteEmotes(event){
this.toggleEmotes(this.siteEmoteToggle, this.siteEmoteList);
}
/**
* Toggles Channel emote display
* @param {Event} event - Event passed down by event listener
*/
toggleChanEmotes(event){
this.toggleEmotes(this.chanEmoteToggle, this.chanEmoteList);
}
/**
* Toggles Personal emote display
* @param {Event} event - Event passed down by event listener
*/
togglePersonalEmotes(event){
this.toggleEmotes(this.personalEmoteToggle, this.personalEmoteSection);
}
/**
* Toggles a specified emote list on or off
* @param {Node} icon - Toggle Icon for given list
* @param {Node} list - Emote list container to toggle
*/
toggleEmotes(icon, list){
if(list.checkVisibility()){
icon.classList.replace('bi-caret-down-fill','bi-caret-left-fill');
@ -98,6 +128,10 @@ class emotePanel extends panelObj{
}
}
/**
* Concatenates specified emote into chat prompt input
* @param {String} emote - Emote to concat into chat
*/
useEmote(emote){
//If we're using this from the active panel
if(this.client.cPanel.activePanel == this){
@ -109,6 +143,10 @@ class emotePanel extends panelObj{
this.client.chatBox.catChat(`[${emote}]`);
}
/**
* Requests server to add emote to list of personal emotes
* @param {Event} event - Event passed down by event listener
*/
addPersonalEmote(event){
//Collect input
const name = this.personalEmoteNamePrompt.value;
@ -122,11 +160,18 @@ class emotePanel extends panelObj{
this.client.socket.emit("addPersonalEmote", {name, link});
}
/**
* Requests server to remove emote from list of personal emotes
* @param {String} name - Name of emote to delete
*/
deletePersonalEmote(name){
//send out delete
this.client.socket.emit('deletePersonalEmote', {name});
}
/**
* Renders out emote list to panel document
*/
renderEmoteLists(){
//if we've initialized the search prompt (wont happen yet first run)
if(this.searchPrompt != null){
@ -158,6 +203,12 @@ class emotePanel extends panelObj{
this.renderEmotes(personalEmotes, this.personalEmoteList, true);
}
/**
* Renders out emotes to emote lists
* @param {Array} emoteList - list of emotes to render
* @param {Node} container - Container to render emotes out to
* @param {Boolean} personal - Denotes whether or not we're rendering personal emotes
*/
renderEmotes(emoteList, container, personal = false){
//Clear out the container
container.innerHTML = '';

View file

@ -13,15 +13,36 @@ 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 representing Playlist Manager UX within the Queue Panel
*/
class playlistManager{
/**
*
* @param {channel} client - Parent Client Management Object
* @param {Document} panelDocument - Panel Document
* @param {queuePanel} queuePanel - Parent Queue Panel Object
*/
constructor(client, panelDocument, queuePanel){
//Set client
/**
* Parent Client Management Object
*/
this.client = client;
//Set panel document
/**
* Panel Document
*/
this.panelDocument = panelDocument;
//Set parent queue panel
/**
* Parent Queue Panel Object
*/
this.queuePanel = queuePanel;
//Create openMap
/**
* Map of which playlists are open and which are not, for better refresh handling
*/
this.openMap = {
Channel: new Map(),
User: new Map()
@ -31,6 +52,9 @@ class playlistManager{
this.defineListeners();
}
/**
* Handles Network-Related Event Listeners
*/
defineListeners(){
this.client.socket.on("chanPlaylists", this.renderChannelPlaylists.bind(this));
this.client.socket.on("userPlaylists", this.renderUserPlaylists.bind(this));
@ -56,6 +80,9 @@ class playlistManager{
this.setupInput();
}
/**
* Handles Input-Related Event Listeners
*/
setupInput(){
this.createPlaylistSpan.addEventListener('click', (event)=>{new newPlaylistPopup(event, this.client, this.queuePanel.ownerDoc)})
this.channelPlaylistLabel.addEventListener('click', this.toggleChannelPlaylists.bind(this));
@ -63,6 +90,11 @@ class playlistManager{
}
/* queue control button functions */
/**
* Toggle Channel Playlists
* @param {Event} event - Event passed down from Event Listener
*/
toggleChannelPlaylists(event){
//If the div is hidden
if(this.channelPlaylistDiv.style.display == 'none'){
@ -82,7 +114,10 @@ class playlistManager{
}
}
/* queue control button functions */
/**
* Toggle User Playlists
* @param {Event} event - Event passed down from Event Listener
*/
toggleUserPlaylists(event){
//If the div is hidden
if(this.userPlaylistDiv.style.display == 'none'){
@ -102,6 +137,10 @@ class playlistManager{
}
}
/**
* Checks which playlists where open before a refresh and re-opens them
* @param {String} location - Whether or not we're dealing with user or channel playlists
*/
checkOpenPlaylists(location){
//If open map is a string, indicating we just renamed a playlist with it's media open
if(typeof this.openMap[location] == 'string'){
@ -128,6 +167,11 @@ class playlistManager{
}
//Main playlist rendering functions
/**
* Renders Channel Playlist list
* @param {Object} data - Data from server
*/
renderChannelPlaylists(data){
//Check for open playlists
this.checkOpenPlaylists('Channel');
@ -139,6 +183,10 @@ class playlistManager{
this.channelPlaylistDiv.append(...this.renderPlaylists(data, 'Channel'));
}
/**
* Renders User Playlist list
* @param {Object} data - Data from server
*/
renderUserPlaylists(data){
//Check for open playlists
this.checkOpenPlaylists('User');
@ -150,6 +198,12 @@ class playlistManager{
this.userPlaylistDiv.append(...this.renderPlaylists(data, 'User'));
}
/**
* Render set of playlists out to Playlist Management Menu
* @param {Object} data - Data from server
* @param {String} location - Location to load from, either Channel or User
* @returns {Node} Rendered out playlist list
*/
renderPlaylists(data, location){
const playlists = [];
@ -194,6 +248,12 @@ class playlistManager{
}
//aux rendering functions
/**
* Renders Playlist labels
* @param {Object} playlist - Playlist from server to render label for
* @param {String} location - Location of playlist (Channel or User)
* @returns {Node} Rendered out playlist label
*/
renderLabels(playlist, location){
//Create playlist label span
const playlistLabels = document.createElement('span');
@ -247,6 +307,12 @@ class playlistManager{
return playlistLabels;
}
/**
* Renders out Playlist Controls
* @param {Object} playlist - Playlist from server to render label for
* @param {String} location - Location of playlist (Channel or User)
* @returns {Node} Rendered out playlist controls
*/
renderControls(playlist, location){
//Create playlist control span
const playlistControls = document.createElement('span');
@ -336,6 +402,12 @@ class playlistManager{
return playlistControls;
}
/**
* Renders media object out for an entire playlist
* @param {Object} playlist - Playlist from server to render label for
* @param {String} location - Location of playlist (Channel or User)
* @returns {Node} Rendered out playlist
*/
renderMedia(playlist, location){
//Create media container div
const mediaContainer = document.createElement('div');
@ -393,6 +465,13 @@ class playlistManager{
return mediaContainer;
}
/**
* Renders controls out for a single media entry within a playlist
* @param {Object} media - Media object from playlist to render controls for
* @param {Object} playlist - Playlist from server to render label for
* @param {String} location - Location of playlist (Channel or User)
* @returns {Node} Rendered out playlist
*/
renderMediaControls(media, playlist, location){
//Create media control span
const mediaControlSpan = document.createElement('span');
@ -429,6 +508,10 @@ class playlistManager{
return mediaControlSpan;
}
/**
* Toggle Media List
* @param {Event} event - Event passed down from Event Listener
*/
toggleMedia(event){
//Grab playlist title caret
const playlistTitleCaret = event.target.querySelector('i');
@ -453,6 +536,10 @@ class playlistManager{
}
}
/**
* Add URL to playlist
* @param {Event} event - Event passed down from Event Listener
*/
addURL(event){
new addURLPopup(
event,
@ -464,6 +551,11 @@ class playlistManager{
}
//playlist control functions
/**
* Sends request to server to edit default titles
* @param {Event} event - Event passed down from Event Listener
*/
editDefaultTitles(event){
new defaultTitlesPopup(
event,
@ -475,6 +567,10 @@ class playlistManager{
);
}
/**
* Sends request to server to rename playlists
* @param {Event} event - Event passed down from Event Listener
*/
renamePlaylist(event){
new renamePopup(
event,
@ -496,38 +592,75 @@ class playlistManager{
}
}
/**
* Sends request to server to queue all playlist items
* @param {Event} event - Event passed down from Event Listener
*/
queueAll(event){
this.client.socket.emit(`queue${event.target.parentNode.dataset['location']}Playlist`, {playlist: event.target.parentNode.dataset['playlist']});
}
/**
* Sends request to server to queue a playlist item
* @param {Event} event - Event passed down from Event Listener
*/
queueMedia(event){
this.client.socket.emit(`queueFrom${event.target.parentNode.dataset['location']}Playlist`,{playlist: event.target.parentNode.dataset['playlist'], uuid: event.target.parentNode.dataset['uuid']});
}
/**
* Sends request to server to queue a random playlist item
* @param {Event} event - Event passed down from Event Listener
*/
queueRandom(event){
this.client.socket.emit(`queueRandomFrom${event.target.parentNode.dataset['location']}Playlist`,{playlist: event.target.parentNode.dataset['playlist']});
}
/**
* Sends request to server to delete a playlist
* @param {Event} event - Event passed down from Event Listener
*/
deletePlaylist(event){
this.client.socket.emit(`delete${event.target.parentNode.dataset['location']}Playlist`, {playlist: event.target.parentNode.dataset['playlist']});
}
/**
* Sends request to server to delete a playlist item
* @param {Event} event - Event passed down from Event Listener
*/
deleteMedia(event ){
this.client.socket.emit(`delete${event.target.parentNode.dataset['location']}PlaylistMedia`, {playlist: event.target.parentNode.dataset['playlist'], uuid: event.target.parentNode.dataset['uuid']});
}
}
/**
* Class representing pop-up dialogue for creating a new playlist
*/
class newPlaylistPopup{
/**
* Instantiates a New Playlist Popup
* @param {Event} event - Event passed down from Event Listener
* @param {channel} client - Parent Client Management Object
* @param {Document} doc - Current owner documnet of the panel, so we know where to drop our pop-up
*/
constructor(event, client, doc){
//Set Client
/**
* Parent Client Management Object
*/
this.client = client;
//Create media popup and call async constructor when done
//unfortunately we cant call constructors asyncronously, and we cant call back to this from super, so we can't extend this as it stands :(
/**
* canopyUXUtils.popup() object
*/
this.popup = new canopyUXUtils.popup('/newPlaylist', true, this.asyncConstructor.bind(this), doc, false);
}
/**
* Continuation of object construction, called after child popup object construction
*/
asyncConstructor(){
this.name = this.popup.contentDiv.querySelector('#queue-create-playlist-popup-name');
this.defaultTitles = this.popup.contentDiv.querySelector('#queue-create-playlist-popup-default-titles');
@ -537,12 +670,19 @@ class newPlaylistPopup{
this.setupInput();
}
/**
* Defines input-related Event Handlers
*/
setupInput(){
//Setup input
this.saveButton.addEventListener('click', this.createPlaylist.bind(this));
this.popup.popupDiv.addEventListener('keydown', this.createPlaylist.bind(this));
}
/**
* Sends request to create a playlist off to the server
* @param {Event} event - Event passed down from Event Listener
*/
createPlaylist(event){
//If we clicked or hit enter
if(event.key == null || (event.key == "Enter" && this.defaultTitles !== this.popup.doc.activeElement)){
@ -559,22 +699,45 @@ class newPlaylistPopup{
}
}
/**
* Class representing pop-up dialogue which adds media to a given playlist
*/
class addURLPopup{
/**
* Instantiates a new Add URL Pop-up
* @param {Event} event - Event passed down from Event Listener
* @param {String} playlist - Playlist name
* @param {String} location - Location of playlist, either Channel or User
* @param {channel} client - Parent Client Management Object
* @param {Document} doc - Current owner documnet of the panel, so we know where to drop our pop-up
*/
constructor(event, playlist, location, client, doc){
//Set Client
/**
* Parent Client Management Object
*/
this.client = client;
//Set playlist
/**
* Playlist Name
*/
this.playlist = playlist
//Set location
/**
* Location of playlist, either Channel or User
*/
this.location = location;
//Create media popup and call async constructor when done
//unfortunately we cant call constructors asyncronously, and we cant call back to this from super, so we can't extend this as it stands :(
/**
* canopyUXUtils.popup() object
*/
this.popup = new canopyUXUtils.popup('/addToPlaylist', true, this.asyncConstructor.bind(this), doc);
}
/**
* Continuation of object construction, called after child popup object construction
*/
asyncConstructor(){
this.urlPrompt = this.popup.contentDiv.querySelector('#playlist-add-media-popup-prompt');
this.addButton = this.popup.contentDiv.querySelector('#playlist-add-media-popup-button');
@ -582,12 +745,19 @@ class addURLPopup{
this.setupInput();
}
/**
* Defines input-related Event Handlers
*/
setupInput(){
//Setup input
this.addButton.addEventListener('click', this.addToPlaylist.bind(this));
this.popup.popupDiv.addEventListener('keydown', this.addToPlaylist.bind(this));
}
/**
* Handles sending request to add to a playlist to the server
* @param {Event} event - Event passed down from Event Listener
*/
addToPlaylist(event){
//If we clicked or hit enter
if(event.key == null || event.key == "Enter"){
@ -605,25 +775,51 @@ class addURLPopup{
}
}
/**
* Class Representing popup dialogue for changing playlists defualt titles
*/
class defaultTitlesPopup{
/**
* Instantiates a new Default Titles Popup
* @param {Event} event - Event passed down from Event Listener
* @param {String} playlist - Playlist name
* @param {String} titles - List of titles, denoted by newlines
* @param {String} location - Location of playlist, either Channel or User
* @param {channel} client - Parent Client Management Object
* @param {Document} doc - Current owner documnet of the panel, so we know where to drop our pop-up
*/
constructor(event, playlist, titles, location, client, doc){
//Set Client
/**
* Parent Client Management Object
*/
this.client = client;
//Set playlist
/**
* Playlist Name
*/
this.playlist = playlist
//Set location
/**
* Location of playlist, either Channel or User
*/
this.location = location;
//Set title string
/**
* Array of titles to set
*/
this.titles = titles.join('\n');
//Create media popup and call async constructor when done
//unfortunately we cant call constructors asyncronously, and we cant call back to this from super, so we can't extend this as it stands :(
/**
* canopyUXUtils.popup() object
*/
this.popup = new canopyUXUtils.popup('/playlistDefaultTitles', true, this.asyncConstructor.bind(this), doc, false);
}
/**
* Continuation of object construction, called after child popup object construction
*/
asyncConstructor(){
this.titlePrompt = this.popup.contentDiv.querySelector('#playlist-default-titles-popup-prompt');
this.titleButton = this.popup.contentDiv.querySelector('#playlist-default-media-popup-button');
@ -632,12 +828,19 @@ class defaultTitlesPopup{
this.setupInput();
}
/**
* Defines input-related Event Handlers
*/
setupInput(){
//Setup input
this.titleButton.addEventListener('click', this.changeDefaultTitles.bind(this));
this.popup.popupDiv.addEventListener('keydown', this.changeDefaultTitles.bind(this));
}
/**
* Handles sending request to change default titles of playlist to the server
* @param {Event} event - Event passed down from Event Listener
*/
changeDefaultTitles(event){
//If we clicked or hit enter while the prompt wasn't active
if(event.key == null || (event.key == "Enter" && this.titlePrompt !== this.popup.doc.activeElement)){
@ -654,22 +857,45 @@ class defaultTitlesPopup{
}
}
/**
* Class representing pop-up dialogue to rename a playlist
*/
class renamePopup{
/**
* Instantiates a new Rename Pop-up
* @param {Event} event - Event passed down from Event Listener
* @param {String} playlist - Playlist name
* @param {channel} client - Parent Client Management Object
* @param {Document} doc - Current owner documnet of the panel, so we know where to drop our pop-up
* @param {Function} cb - Callback function, passed new name upon rename
*/
constructor(event, playlist, client, doc, cb){
//Set Client
/**
* Parent Client Management Object
*/
this.client = client;
//Set playlist
/**
* Playlist Name
*/
this.playlist = playlist
//Set callback
/**
* Callback Function, passed new name upon rename
*/
this.cb = cb;
//Create media popup and call async constructor when done
//unfortunately we cant call constructors asyncronously, and we cant call back to this from super, so we can't extend this as it stands :(
/**
* canopyUXUtils.popup() object
*/
this.popup = new canopyUXUtils.popup('/renamePlaylist', true, this.asyncConstructor.bind(this), doc);
}
/**
* Continuation of object construction, called after child popup object construction
*/
asyncConstructor(){
this.renamePrompt = this.popup.contentDiv.querySelector('#playlist-rename-popup-prompt');
this.renameButton = this.popup.contentDiv.querySelector('#playlist-rename-popup-button');
@ -677,13 +903,20 @@ class renamePopup{
this.setupInput();
}
/**
* Defines input-related Event Handlers
*/
setupInput(){
//Setup input
this.renameButton.addEventListener('click', this.changeDefaultTitles.bind(this));
this.popup.popupDiv.addEventListener('keydown', this.changeDefaultTitles.bind(this));
this.renameButton.addEventListener('click', this.renamePlaylist.bind(this));
this.popup.popupDiv.addEventListener('keydown', this.renamePlaylist.bind(this));
}
changeDefaultTitles(event){
/**
* Handles sending request to rename playlist to the server
* @param {Event} event - Event passed down from Event Listener
*/
renamePlaylist(event){
//If we clicked or hit enter while the prompt wasn't active
if(event.key == null || event.key == "Enter"){

View file

@ -13,7 +13,17 @@ 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 representing the settings panel
* @extends panelObj
*/
class settingsPanel extends panelObj{
/**
* Instantiates a new Panel Object
* @param {channel} client - Parent client Management Object
* @param {Document} panelDocument - Panel Document
*/
constructor(client, panelDocument){
super(client, "Client Settings", "/panel/settings", panelDocument);
}
@ -28,14 +38,23 @@ class settingsPanel extends panelObj{
this.setupInput();
}
/**
* Defines input-related event handlers
*/
setupInput(){
this.youtubeSource.addEventListener('change', this.updateYoutubeSource.bind(this));
}
/**
* Renders actual user settings state into panel display
*/
renderSettings(){
this.youtubeSource.value = localStorage.getItem("ytPlayerType");
}
/**
* Event handler for Youtube Source selector
*/
updateYoutubeSource(){
localStorage.setItem("ytPlayerType", this.youtubeSource.value);
client.processConfig("ytPlayerType", this.youtubeSource.value);