Added proper handling of items that begin late and end early.
This commit is contained in:
parent
330c4c275b
commit
179a10fb72
5 changed files with 286 additions and 69 deletions
|
|
@ -505,18 +505,36 @@ div.queue-entry{
|
|||
background-color: var(--bg2-alt1);
|
||||
}
|
||||
|
||||
div.started-before-today{
|
||||
div.started-yesterday{
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-top: 1px dashed var(--accent1);
|
||||
}
|
||||
|
||||
div.ends-after-today{
|
||||
div.ends-tomorrow{
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom: 1px dashed var(--accent1);
|
||||
}
|
||||
|
||||
div.started-late{
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-top: 1px dashed var(--danger0-alt1);
|
||||
}
|
||||
|
||||
div.ended-early{
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom: 1px dashed var(--danger0-alt1);
|
||||
}
|
||||
|
||||
div.now-playing{
|
||||
color: var(--focus0);
|
||||
box-shadow: var(--focus-glow0);
|
||||
text-shadow: var(--focus-glow0);
|
||||
}
|
||||
|
||||
/* altcha theming*/
|
||||
div.altcha{
|
||||
box-shadow: 4px 4px 1px var(--bg1-alt0) inset;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ class queuePanel extends panelObj{
|
|||
this.client.socket.on("clientMetadata", (data) => {this.renderQueue();});
|
||||
this.client.socket.on("queue", (data) => {this.renderQueue();});
|
||||
this.client.socket.on("lock", this.handleScheduleLock.bind(this));
|
||||
this.client.socket.on("error", this.handleQueueError.bind(this));
|
||||
}
|
||||
|
||||
setupInput(){
|
||||
|
|
@ -123,6 +124,26 @@ class queuePanel extends panelObj{
|
|||
}
|
||||
}
|
||||
|
||||
handleQueueError(data){
|
||||
//Create a flag to reload the queue
|
||||
let reloadQueue = false;
|
||||
|
||||
//Check errors
|
||||
for(let error of data.errors){
|
||||
//If we have a queue error
|
||||
if(error.type == "queue"){
|
||||
//Throw the reload flag
|
||||
reloadQueue = true;
|
||||
}
|
||||
}
|
||||
|
||||
//If we need to reload the queue
|
||||
if(reloadQueue){
|
||||
//Do so
|
||||
this.renderQueue();
|
||||
}
|
||||
}
|
||||
|
||||
/* queue control button functions */
|
||||
toggleAddMedia(event){
|
||||
//If the div is hidden
|
||||
|
|
@ -491,13 +512,13 @@ class queuePanel extends panelObj{
|
|||
entryDiv.style.top = `${this.offsetByDate(dawn)}px`;
|
||||
|
||||
//Run apply the rest of the styling rules
|
||||
entryDiv.classList.add('started-before-today');
|
||||
entryDiv.classList.add('started-yesterday');
|
||||
}
|
||||
|
||||
//If the item ends today
|
||||
if(endsToday){
|
||||
//Place the bottom of the entry div based on time
|
||||
entryDiv.style.bottom = `${this.offsetByDate(new Date(entry[1].startTime + (entry[1].duration * 1000)), true)}px`;
|
||||
entryDiv.style.bottom = `${this.offsetByDate(new Date(this.getMediaEnd(entry[1])), true)}px`;
|
||||
}else{
|
||||
//Get midnight
|
||||
const dusk = new Date();
|
||||
|
|
@ -507,7 +528,17 @@ class queuePanel extends panelObj{
|
|||
entryDiv.style.bottom = `${this.offsetByDate(dusk, true)}px`;
|
||||
|
||||
//Run apply the rest of the styling rules
|
||||
entryDiv.classList.add('ends-after-today');
|
||||
entryDiv.classList.add('ends-tomorrow');
|
||||
}
|
||||
|
||||
//If we started in the middle of the video
|
||||
if(entry[1].startTimeStamp > 0){
|
||||
entryDiv.classList.add('started-late');
|
||||
}
|
||||
|
||||
//If we ended early
|
||||
if(entry[1].earlyEnd != null){
|
||||
entryDiv.classList.add('ended-early');
|
||||
}
|
||||
|
||||
//Create entry title
|
||||
|
|
@ -526,8 +557,8 @@ class queuePanel extends panelObj{
|
|||
`File Name: ${entry[1].fileName}`,
|
||||
`Source: ${entry[1].type}`,
|
||||
`Duration: ${entry[1].duration}`,
|
||||
`Start Time: ${new Date(entry[1].startTime).toLocaleString()}`,
|
||||
`End Time: ${new Date(entry[1].startTime + (entry[1].duration * 1000)).toLocaleString()}`
|
||||
`Start Time: ${new Date(entry[1].startTime).toLocaleString()}${entry[1].startTimeStamp == 0 ? '' : ' (Started Late)'}`,
|
||||
`End Time: ${new Date(this.getMediaEnd(entry[1])).toLocaleString()}`
|
||||
]){
|
||||
//Create a 'p' node
|
||||
const component = document.createElement('p');
|
||||
|
|
@ -546,14 +577,29 @@ class queuePanel extends panelObj{
|
|||
}
|
||||
});
|
||||
|
||||
//context menu
|
||||
const menuMap = new Map([
|
||||
["Play now", ()=>{this.client.socket.emit('move', {uuid: entry[1].uuid})}],
|
||||
["Move To...", (event)=>{new reschedulePopup(event, this.client, entry[1], null, this.ownerDoc)}],
|
||||
["Delete", ()=>{this.client.socket.emit('delete', {uuid: entry[1].uuid})}],
|
||||
["Open in New Tab", ()=>{window.open(entry[1].url, '_blank').focus();}],
|
||||
["Copy URL", ()=>{navigator.clipboard.writeText(entry[1].url);}],
|
||||
]);
|
||||
//Create context menu map
|
||||
const menuMap = new Map();
|
||||
|
||||
//If the item hasn't started yet
|
||||
if(entry[1].startTime > new Date().getTime()){
|
||||
//Add 'Play' option to context menu
|
||||
menuMap.set("Play now", ()=>{this.client.socket.emit('move', {uuid: entry[1].uuid})});
|
||||
//Add 'Move To...' option to context menu
|
||||
menuMap.set("Move To...", (event)=>{new reschedulePopup(event, this.client, entry[1], null, this.ownerDoc)});
|
||||
//Otherwise, if the item is currently playing
|
||||
}else if(this.getMediaEnd(entry[1]) > new Date().getTime()){
|
||||
//Add 'Stop' option to context menu
|
||||
menuMap.set("Stop", ()=>{this.client.socket.emit('stop', {uuid: entry[1].uuid})});
|
||||
//Add the Now Playing glow, not the prettiest place to add this, but why let a good conditional go to waste?
|
||||
entryDiv.classList.add('now-playing');
|
||||
}
|
||||
|
||||
//Add 'Delete' option to context menu
|
||||
menuMap.set("Delete", ()=>{this.client.socket.emit('delete', {uuid: entry[1].uuid})})
|
||||
//Add 'New Tab' option to context menu
|
||||
menuMap.set("Open in New Tab", ()=>{window.open(entry[1].url, '_blank').focus();})
|
||||
//Add 'Copy URL' option to context menu
|
||||
menuMap.set("Copy URL", ()=>{navigator.clipboard.writeText(entry[1].url);})
|
||||
|
||||
//Setup drag n drop
|
||||
entryDiv.addEventListener('mousedown', clickEntry.bind(this));
|
||||
|
|
@ -582,8 +628,29 @@ class queuePanel extends panelObj{
|
|||
return;
|
||||
}
|
||||
|
||||
//Create variables to hold width and height
|
||||
const height = event.target.offsetHeight;
|
||||
//Grab existing height
|
||||
let height = event.target.offsetHeight;
|
||||
let cutoffOffset = 0;
|
||||
|
||||
//If the item got cut-off at the bottom
|
||||
if(event.target.classList.contains("ends-tomorrow") || event.target.classList.contains("ended-early")){
|
||||
//Calculate height from duration
|
||||
height = this.offsetByMilliseconds(Number(event.target.dataset['duration']) * 1000);
|
||||
//If the item got cut-off at the top
|
||||
}else if(event.target.classList.contains('started-yesterday') || event.target.classList.contains("started-late")){
|
||||
//Keep old height for now
|
||||
const oldHeight = height;
|
||||
|
||||
//Calculate height from duration
|
||||
height = this.offsetByMilliseconds(Number(event.target.dataset['duration']) * 1000);
|
||||
|
||||
//Calculate the mouse offset needed to keep it properly placed relative to the original click point
|
||||
cutoffOffset = height - oldHeight;
|
||||
}
|
||||
|
||||
//Remove any cut-off borders
|
||||
event.target.classList.remove('ends-tomorrow', 'started-yesterday', 'ended-early', 'started-late');
|
||||
|
||||
|
||||
//If we havent set height or width
|
||||
if(event.target.style.height == ""){
|
||||
|
|
@ -611,7 +678,7 @@ class queuePanel extends panelObj{
|
|||
this.ownerDoc.body.style.userSelect = 'none';
|
||||
|
||||
//Save top of target relative to window minus the mouse position as our drag offset
|
||||
event.target.dataset['dragoffset'] = (event.target.offsetTop + this.ownerDoc.defaultView.scrollY) - event.clientY;
|
||||
event.target.dataset['dragoffset'] = (event.target.offsetTop + this.ownerDoc.defaultView.scrollY) - event.clientY - cutoffOffset;
|
||||
|
||||
//Call the drag entry function to move the entry on click without re-writing the wheel
|
||||
(dragEntry.bind(this))(event, event.target, timetip);
|
||||
|
|
@ -711,7 +778,7 @@ class queuePanel extends panelObj{
|
|||
|
||||
function dropEntry(event, target, timetip){
|
||||
//Gross but works :P
|
||||
if(!target.isConnected){
|
||||
if(!target.isConnected || target.dataset['drag'] != "true"){
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -861,24 +928,9 @@ class queuePanel extends panelObj{
|
|||
const dayEpoch = new Date(date).setHours(0,0,0,0);
|
||||
//Get difference between now and day epoch to get time since the start of the current day in milliseconds
|
||||
const curTime = date.getTime() - dayEpoch;
|
||||
//Devide by amount of milliseconds in a day to convert time over to a floating point number between 0 and 1
|
||||
//Make sure to reverse it if bottomOffset is set to true
|
||||
const timeFloat = bottomOffset ? 1 - (curTime / 86400000) : curTime / 86400000;
|
||||
//Get queue markers
|
||||
const markers = this.panelDocument.querySelectorAll('span.queue-marker');
|
||||
|
||||
//If the marker is null for some reason
|
||||
if(markers[0] == null){
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
//Get marker position range
|
||||
const range = [markers[0].offsetTop, markers[markers.length - 1].offsetTop]
|
||||
//Get maximum position relative to the range itself
|
||||
const offsetMax = range[1] - range[0];
|
||||
//return position relative to parent
|
||||
return (offsetMax * timeFloat) + range[0];
|
||||
//Calculate the offset from todays milliseconds
|
||||
return this.offsetByMilliseconds(curTime, bottomOffset);
|
||||
}
|
||||
|
||||
dateByOffset(input = 0){
|
||||
|
|
@ -902,6 +954,38 @@ class queuePanel extends panelObj{
|
|||
//return our date
|
||||
return date;
|
||||
}
|
||||
|
||||
offsetByMilliseconds(input = 0, bottomOffset = false){
|
||||
//Convert amount of milliseconds to a float, 0 representing the start of the day and 1 representing the end.
|
||||
//Make sure to reverse it if bottomOffset is set to true
|
||||
const timeFloat = bottomOffset ? 1 - (input / 86400000) : input / 86400000;
|
||||
|
||||
//Get queue markers
|
||||
const markers = this.panelDocument.querySelectorAll('span.queue-marker');
|
||||
|
||||
//If the marker is null for some reason
|
||||
if(markers[0] == null){
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
//Get marker position range
|
||||
const range = [markers[0].offsetTop, markers[markers.length - 1].offsetTop]
|
||||
//Get maximum position relative to the range itself
|
||||
const offsetMax = range[1] - range[0];
|
||||
//return position relative to parent
|
||||
return (offsetMax * timeFloat) + range[0];
|
||||
}
|
||||
|
||||
getMediaEnd(media){
|
||||
//If we have an early end
|
||||
if(media.earlyEnd != null){
|
||||
return media.startTime + (media.earlyEnd * 1000);
|
||||
//Otherwise
|
||||
}else{
|
||||
return media.startTime + ((media.duration - media.startTimeStamp) * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class schedulePopup{
|
||||
|
|
|
|||
|
|
@ -553,7 +553,19 @@ class canopyUXUtils{
|
|||
}
|
||||
|
||||
|
||||
fixCutoff(standalone = true, pageBreak = document.body.scrollWidth - document.body.getBoundingClientRect().width){
|
||||
fixCutoff(standalone = true, pageBreak){
|
||||
//If we have no pagebreak
|
||||
if(pageBreak == null){
|
||||
//If we have a document body
|
||||
if(document.body != null){
|
||||
pageBreak = document.body.scrollWidth - document.body.getBoundingClientRect().width
|
||||
//Otherwise
|
||||
}else{
|
||||
//Pretend nothing happened because we probably have bigger issues then a fucked up click-dragger cutoff
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Fix the page width
|
||||
if(this.flex){
|
||||
this.element.style.flexBasis = `${this.calcWidth(this.element.getBoundingClientRect().width + pageBreak)}vw`;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue