Continued work on media schedule panel.
This commit is contained in:
parent
42c20455e5
commit
07d1a37453
|
|
@ -14,6 +14,7 @@ GNU Affero General Public License for more details.
|
||||||
You should have received a copy of the GNU Affero General Public License
|
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/>. %>
|
along with this program. If not, see <https://www.gnu.org/licenses/>. %>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/panel/queue.css">
|
<link rel="stylesheet" type="text/css" href="/css/panel/queue.css">
|
||||||
|
<div id="queue-panel-layout-controller">
|
||||||
<div id="queue-controls">
|
<div id="queue-controls">
|
||||||
<span id="queue-media-prompts">
|
<span id="queue-media-prompts">
|
||||||
<div class="panel-control-prompt control-prompt">
|
<div class="panel-control-prompt control-prompt">
|
||||||
|
|
@ -27,4 +28,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="queue">
|
<div id="queue">
|
||||||
|
<div id="queue-marker-container"></div>
|
||||||
|
<div id="queue-container"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -242,14 +242,12 @@ span.user-entry{
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
overflow-y: auto;
|
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
width: 75%;
|
width: 75%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#cpanel-pinned-div{
|
#cpanel-pinned-div{
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow-y: auto;
|
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
.cpanel-div{
|
.cpanel-div{
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cpanel-header-div{
|
.cpanel-header-div{
|
||||||
|
|
@ -38,3 +39,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
.cpanel-header-icon{
|
.cpanel-header-icon{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cpanel-doc{
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cpanel-body{
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cpanel-div{
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
@ -13,18 +13,36 @@ GNU Affero General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
#queue{
|
#queue-panel-layout-controller{
|
||||||
position: relative;
|
display: flex;
|
||||||
display: grid;
|
flex-direction: column;
|
||||||
grid-template-columns: auto 75%;
|
overflow-y: auto;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#queue{
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: row;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#queue-container{
|
||||||
|
position: relative;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#queue-marker-container{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-grow: 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
div.queue-marker{
|
div.queue-marker{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
grid-column: 1;
|
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,12 +54,29 @@ span.queue-marker{
|
||||||
|
|
||||||
div.queue-entry{
|
div.queue-entry{
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin: 1.5em 0.5em;
|
position: absolute;
|
||||||
grid-column: 2;
|
margin: 0 1em;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.queue-entry a{
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
#time-marker{
|
#time-marker{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#queue-marker-scale-label{
|
||||||
|
position: absolute;
|
||||||
|
top: 25%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 3em;
|
||||||
}
|
}
|
||||||
|
|
@ -47,6 +47,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
--danger-glow0: 2px 2px 3px var(--danger0), -2px 2px 3px var(--danger0), 2px -2px 3px var(--danger0), -2px -2px 3px var(--danger0);
|
--danger-glow0: 2px 2px 3px var(--danger0), -2px 2px 3px var(--danger0), 2px -2px 3px var(--danger0), -2px -2px 3px var(--danger0);
|
||||||
--danger-glow0-alt1: 2px 2px 3px var(--danger0-alt1), -2px 2px 3px var(--danger0-alt1), 2px -2px 3px var(--danger0-alt1), -2px -2px 3px var(--danger0-alt1);
|
--danger-glow0-alt1: 2px 2px 3px var(--danger0-alt1), -2px 2px 3px var(--danger0-alt1), 2px -2px 3px var(--danger0-alt1), -2px -2px 3px var(--danger0-alt1);
|
||||||
|
|
||||||
|
--timer-glow: -2px 1px 3px var(--danger0-alt1), 2px -1px 3px var(--danger0-alt1);
|
||||||
|
|
||||||
--userlist-color0:rgb(63, 121, 71);
|
--userlist-color0:rgb(63, 121, 71);
|
||||||
--userlist-color1:rgb(143, 46, 26);
|
--userlist-color1:rgb(143, 46, 26);
|
||||||
--userlist-color2:rgb(51, 101, 161);
|
--userlist-color2:rgb(51, 101, 161);
|
||||||
|
|
@ -464,12 +466,13 @@ span.queue-marker{
|
||||||
|
|
||||||
#time-marker{
|
#time-marker{
|
||||||
background-color: var(--danger0);
|
background-color: var(--danger0);
|
||||||
|
box-shadow: var(--timer-glow);
|
||||||
}
|
}
|
||||||
|
|
||||||
div.queue-entry{
|
div.queue-entry{
|
||||||
margin: 0.2em;
|
margin: 0.2em;
|
||||||
padding: 0 0.7em;
|
padding: 0 0.7em;
|
||||||
border-radius: 1em;
|
border-radius: 0.3em;
|
||||||
background-color: var(--bg1);
|
background-color: var(--bg1);
|
||||||
border: 1px solid var(--accent1);
|
border: 1px solid var(--accent1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,178 @@ class queuePanel extends panelObj{
|
||||||
|
|
||||||
//Store releative scale of items in seconds, defaulting to 30 minute chunks
|
//Store releative scale of items in seconds, defaulting to 30 minute chunks
|
||||||
this.scale = 30 * 60;
|
this.scale = 30 * 60;
|
||||||
|
|
||||||
|
//Create variable to hold rescale timer
|
||||||
|
this.rescaleTimer = null;
|
||||||
|
|
||||||
|
//Define non-input event listeners
|
||||||
|
this.defineListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
docSwitch(){
|
docSwitch(){
|
||||||
|
//Get queue div
|
||||||
|
this.queue = this.panelDocument.querySelector('#queue');
|
||||||
//Get queue container
|
//Get queue container
|
||||||
this.queueContainer = this.panelDocument.querySelector('#queue');
|
this.queueContainer = this.queue.querySelector("#queue-container");
|
||||||
|
//Get queue marker contianer
|
||||||
|
this.queueMarkerContainer = this.queue.querySelector('#queue-marker-container');
|
||||||
|
//Get queue layout controller
|
||||||
|
this.queueLayoutController = this.panelDocument.querySelector('#queue-panel-layout-controller');
|
||||||
|
//Re-acquire time marker
|
||||||
|
this.timeMarker = this.panelDocument.querySelector('#time-marker');
|
||||||
|
|
||||||
|
//Render out the queue
|
||||||
|
this.fullRender();
|
||||||
|
|
||||||
|
//Setup panel input
|
||||||
|
this.setupInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
closer(){
|
||||||
|
//Clear any remaining timers
|
||||||
|
clearTimeout(this.timeMarkerTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
defineListeners(){
|
||||||
|
this.client.socket.on("queue", (data) => {
|
||||||
|
this.renderQueue();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setupInput(){
|
||||||
|
this.queue.addEventListener('wheel', this.scaleScroll.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
scaleScroll(event){
|
||||||
|
if(event.ctrlKey){
|
||||||
|
//Capture inverse scroll wheel direction
|
||||||
|
const scrollDirection = event.wheelDeltaY / Math.abs(event.wheelDeltaY) * -1;
|
||||||
|
|
||||||
|
//Default scale factor to 5 seconds
|
||||||
|
let scaleFactor = 5;
|
||||||
|
|
||||||
|
//Tried to do this with math but couldnt because im bad at math so heres the if statement of shame :(
|
||||||
|
if(this.scale >= 7200){
|
||||||
|
scaleFactor = 3600
|
||||||
|
}else if(this.scale >= 3600){
|
||||||
|
scaleFactor = scrollDirection > 0 ? 3600 : 1800;
|
||||||
|
}else if(this.scale >= 1800){
|
||||||
|
scaleFactor = scrollDirection > 0 ? 1800 : 900;
|
||||||
|
}else if(this.scale == 900){
|
||||||
|
scaleFactor = scrollDirection > 0 ? 900 : 300;
|
||||||
|
}else if(this.scale > 300){
|
||||||
|
//If we're above five minutes use five minutes
|
||||||
|
scaleFactor = 300;
|
||||||
|
}else if(this.scale == 300){
|
||||||
|
//If we're at five minutes scroll up by five minutes or scroll down to one minute
|
||||||
|
scaleFactor = scrollDirection > 0 ? 300 : 240;
|
||||||
|
}else if(this.scale == 60){
|
||||||
|
//If we're at one minutes scroll up by four minutes or scroll down by 10 seconds
|
||||||
|
scaleFactor = scrollDirection > 0 ? 240 : 10;
|
||||||
|
}else if(this.scale > 10){
|
||||||
|
scaleFactor = 10;
|
||||||
|
}else if(this.scale == 10){
|
||||||
|
scaleFactor = scrollDirection > 0 ? 10 : 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Prevent page-wide zoom in/out
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
//Clear out the queue UI
|
||||||
|
this.clearQueue();
|
||||||
|
|
||||||
|
|
||||||
|
//Calculate new scale
|
||||||
|
const newScale = this.scale + (scaleFactor * scrollDirection);
|
||||||
|
|
||||||
|
//Clamp scale between 10 seconds and half a day
|
||||||
|
this.scale = Math.max(5, Math.min(43200, newScale));
|
||||||
|
|
||||||
|
//If we have no scale label
|
||||||
|
if(this.scaleLabel == null){
|
||||||
|
//Make it
|
||||||
|
this.scaleLabel = document.createElement('p');
|
||||||
|
this.scaleLabel.id = 'queue-marker-scale-label';
|
||||||
|
this.queue.appendChild(this.scaleLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set scale label text to humie readable time scale
|
||||||
|
this.scaleLabel.innerHTML = `Time Scale:<br>${this.humieFriendlyDuration(this.scale)}`
|
||||||
|
|
||||||
|
//Clear any previous rescale timer
|
||||||
|
clearTimeout(this.rescaleTimer);
|
||||||
|
//Set timeout to re-render after input stops
|
||||||
|
this.rescaleTimer = setTimeout(this.fullRender.bind(this), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
humieFriendlyDuration(seconds){
|
||||||
|
//If we have an invalid duration
|
||||||
|
if(seconds <= 0){
|
||||||
|
//bitch, moan, and complain!
|
||||||
|
return('Invalid input duration');
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create an empty array to hold the time strings
|
||||||
|
const timeStrings = [];
|
||||||
|
|
||||||
|
//Pull hours from time
|
||||||
|
const hours = Math.floor(seconds / 3600);
|
||||||
|
//Remove recorded hours
|
||||||
|
seconds -= hours * 3600;
|
||||||
|
|
||||||
|
//Pull minutes from time
|
||||||
|
const minutes = Math.floor(seconds / 60);
|
||||||
|
//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 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}${seconds} Seconds`);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Join the time strings together
|
||||||
|
return timeStrings.join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
clearQueue(){
|
||||||
|
//Clear out queue container
|
||||||
|
this.queueContainer.innerHTML = '';
|
||||||
|
//Clear out queue marker container
|
||||||
|
this.queueMarkerContainer.innerHTML = '';
|
||||||
|
|
||||||
|
|
||||||
|
//Clear any marker timers
|
||||||
|
clearTimeout(this.timeMarkerTimer);
|
||||||
|
|
||||||
//If we have an existing time marker
|
//If we have an existing time marker
|
||||||
if(this.timeMarker != null){
|
if(this.timeMarker != null){
|
||||||
|
|
@ -16,28 +183,46 @@ class queuePanel extends panelObj{
|
||||||
this.timeMarker.remove();
|
this.timeMarker.remove();
|
||||||
this.timeMarker = null;
|
this.timeMarker = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Render out the queue
|
|
||||||
this.renderQueue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
closer(){
|
async fullRender(date = new Date()){
|
||||||
//Clear any remaining timers
|
|
||||||
clearTimeout(this.renderTimeMarker);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderQueue(date = new Date()){
|
//Clear the queue
|
||||||
//Clear out queue container
|
this.clearQueue();
|
||||||
this.queueContainer.innerHTML = '';
|
|
||||||
|
//If we have a scale label
|
||||||
|
if(this.scaleLabel != null){
|
||||||
|
//Take it out
|
||||||
|
this.scaleLabel.remove();
|
||||||
|
this.scaleLabel = null;
|
||||||
|
}
|
||||||
|
|
||||||
//Render out time scale
|
//Render out time scale
|
||||||
this.renderQueueScale(date);
|
this.renderQueueScale(date);
|
||||||
|
|
||||||
|
//wait a few frames so the scale can finish rendering, because dom function aren't async for some fucking reason
|
||||||
|
for(let i = 0; i <= 2; i++){
|
||||||
|
await utils.awaitNextFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
//render the time marker
|
||||||
|
this.renderTimeMarker(date);
|
||||||
|
|
||||||
|
//render out the queue
|
||||||
|
this.renderQueue(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderQueue(date = new Date()){
|
||||||
|
//for every entry in the queue
|
||||||
for(let entry of this.client.queue){
|
for(let entry of this.client.queue){
|
||||||
//Create entry div
|
//Create entry div
|
||||||
const entryDiv = document.createElement('div');
|
const entryDiv = document.createElement('div');
|
||||||
entryDiv.classList.add('queue-entry');
|
entryDiv.classList.add('queue-entry');
|
||||||
|
|
||||||
|
//Place entry div
|
||||||
|
entryDiv.style.top = `${this.offsetByDate(new Date(entry[1].startTime))}px`;
|
||||||
|
entryDiv.style.bottom = `${this.offsetByDate(new Date(entry[1].startTime + (entry[1].duration * 1000)), true)}px`;
|
||||||
|
|
||||||
//Create entry title
|
//Create entry title
|
||||||
const entryTitle = document.createElement('a');
|
const entryTitle = document.createElement('a');
|
||||||
entryTitle.textContent = entry[1].title;
|
entryTitle.textContent = entry[1].title;
|
||||||
|
|
@ -52,42 +237,50 @@ class queuePanel extends panelObj{
|
||||||
}
|
}
|
||||||
|
|
||||||
renderTimeMarker(date = new Date()){
|
renderTimeMarker(date = new Date()){
|
||||||
//Pull start of day epoch from given date
|
//Calculate marker position by date
|
||||||
const dayEpoch = structuredClone(date).setHours(0,0,0,0);
|
const markerPosition = Math.round(this.offsetByDate(date));
|
||||||
//Get difference to get time since the start of the current day in seconds
|
|
||||||
const curTime = date.getTime() - dayEpoch;
|
|
||||||
//Get time in day as a float between 0 and 1
|
|
||||||
const timeFloat = curTime / 86400000;
|
|
||||||
//Get queue markers
|
|
||||||
const markers = this.panelDocument.querySelectorAll('span.queue-marker');
|
|
||||||
|
|
||||||
//If the marker is null for some reason
|
//If markers are null
|
||||||
if(markers[0] == null){
|
if(markerPosition == null){
|
||||||
//Try again in a second since the user probably just popped the panel or something :P
|
//Try again in a second since the user probably just popped the panel or something :P
|
||||||
(smackTimer.bind(this))();
|
(smackTimer.bind(this))();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//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];
|
|
||||||
//Get marker position relative to parent
|
|
||||||
const markerPosition = (offsetMax * timeFloat) + range[0];
|
|
||||||
|
|
||||||
//if we need to make the time marker
|
//if we need to make the time marker
|
||||||
if(this.timeMarker == null){
|
if(this.timeMarker == null){
|
||||||
//Create time marker
|
//Create the time marker
|
||||||
this.timeMarker = document.createElement('span');
|
this.timeMarker = document.createElement('span');
|
||||||
//Add time marker class
|
//Add time marker class
|
||||||
this.timeMarker.id = 'time-marker';
|
this.timeMarker.id = 'time-marker';
|
||||||
//Append time marker
|
//Append time marker
|
||||||
this.queueContainer.appendChild(this.timeMarker);
|
this.queue.appendChild(this.timeMarker);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set time marker position
|
//Set time marker position
|
||||||
this.timeMarker.style.top = `${markerPosition}px`;
|
this.timeMarker.style.top = `${markerPosition}px`;
|
||||||
|
|
||||||
|
//If the panel document isn't null (we're not actively switching panels)
|
||||||
|
if(this.panelDocument != null){
|
||||||
|
//Grab the current owner document object
|
||||||
|
const ownerDoc = this.panelDocument.ownerDocument == null ? this.panelDocument : this.panelDocument.ownerDocument;
|
||||||
|
|
||||||
|
//Get height difference between window and queue layout controller
|
||||||
|
const docDifference = ownerDoc.defaultView.innerHeight - this.queueLayoutController.getBoundingClientRect().height;
|
||||||
|
//Calculate scroll target by body difference and marker position
|
||||||
|
const scrollTarget = (markerPosition - (this.queueLayoutController.getBoundingClientRect().height - docDifference) / 2) + docDifference;
|
||||||
|
//Calculate scroll behavior by distance
|
||||||
|
const scrollBehavior = Math.abs(scrollTarget - this.queueLayoutController.scrollTop) > 10 ? "smooth" : "instant";
|
||||||
|
|
||||||
|
|
||||||
|
//Scroll to the marker
|
||||||
|
this.queueLayoutController.scroll({
|
||||||
|
left: 0,
|
||||||
|
top: scrollTarget,
|
||||||
|
behavior: scrollBehavior
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set the timer to run the function again
|
||||||
(smackTimer.bind(this))();
|
(smackTimer.bind(this))();
|
||||||
|
|
||||||
function smackTimer(){
|
function smackTimer(){
|
||||||
|
|
@ -102,7 +295,7 @@ class queuePanel extends panelObj{
|
||||||
//Make sure we don't modify the date we're handed
|
//Make sure we don't modify the date we're handed
|
||||||
const date = structuredClone(inputDate);
|
const date = structuredClone(inputDate);
|
||||||
|
|
||||||
//Zero out date to midnight
|
//Zero out time to midnight on the morning of the input date
|
||||||
date.setHours(0,0,0,0);
|
date.setHours(0,0,0,0);
|
||||||
|
|
||||||
//Store epoch of current date at midnight for later user
|
//Store epoch of current date at midnight for later user
|
||||||
|
|
@ -152,18 +345,32 @@ class queuePanel extends panelObj{
|
||||||
markerSpan.appendChild(marker);
|
markerSpan.appendChild(marker);
|
||||||
|
|
||||||
//Append marker span to queue container
|
//Append marker span to queue container
|
||||||
this.queueContainer.appendChild(markerSpan);
|
this.queueMarkerContainer.appendChild(markerSpan);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Easiest way to wait for DOM to do it's thing is to:
|
offsetByDate(date = new Date(), bottomOffset = false){
|
||||||
//fires before next frame
|
//Pull start of day epoch from given date
|
||||||
requestAnimationFrame(()=>{
|
const dayEpoch = structuredClone(date).setHours(0,0,0,0);
|
||||||
//fires before next-next frame (after next frame)
|
//Get difference between now and day epoch to get time since the start of the current day in milliseconds
|
||||||
requestAnimationFrame(()=>{
|
const curTime = date.getTime() - dayEpoch;
|
||||||
//render the time marker
|
//Devide by amount of milliseconds in a day to convert time over to a floating point number between 0 and 1
|
||||||
this.renderTimeMarker(inputDate);
|
//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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -209,7 +209,7 @@ class player{
|
||||||
this.toggleUI(true);
|
this.toggleUI(true);
|
||||||
clearTimeout(this.uiTimer);
|
clearTimeout(this.uiTimer);
|
||||||
if(!this.onUI){
|
if(!this.onUI){
|
||||||
this.uiTimer = setTimeout(this.toggleUI.bind(this), 1500, false);
|
//this.uiTimer = setTimeout(this.toggleUI.bind(this), 1500, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,20 @@ class canopyUtils{
|
||||||
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/escape */
|
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/escape */
|
||||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async awaitNextFrame(){
|
||||||
|
//return a new promise
|
||||||
|
return new Promise((resolve)=>{
|
||||||
|
//Before the next frame
|
||||||
|
requestAnimationFrame(()=>{
|
||||||
|
//fires before next-next frame (after next frame)
|
||||||
|
requestAnimationFrame(()=>{
|
||||||
|
//resolve the promise
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class canopyUXUtils{
|
class canopyUXUtils{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue