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