diff --git a/src/app/channel/media/queue.js b/src/app/channel/media/queue.js
index f4cfe3e..83eb236 100644
--- a/src/app/channel/media/queue.js
+++ b/src/app/channel/media/queue.js
@@ -596,7 +596,7 @@ class queue{
}
//Find our media, don't remove it yet since we want to do some more testing first
- const media = this.getItemByUUID(uuid);
+ let media = this.getItemByUUID(uuid);
//If we got a bad request
if(media == null){
@@ -611,27 +611,31 @@ class queue{
//If someone is trying to re-schedule something that starts in the past
if(media.startTime < new Date().getTime()){
- //If an originating socket was provided for this request
- if(socket != null){
- //If the item is currently playing
- if(media.getEndTime() > new Date().getTime()){
- //Yell at the user for being an asshole
- loggerUtils.socketErrorHandler(socket, "You cannot move an actively playing video!", "queue");
- //Otherwise, if it's already ended
- }else{
+ //If the item is currently playing
+ if(media.getEndTime() > new Date().getTime()){
+ //Dupe media for the rest of the function
+ media = media.clone();
+
+ //Stop current item
+ await this.stop(socket, chanDB);
+
+ //Otherwise, if it's already ended
+ }else{
+ //If an originating socket was provided for this request
+ if(socket != null){
//Yell at the user for being an asshole
loggerUtils.socketErrorHandler(socket, "You cannot alter the past!", "queue");
}
+
+ //Ignore it
+ return;
}
-
-
- //Ignore it
- return;
+ //If the item has yet to be played
+ }else{
+ //Remove the media from the schedule
+ await this.removeMedia(uuid, socket, chanDB);
}
- //Remove the media from the schedule
- await this.removeMedia(uuid, socket, chanDB);
-
//Grab the old start time for safe keeping
const oldStart = media.startTime;
@@ -1438,9 +1442,10 @@ class queue{
/**
* Stops currently playing media item
* @param {Socket} socket - Requesting Socket
+ * @param {Mongoose.Document} chanDB - Pass through Channel Document to save on DB Transactions
* @returns returns false if there is nothing to stop
*/
- stop(socket){
+ async stop(socket, chanDB){
//If we're not currently playing anything
if(this.nowPlaying == null){
//If an originating socket was provided for this request
@@ -1462,7 +1467,7 @@ class queue{
}
//End the media
- this.end();
+ await this.end(false, false, false, chanDB);
}
/**
diff --git a/src/app/channel/media/queuedMedia.js b/src/app/channel/media/queuedMedia.js
index c92d7d0..863c770 100644
--- a/src/app/channel/media/queuedMedia.js
+++ b/src/app/channel/media/queuedMedia.js
@@ -119,6 +119,25 @@ class queuedMedia extends media{
this.uuid = crypto.randomUUID();
}
+ /**
+ * Generates a unique clone of a given media object
+ * @returns unique clone of media object
+ */
+ clone(){
+ return new queuedMedia(
+ this.title,
+ this.fileName,
+ this.url,
+ this.id,
+ this.type,
+ this.duration,
+ this.rawLink,
+ this.startTime,
+ this.startTimeStamp,
+ this.earlyEnd
+ );
+ }
+
/**
* return the end time of a given queuedMedia object
* @param {boolean} fullTime - Overrides early ends
diff --git a/www/js/channel/panels/queuePanel/queuePanel.js b/www/js/channel/panels/queuePanel/queuePanel.js
index 9bb91f4..5fb159e 100644
--- a/www/js/channel/panels/queuePanel/queuePanel.js
+++ b/www/js/channel/panels/queuePanel/queuePanel.js
@@ -956,16 +956,25 @@ class queuePanel extends panelObj{
//Get current start time
const start = this.dateByOffset(target.offsetTop);
+ const end = new Date(start.getTime() + (target.dataset['duration'] * 1000));
//Position timetip
timetip.moveToMouse(event);
- //Inject timetip label
- //Normally wouldn't do innerHTML but these values are calculated serverside and it saves us making a
element
- timetip.tooltip.innerHTML = [
+ //Normally wouldn't do innerHTML but these values are calculated serverside and it saves us making a
dom node
+ let timetipContents = [
`Start Time: ${utils.ux.timeStringFromDate(start, true)}`,
- `End Time: ${utils.ux.timeStringFromDate(new Date(start.getTime() + (target.dataset['duration'] * 1000)), true)}`
- ].join('
');
+ `End Time: ${utils.ux.timeStringFromDate(end, true)}`
+ ];
+
+ //If the current time is after the start date, but before the end (we're scheduling to start now)
+ if(start.getTime() < date.getTime() && end.getTime() > date.getTime()){
+ //Add start timestamp to item
+ timetipContents.push(`Start Timestamp: ${utils.ux.humieFriendlyDuration((date.getTime() - start.getTime()) / 1000, true)}`);
+ }
+
+ //Inject timetip label
+ timetip.tooltip.innerHTML = timetipContents.join('
')
//Calculate offset from rest of window
const windowOffset = this.queueContainer.offsetTop + this.ownerDoc.defaultView.scrollY;
diff --git a/www/js/utils.js b/www/js/utils.js
index e7bfce2..c8d7508 100644
--- a/www/js/utils.js
+++ b/www/js/utils.js
@@ -99,7 +99,7 @@ class canopyUXUtils{
return outString;
}
- humieFriendlyDuration(seconds){
+ humieFriendlyDuration(seconds, compact = false){
//If we have an invalid duration
if(seconds <= 0){
//bitch, moan, and complain!
@@ -119,41 +119,62 @@ class canopyUXUtils{
//Remove recorded minutes
seconds -= minutes * 60;
- //If we have an hour
- if(hours == 1){
- //Add the string
- timeStrings.push('1 Hour');
- //If we have hours
- }else if(hours > 0){
- //Add the string
- timeStrings.push(`${hours} Hours`);
+ //If we're rendering compact, alarm-clock style duration
+ if(compact){
+ if(hours > 0){
+ //Push hours, pad start with 0
+ timeStrings.push(String(hours).padStart(2, '0'));
+ }
+
+ if(hours > 0 || minutes > 0){
+ //Push minutes, pad start with 0
+ timeStrings.push(String(minutes).padStart(2, '0'));
+ }
+
+ if(hours > 0 || minutes > 0 || seconds > 0){
+ //Push seconds, pre-fix a 00: if hours and minutes are empty, round to nearest int and pad start with 0
+ timeStrings.push(`${(hours == 0 && minutes == 0) ? '00:' : ''}${String(Math.round(seconds)).padStart(2, '0')}`);
+ }
+
+ return timeStrings.join(':');
+ //If we're rendering out using our words
+ }else{
+ //If we have an hour
+ if(hours == 1){
+ //Add the string
+ timeStrings.push('1 Hour');
+ //If we have hours
+ }else if(hours > 0){
+ //Add the string
+ timeStrings.push(`${hours} Hours`);
+ }
+
+ //If we have a minute
+ if(minutes == 1){
+ //Add the string
+ timeStrings.push('1 Minute');
+ //If we have minutes
+ }else if(minutes > 0){
+ //Add the string
+ timeStrings.push(`${minutes} Minutes`);
+ }
+
+ //Add the 'and ' if we need it
+ const secondsPrefix = timeStrings.length > 0 ? 'and ' : '';
+
+ //If we have a second
+ if(seconds == 1){
+ //Add the string
+ timeStrings.push(`${secondsPrefix}1 Second`);
+ //If we have more than a second
+ }else if(seconds > 1){
+ //Add the string
+ timeStrings.push(`${secondsPrefix}${Math.round(seconds)} Seconds`);
+ }
+
+ //Join the time strings together
+ return timeStrings.join(', ');
}
-
- //If we have a minute
- if(minutes == 1){
- //Add the string
- timeStrings.push('1 Minute');
- //If we have minutes
- }else if(minutes > 0){
- //Add the string
- timeStrings.push(`${minutes} Minutes`);
- }
-
- //Add the 'and ' if we need it
- const secondsPrefix = timeStrings.length > 0 ? 'and ' : '';
-
- //If we have a second
- if(seconds == 1){
- //Add the string
- timeStrings.push(`${secondsPrefix}1 Second`);
- //If we have more than a second
- }else if(seconds > 1){
- //Add the string
- timeStrings.push(`${secondsPrefix}${Math.round(seconds)} Seconds`);
- }
-
- //Join the time strings together
- return timeStrings.join(', ');
}
//Update this and popup class to use nodes