diff --git a/now-playing/script.js b/now-playing/script.js
index f52886c..f680e7a 100644
--- a/now-playing/script.js
+++ b/now-playing/script.js
@@ -443,7 +443,7 @@ async function UpdatePlayerState(data) {
const isPlaying = (targetSession.playback_info.PlaybackStatus === PlaybackStatus.PLAYING);
const currentPositionMs = isPlaying && timelineProps.EndTime > 0 ? timelineProps.Position + driftMs : timelineProps.Position;
- SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette);
+ SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette, targetSession.playback_info.PlaybackStatus);
}
}
else {
diff --git a/now-playing/settings/settings.json b/now-playing/settings/settings.json
index fa70ba5..39a677f 100644
--- a/now-playing/settings/settings.json
+++ b/now-playing/settings/settings.json
@@ -150,6 +150,14 @@
"showIf": "useCustomColors",
"group": "Appearance"
},
+ {
+ "id": "showWhilePaused",
+ "label": "Show While Paused",
+ "description": "If enabled, the widget will be visible even when the track is paused.",
+ "type": "checkbox",
+ "defaultValue": false,
+ "group": "General"
+ },
{
"id": "autoHide",
"label": "Auto-Hide on Track Change",
@@ -159,11 +167,14 @@
"group": "General"
},
{
- "id": "showWhilePaused",
- "label": "Show While Paused",
- "description": "If enabled, the widget will be visible even when the track is paused.",
- "type": "checkbox",
- "defaultValue": false,
+ "id": "displayDuration",
+ "label": "Display Duration (seconds)",
+ "description": "How long the widget should remain visible.",
+ "type": "number",
+ "min": 1,
+ "max": 60,
+ "defaultValue": 5,
+ "showIf": "autoHide",
"group": "General"
},
{
@@ -224,17 +235,6 @@
"defaultValue": true,
"group": "General"
},
- {
- "id": "displayDuration",
- "label": "Display Duration (seconds)",
- "description": "How long the widget should remain visible.",
- "type": "number",
- "min": 1,
- "max": 60,
- "defaultValue": 5,
- "showIf": "autoHide",
- "group": "General"
- },
{
"id": "showAnimation",
"label": "Show Animation",
diff --git a/now-playing/style.css b/now-playing/style.css
index de16278..f33f7eb 100644
--- a/now-playing/style.css
+++ b/now-playing/style.css
@@ -97,7 +97,7 @@ body {
@keyframes slide-in-from-left {
0% {
- transform: translateX(-1em);
+ transform: translateX(-100%);
opacity: 0;
}
@@ -114,14 +114,14 @@ body {
}
100% {
- transform: translateX(-1em);
+ transform: translateX(-100%);
opacity: 0;
}
}
@keyframes slide-in-from-right {
0% {
- transform: translateX(1em);
+ transform: translateX(100%);
opacity: 0;
}
@@ -138,7 +138,7 @@ body {
}
100% {
- transform: translateX(1em);
+ transform: translateX(100%);
opacity: 0;
}
}
diff --git a/now-playing/themes/album-art/index.html b/now-playing/themes/album-art/index.html
index bfac360..a75a2ec 100644
--- a/now-playing/themes/album-art/index.html
+++ b/now-playing/themes/album-art/index.html
@@ -3,6 +3,11 @@
diff --git a/now-playing/themes/album-art/script.js b/now-playing/themes/album-art/script.js
index e5a82e4..7536fc2 100644
--- a/now-playing/themes/album-art/script.js
+++ b/now-playing/themes/album-art/script.js
@@ -96,7 +96,12 @@ async function ChangeTrack(mediaProps, accentColorPalette) {
}, 250);
}
-function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
+function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette, playbackStatus) {
+ // Set the pause overlay visibility based on playback status
+ if (playbackStatus === PlaybackStatus.PAUSED)
+ albumArtContainer.classList.add('is-paused');
+ else
+ albumArtContainer.classList.remove('is-paused');
// Set progressbar
// Ensure we don't divide by zero or exceed 100%
@@ -105,7 +110,7 @@ function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
progressPercent = Math.min(100, Math.max(0, progressPercent));
progressBar.style.width = `${progressPercent}%`;
if (!useCustomColors)
- progressBar.style.setProperty('--accent-color', accentColorPalette.LightVibrant);
+ document.body.style.setProperty('--accent-color', accentColorPalette.LightVibrant);
else
- progressBar.style.setProperty('--accent-color', color1);
+ document.body.style.setProperty('--accent-color', color1);
}
\ No newline at end of file
diff --git a/now-playing/themes/album-art/style.css b/now-playing/themes/album-art/style.css
index bd86dd2..4c156d2 100644
--- a/now-playing/themes/album-art/style.css
+++ b/now-playing/themes/album-art/style.css
@@ -21,6 +21,36 @@
display: var(--show-album-art);
}
+#album-art-container.is-paused #album-art-layer,
+#album-art-container.is-paused #album-art-transition-layer {
+ opacity: 0.7;
+}
+
+#pause-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.3s ease;
+ z-index: 10;
+ border-radius: inherit;
+}
+
+#pause-overlay svg {
+ height: 30%;
+ width: auto;
+}
+
+#album-art-container.is-paused #pause-overlay {
+ opacity: 1;
+}
+
#album-art-layer,
#album-art-transition-layer {
position: absolute;
diff --git a/now-playing/themes/card/index.html b/now-playing/themes/card/index.html
index 7bcf8c2..99e8297 100644
--- a/now-playing/themes/card/index.html
+++ b/now-playing/themes/card/index.html
@@ -9,6 +9,11 @@
diff --git a/now-playing/themes/card/script.js b/now-playing/themes/card/script.js
index baf4f4c..280bc64 100644
--- a/now-playing/themes/card/script.js
+++ b/now-playing/themes/card/script.js
@@ -84,13 +84,19 @@ async function ChangeTrack(mediaProps, accentColorPalette) {
}, 250);
}
-function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
+function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette, playbackStatus) {
// Update the label using your naming convention
currentTimeLabel.innerText =
ConvertMillisecondsToHoursMinutesSecondsSoItLooksBetterAndNotCringe(currentPositionMs);
durationLabel.innerText =
ConvertMillisecondsToHoursMinutesSecondsSoItLooksBetterAndNotCringe(timelineProps.EndTime);
+
+ // Set the pause overlay visibility based on playback status
+ if (playbackStatus === PlaybackStatus.PAUSED)
+ albumArtContainer.classList.add('is-paused');
+ else
+ albumArtContainer.classList.remove('is-paused');
// Set progressbar
// Ensure we don't divide by zero or exceed 100%
diff --git a/now-playing/themes/card/style.css b/now-playing/themes/card/style.css
index c578d13..f2a8af1 100644
--- a/now-playing/themes/card/style.css
+++ b/now-playing/themes/card/style.css
@@ -23,6 +23,36 @@
display: var(--show-album-art);
}
+#album-art-container.is-paused #album-art-layer,
+#album-art-container.is-paused #album-art-transition-layer {
+ opacity: 0.2;
+}
+
+#pause-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.3s ease;
+ z-index: 10;
+ border-radius: inherit;
+}
+
+#pause-overlay svg {
+ height: 30%;
+ width: auto;
+}
+
+#album-art-container.is-paused #pause-overlay {
+ opacity: 0.8;
+}
+
#album-art-layer,
#album-art-transition-layer {
position: absolute;
diff --git a/now-playing/themes/classic/index.html b/now-playing/themes/classic/index.html
index 5aab0e6..8d366f3 100644
--- a/now-playing/themes/classic/index.html
+++ b/now-playing/themes/classic/index.html
@@ -3,6 +3,11 @@
diff --git a/now-playing/themes/classic/script.js b/now-playing/themes/classic/script.js
index 64b7fd6..2a5c385 100644
--- a/now-playing/themes/classic/script.js
+++ b/now-playing/themes/classic/script.js
@@ -84,13 +84,19 @@ async function ChangeTrack(mediaProps, accentColorPalette) {
}, 250);
}
-function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
+function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette, playbackStatus) {
// Update the label using your naming convention
currentTimeLabel.innerText =
ConvertMillisecondsToHoursMinutesSecondsSoItLooksBetterAndNotCringe(currentPositionMs);
durationLabel.innerText =
ConvertMillisecondsToHoursMinutesSecondsSoItLooksBetterAndNotCringe(timelineProps.EndTime);
+
+ // Set the pause overlay visibility based on playback status
+ if (playbackStatus === PlaybackStatus.PAUSED)
+ albumArtContainer.classList.add('is-paused');
+ else
+ albumArtContainer.classList.remove('is-paused');
// Set progressbar
// Ensure we don't divide by zero or exceed 100%
diff --git a/now-playing/themes/classic/style.css b/now-playing/themes/classic/style.css
index 1223703..8880684 100644
--- a/now-playing/themes/classic/style.css
+++ b/now-playing/themes/classic/style.css
@@ -24,6 +24,37 @@
flex-shrink: 0;
}
+#album-art-container.is-paused #album-art-layer,
+#album-art-container.is-paused #album-art-transition-layer {
+ opacity: 0.7;
+ filter: grayscale(50%);
+}
+
+#pause-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.3s ease;
+ z-index: 10;
+ border-radius: inherit;
+}
+
+#pause-overlay svg {
+ height: 40%;
+ width: auto;
+}
+
+#album-art-container.is-paused #pause-overlay {
+ opacity: 1;
+}
+
#album-art-layer,
#album-art-transition-layer {
position: absolute;
diff --git a/now-playing/themes/color-palette/script.js b/now-playing/themes/color-palette/script.js
index bffb9b2..bb194e4 100644
--- a/now-playing/themes/color-palette/script.js
+++ b/now-playing/themes/color-palette/script.js
@@ -94,7 +94,7 @@ async function ChangeTrack(mediaProps, accentColorPalette) {
}, 250);
}
-function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
+function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette, playbackStatus) {
const durationMs = timelineProps.EndTime;
let progressPercent = durationMs > 0 ? (currentPositionMs / durationMs) * 100 : 0;
diff --git a/now-playing/themes/compact/script.js b/now-playing/themes/compact/script.js
index 7945afb..337e363 100644
--- a/now-playing/themes/compact/script.js
+++ b/now-playing/themes/compact/script.js
@@ -97,7 +97,7 @@ async function ChangeTrack(mediaProps, accentColorPalette) {
}, 250);
}
-function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
+function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette, playbackStatus) {
// Set progressbar
// Ensure we don't divide by zero or exceed 100%
const durationMs = timelineProps.EndTime;
@@ -122,6 +122,12 @@ function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
// const transitionWidth = '1em';
// progressBar.style.maskImage = `linear-gradient(to right, black calc(${clipRight}% - ${transitionWidth}), transparent ${clipRight}%)`
// progressBarTrack.style.maskImage = `linear-gradient(to right, transparent calc(${clipRight}% - ${transitionWidth}), black ${clipRight}%)`;
+
+ // Set the pause overlay visibility based on playback status
+ if (playbackStatus === PlaybackStatus.PAUSED)
+ songInfoContainer.classList.add('is-paused');
+ else
+ songInfoContainer.classList.remove('is-paused');
}
// MARQUEE LOGIC
diff --git a/now-playing/themes/compact/style.css b/now-playing/themes/compact/style.css
index 31b651d..f5747ab 100644
--- a/now-playing/themes/compact/style.css
+++ b/now-playing/themes/compact/style.css
@@ -24,6 +24,10 @@
grid-template-areas: "stack";
}
+#song-info-container.is-paused {
+ opacity: 0.8;
+}
+
/* The content sits on top */
#progress-bar {
position: relative;
diff --git a/now-playing/themes/simple/index.html b/now-playing/themes/simple/index.html
index 5c200da..c810810 100644
--- a/now-playing/themes/simple/index.html
+++ b/now-playing/themes/simple/index.html
@@ -2,6 +2,11 @@
diff --git a/now-playing/themes/simple/script.js b/now-playing/themes/simple/script.js
index 5b85975..c775c49 100644
--- a/now-playing/themes/simple/script.js
+++ b/now-playing/themes/simple/script.js
@@ -78,13 +78,19 @@ async function ChangeTrack(mediaProps) {
}, 250);
}
-function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
+function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette, playbackStatus) {
// Update the label using your naming convention
currentTimeLabel.innerText =
ConvertMillisecondsToHoursMinutesSecondsSoItLooksBetterAndNotCringe(currentPositionMs);
durationLabel.innerText =
ConvertMillisecondsToHoursMinutesSecondsSoItLooksBetterAndNotCringe(timelineProps.EndTime);
+
+ // Set the pause overlay visibility based on playback status
+ if (playbackStatus === PlaybackStatus.PAUSED)
+ albumArtContainer.classList.add('is-paused');
+ else
+ albumArtContainer.classList.remove('is-paused');
// Set progressbar
// Ensure we don't divide by zero or exceed 100%
@@ -95,12 +101,12 @@ function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
if (!useCustomColors)
{
- progressBarFill.style.setProperty('--accent-color', accentColorPalette.LightVibrant);
+ document.body.style.setProperty('--accent-color', accentColorPalette.LightVibrant);
document.body.style.color = accentColorPalette.LightVibrant;
}
else
{
- progressBarFill.style.setProperty('--accent-color', color1);
+ document.body.style.setProperty('--accent-color', color1);
document.body.style.color = color1;
}
}
diff --git a/now-playing/themes/simple/style.css b/now-playing/themes/simple/style.css
index 283f1d7..b1c000e 100644
--- a/now-playing/themes/simple/style.css
+++ b/now-playing/themes/simple/style.css
@@ -23,6 +23,37 @@
flex-shrink: 0;
}
+#album-art-container.is-paused #album-art-layer,
+#album-art-container.is-paused #album-art-transition-layer {
+ opacity: 0.7;
+ filter: grayscale(50%);
+}
+
+#pause-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.3s ease;
+ z-index: 10;
+ border-radius: inherit;
+}
+
+#pause-overlay svg {
+ height: 40%;
+ width: auto;
+}
+
+#album-art-container.is-paused #pause-overlay {
+ opacity: 1;
+}
+
#album-art-layer,
#album-art-transition-layer {
position: absolute;
diff --git a/now-playing/themes/standard/index.html b/now-playing/themes/standard/index.html
index bd9b89c..c1ef9b2 100644
--- a/now-playing/themes/standard/index.html
+++ b/now-playing/themes/standard/index.html
@@ -6,6 +6,11 @@
diff --git a/now-playing/themes/standard/script.js b/now-playing/themes/standard/script.js
index 0ca049a..2be6e45 100644
--- a/now-playing/themes/standard/script.js
+++ b/now-playing/themes/standard/script.js
@@ -147,7 +147,7 @@ async function ChangeTrack(mediaProps, accentColorPalette) {
}, 250);
}
-function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
+function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette, playbackStatus) {
// Update the label using your naming convention
currentTimeLabel.innerText =
ConvertMillisecondsToHoursMinutesSecondsSoItLooksBetterAndNotCringe(currentPositionMs);
@@ -155,6 +155,12 @@ function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
durationLabel.innerText =
ConvertMillisecondsToHoursMinutesSecondsSoItLooksBetterAndNotCringe(timelineProps.EndTime);
+ // Set the pause overlay visibility based on playback status
+ if (playbackStatus === PlaybackStatus.PAUSED)
+ albumArtContainer.classList.add('is-paused');
+ else
+ albumArtContainer.classList.remove('is-paused');
+
// Set progressbar
// Ensure we don't divide by zero or exceed 100%
const durationMs = timelineProps.EndTime;
@@ -165,9 +171,11 @@ function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
if (!useCustomColors) {
switch (themeVariant) {
case "matte":
- progressBarFill.style.setProperty('--accent-color', accentColorPalette.DarkVibrant);
+ document.body.style.setProperty('--accent-color', accentColorPalette.DarkVibrant);
break;
case "matte-dark":
+ document.body.style.setProperty('--accent-color', accentColorPalette.LightVibrant);
+ break;
default:
progressBarFill.style.setProperty('--accent-color', accentColorPalette.LightVibrant);
break;
@@ -177,11 +185,11 @@ function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
{
switch (themeVariant) {
case "matte":
- progressBarFill.style.setProperty('--accent-color', color2);
+ document.body.style.setProperty('--accent-color', color2);
break;
// case "matte-dark":
default:
- progressBarFill.style.setProperty('--accent-color', color1);
+ document.body.style.setProperty('--accent-color', color1);
break;
}
}
diff --git a/now-playing/themes/standard/style.css b/now-playing/themes/standard/style.css
index 90959e8..cfb32eb 100644
--- a/now-playing/themes/standard/style.css
+++ b/now-playing/themes/standard/style.css
@@ -25,6 +25,36 @@
flex-shrink: 0;
}
+#album-art-container.is-paused #album-art-layer,
+#album-art-container.is-paused #album-art-transition-layer {
+ opacity: 0.2;
+}
+
+#pause-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.3s ease;
+ z-index: 10;
+ border-radius: inherit;
+}
+
+#pause-overlay svg {
+ height: 50%;
+ width: auto;
+}
+
+#album-art-container.is-paused #pause-overlay {
+ opacity: 1;
+}
+
#album-art-layer,
#album-art-transition-layer {
position: absolute;
diff --git a/now-playing/themes/vinyl/script.js b/now-playing/themes/vinyl/script.js
index c4d2d48..8171fcb 100644
--- a/now-playing/themes/vinyl/script.js
+++ b/now-playing/themes/vinyl/script.js
@@ -8,6 +8,7 @@ const albumArtContainer = document.getElementById('album-art-container');
const albumArtLayer = document.getElementById('album-art-layer');
const albumArtTransition = document.getElementById('album-art-transition-layer');
const progressCircle = document.getElementById('progress-pie-circle');
+const vinylContainer = document.getElementById('vinyl-container');
///////////////
// CONSTANTS //
@@ -60,7 +61,7 @@ async function ChangeTrack(mediaProps) {
}, 250);
}
-function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
+function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette, playbackStatus) {
// Set progressbar
// Ensure we don't divide by zero or exceed 100%
const durationMs = timelineProps.EndTime;
@@ -75,4 +76,52 @@ function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) {
// 0% progress = 157.1 offset. 100% progress = 0 offset.
const offset = circumference - (progressPercent / 100) * circumference;
progressCircle.style.strokeDashoffset = offset;
+
+ // Adjust 'Paused' check to match whatever string/value your backend sends
+ if (playbackStatus === PlaybackStatus.PAUSED)
+ setVinylPaused(true);
+ else
+ setVinylPaused(false);
+}
+
+const vinylAnimation = vinylContainer.animate(
+ [
+ { transform: "rotate(0deg)" },
+ { transform: "rotate(360deg)" }
+ ],
+ {
+ duration: 10000,
+ iterations: Infinity,
+ easing: "linear"
+ }
+);
+
+let animationFrame;
+
+function setVinylPaused(shouldPause) {
+ cancelAnimationFrame(animationFrame);
+
+ const from = vinylAnimation.playbackRate;
+ const to = shouldPause ? 0 : 1;
+ const duration = 700;
+ const start = performance.now();
+
+ vinylAnimation.play();
+
+ function update(now) {
+ const progress = Math.min((now - start) / duration, 1);
+
+ // Smooth acceleration/deceleration
+ const eased = progress * progress * (3 - 2 * progress);
+
+ vinylAnimation.playbackRate = from + (to - from) * eased;
+
+ if (progress < 1) {
+ animationFrame = requestAnimationFrame(update);
+ } else if (shouldPause) {
+ vinylAnimation.pause();
+ }
+ }
+
+ animationFrame = requestAnimationFrame(update);
}
\ No newline at end of file
diff --git a/now-playing/themes/vinyl/style.css b/now-playing/themes/vinyl/style.css
index cce72c6..991e3c1 100644
--- a/now-playing/themes/vinyl/style.css
+++ b/now-playing/themes/vinyl/style.css
@@ -16,7 +16,7 @@
justify-content: center;
width: 100%;
filter: drop-shadow(0px 10px 15px rgba(0, 0, 0, 0.5));
- animation: spin 10s linear infinite;
+ transition: transform 1.2s cubic-bezier(0.25, 1, 0.5, 1);
}
#vinyl-background {
@@ -91,7 +91,64 @@
transition: all 1s linear;
}
-@keyframes spin {
- from { transform: rotate(0deg); }
- to { transform: rotate(360deg); }
+
+
+@keyframes slide-in-from-top {
+ 0% {
+ transform: translateY(-100%);
+ opacity: 0;
+ }
+
+ 100% {
+ transform: translateY(0);
+ opacity: 1;
+ }
+}
+
+@keyframes slide-in-from-top {
+ 0% {
+ transform: translateY(-100%);
+ opacity: 0;
+ }
+
+ 100% {
+ transform: translateY(0);
+ opacity: 1;
+ }
+}
+
+@keyframes slide-out-top {
+ 0% {
+ transform: translateY(0);
+ opacity: 1;
+ }
+
+ 100% {
+ transform: translateY(-100%);
+ opacity: 0;
+ }
+}
+
+@keyframes slide-in-from-bottom {
+ 0% {
+ transform: translateY(100%);
+ opacity: 0;
+ }
+
+ 100% {
+ transform: translateY(0);
+ opacity: 1;
+ }
+}
+
+@keyframes slide-out-bottom {
+ 0% {
+ transform: translateY(0);
+ opacity: 1;
+ }
+
+ 100% {
+ transform: translateY(100%);
+ opacity: 0;
+ }
}
\ No newline at end of file