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

@ -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"){