From ff9674560800da65976feb0410cdfae29e24e518 Mon Sep 17 00:00:00 2001 From: nutty Date: Sun, 16 Aug 2026 11:11:40 +1000 Subject: [PATCH 1/9] =?UTF-8?q?=E2=80=A2=20Updated=20Marquee=20animation?= =?UTF-8?q?=20=E2=80=94=20should=20be=20more=20consistent=20=E2=80=A2=20Up?= =?UTF-8?q?dated=20Settings=20core=20=E2=80=94=20Streamer.bot=20will=20not?= =?UTF-8?q?=20load=20in=20the=20background=20for=20widgets=20that=20do=20n?= =?UTF-8?q?ot=20require=20it?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .common/core/settings-core/script.js | 66 +++++++++++++++------------- now-playing/script.js | 64 +++++++++++++++++++++------ now-playing/style.css | 52 +--------------------- now-playing/themes/compact/script.js | 53 +++++++++++++++++++--- now-playing/themes/compact/style.css | 12 ----- 5 files changed, 132 insertions(+), 115 deletions(-) diff --git a/.common/core/settings-core/script.js b/.common/core/settings-core/script.js index 6868574..f0f0e8c 100644 --- a/.common/core/settings-core/script.js +++ b/.common/core/settings-core/script.js @@ -337,9 +337,10 @@ function RefreshWidgetPreview() { } function UpdateStreamerBotConnection() { + // If Streamer.bot is not being used, exit early if (!useStreamerBot) return; - + let addressElement = document.getElementById('address'); let portElement = document.getElementById('port'); @@ -359,40 +360,43 @@ function UpdateStreamerBotConnection() { ////////////////// // Connect to Streamer.bot and get list of actions -let sbServerAddress = '127.0.0.1'; -let sbServerPort = '8080'; -let client = new StreamerbotClient({ - host: sbServerAddress, - port: sbServerPort, +if (useStreamerBot) +{ + let sbServerAddress = '127.0.0.1'; + let sbServerPort = '8080'; + let client = new StreamerbotClient({ + host: sbServerAddress, + port: sbServerPort, - onConnect: (data) => { - console.log(`Streamer.bot successfully connected to ${sbServerAddress}:${sbServerPort}`) - console.debug(data); + onConnect: (data) => { + console.log(`Streamer.bot successfully connected to ${sbServerAddress}:${sbServerPort}`) + console.debug(data); - // Get list of actions - GetSBActions(); - }, + // Get list of actions + GetSBActions(); + }, - onDisconnect: () => { - console.error(`Streamer.bot disconnected from ${sbServerAddress}:${sbServerPort}`) + onDisconnect: () => { + console.error(`Streamer.bot disconnected from ${sbServerAddress}:${sbServerPort}`) + } + }); + + async function GetSBActions() { + const response = await client.getActions(); + + console.debug(response); + + const datalistElement = document.createElement('datalist'); + datalistElement.id = 'streamer-bot-actions'; + + for (const action of response.actions) { + const option = document.createElement('option'); + option.value = action.name; + datalistElement.appendChild(option); + } + + document.body.appendChild(datalistElement); } -}); - -async function GetSBActions() { - const response = await client.getActions(); - - console.debug(response); - - const datalistElement = document.createElement('datalist'); - datalistElement.id = 'streamer-bot-actions'; - - for (const action of response.actions) { - const option = document.createElement('option'); - option.value = action.name; - datalistElement.appendChild(option); - } - - document.body.appendChild(datalistElement); } async function PopulateFontDatalist() { diff --git a/now-playing/script.js b/now-playing/script.js index 64aed80..78c8f2d 100644 --- a/now-playing/script.js +++ b/now-playing/script.js @@ -475,9 +475,6 @@ function SetVisibility(visible) { // This is a more advanced marquee implementation that calculates the overflow distance and adjusts the scroll speed accordingly const labelData = new Map(); -// Adjust this value to change scroll speed (pixels per second) -const SCROLL_SPEED_PX_PER_SEC = 40; - function SetLabelText(elementId, text) { const label = document.getElementById(elementId); if (!label) return; @@ -495,8 +492,11 @@ function SetLabelText(elementId, text) { } } +// Adjust this value to change scroll speed (pixels per second) +const SCROLL_SPEED_PX_PER_SEC = 30; +const PAUSE_SEC = 5; + function ApplyMarquee(label, text) { - // 1. Render single span to measure dimensions label.classList.remove('is-overflowing'); label.innerHTML = ``; label.querySelector('.scroll-content').textContent = text; @@ -507,20 +507,56 @@ function ApplyMarquee(label, text) { const containerWidth = label.clientWidth; const overflowDistance = textWidth - containerWidth; - // 2. Check if text exceeds container if (overflowDistance > 0) { - // Calculate travel distance in percentage relative to scrollContent's width const distancePercent = (overflowDistance / textWidth) * 100; - // Compute duration to keep speed consistent regardless of length - // We multiply travel time by 2 (for both directions) plus 3 seconds for pauses - const travelTime = overflowDistance / SCROLL_SPEED_PX_PER_SEC; - const totalDuration = (travelTime * 2) + 3; - - // Pass calculated variables to CSS - scrollContent.style.setProperty('--scroll-distance', `-${distancePercent}%`); - label.style.setProperty('--marquee-duration', `${totalDuration}s`); + // --- CONSTANT TIMINGS --- + const travelSec = overflowDistance / SCROLL_SPEED_PX_PER_SEC; + const pauseSec = PAUSE_SEC; // Always constant at each end + const totalSec = (travelSec * 2) + (pauseSec * 2); + const totalMs = totalSec * 1000; + + const p1 = (pauseSec / totalSec); + const p2 = ((pauseSec + travelSec) / totalSec); + const p3 = ((pauseSec * 2 + travelSec) / totalSec); + + scrollContent.style.setProperty('--scroll-distance', `-${distancePercent}%`); + + // 1. Animate Text Translation + scrollContent.animate([ + // Stay at start during pause 1 (linear/instant transition into movement) + { transform: 'translateX(0%)', offset: 0, easing: 'linear' }, + { transform: 'translateX(0%)', offset: p1, easing: 'ease-in-out' }, // <--- Easing starts HERE as it leaves the edge + + // Travel to the far end with smooth ease-in-out + { transform: `translateX(-${distancePercent}%)`, offset: p2, easing: 'linear' }, // <--- Easing ends HERE as it arrives + + // Stay at far end during pause 2 + { transform: `translateX(-${distancePercent}%)`, offset: p3, easing: 'ease-in-out' }, // <--- Easing starts HERE for return trip + + // Return to start with smooth ease-in-out + { transform: 'translateX(0%)', offset: 1, easing: 'linear' } // <--- Easing ends HERE back at start + ], { + duration: totalMs, + iterations: Infinity + }); + + // 2. Animate Mask Variables simultaneously to keep soft edges synced + label.animate([ + { '--mask-left': 'black', '--mask-right': 'transparent', offset: 0 }, + { '--mask-left': 'black', '--mask-right': 'transparent', offset: p1 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: p1 + 0.02 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: p2 - 0.02 }, + { '--mask-left': 'transparent', '--mask-right': 'black', offset: p2 }, + { '--mask-left': 'transparent', '--mask-right': 'black', offset: p3 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: p3 + 0.02 }, + { '--mask-left': 'black', '--mask-right': 'transparent', offset: 1 } + ], { + duration: totalMs, + iterations: Infinity + }); + label.classList.add('is-overflowing'); } } \ No newline at end of file diff --git a/now-playing/style.css b/now-playing/style.css index 1d6282c..de16278 100644 --- a/now-playing/style.css +++ b/now-playing/style.css @@ -183,13 +183,7 @@ body { will-change: transform; } -.text-label.is-overflowing .scroll-content { - animation: ping-pong-scroll var(--marquee-duration, 8s) ease-in-out infinite; -} - -.text-label.is-overflowing { - animation: ping-pong-mask var(--marquee-duration, 8s) ease-in-out infinite; - +.text-label.is-overflowing { /* Static gradient structure referencing dynamic color variables */ mask-image: linear-gradient( to right, @@ -205,48 +199,4 @@ body { black calc(100% - var(--fade-width)), var(--mask-right) 100% ); -} - -@keyframes ping-pong-scroll { - 0%, 15% { - transform: translateX(0%); - } - 50%, 65% { - transform: translateX(var(--scroll-distance, -100%)); - } - 100% { - transform: translateX(0%); - } -} - -@keyframes ping-pong-mask { - /* 1. AT START: Left is solid (black), Right is faded (transparent) */ - 0%, 15% { - --mask-left: black; - --mask-right: transparent; - } - - /* 2. MOVING LEFT: Left smoothly fades in (transparent), Right stays faded */ - 22%, 43% { - --mask-left: transparent; - --mask-right: transparent; - } - - /* 3. AT FAR END: Right smoothly solidifies (black), Left stays faded */ - 50%, 65% { - --mask-left: transparent; - --mask-right: black; - } - - /* 4. MOVING RIGHT: Right smoothly fades back out (transparent) */ - 72%, 93% { - --mask-left: transparent; - --mask-right: transparent; - } - - /* 5. RETURN TO START: Left smoothly solidifies (black) */ - 100% { - --mask-left: black; - --mask-right: transparent; - } } \ No newline at end of file diff --git a/now-playing/themes/compact/script.js b/now-playing/themes/compact/script.js index a8b736d..4b10cb0 100644 --- a/now-playing/themes/compact/script.js +++ b/now-playing/themes/compact/script.js @@ -145,7 +145,6 @@ function UpdateSingleSongLabel(containerId, trackName, artistName) { let scrollContent = container.querySelector('.scroll-content'); - // Only rebuild the HTML structure if the text content actually changed or doesn't exist yet const currentTrackEl = container.querySelector('.track-label'); const currentArtistEl = container.querySelector('.artist-label'); @@ -160,7 +159,6 @@ function UpdateSingleSongLabel(containerId, trackName, artistName) { scrollContent = container.querySelector('.scroll-content'); } - // Encapsulate measurement logic so it can be called safely by the observer const updateMetrics = () => { scrollContent = container.querySelector('.scroll-content'); @@ -170,20 +168,61 @@ function UpdateSingleSongLabel(containerId, trackName, artistName) { if (overflowDistance > 0) { const distancePercent = (overflowDistance / textWidth) * 100; - const travelTime = overflowDistance / SCROLL_SPEED_PX_PER_SEC; - const totalDuration = (travelTime * 2) + 3; + + // --- CONSTANT TIMINGS --- + const travelSec = overflowDistance / SCROLL_SPEED_PX_PER_SEC; + const pauseSec = PAUSE_SEC; + + const totalSec = (travelSec * 2) + (pauseSec * 2); + const totalMs = totalSec * 1000; + + const p1 = (pauseSec / totalSec); + const p2 = ((pauseSec + travelSec) / totalSec); + const p3 = ((pauseSec * 2 + travelSec) / totalSec); + + scrollContent.style.setProperty('--scroll-distance', `-${distancePercent}%`); + + // Clear any previous active animations to prevent stacking on resize + if (scrollContent._anim) scrollContent._anim.cancel(); + if (container._anim) container._anim.cancel(); + + // 1. Animate Text Translation inside container + scrollContent._anim = scrollContent.animate([ + { transform: 'translateX(0%)', offset: 0, easing: 'linear' }, + { transform: 'translateX(0%)', offset: p1, easing: 'ease-in-out' }, + { transform: `translateX(-${distancePercent}%)`, offset: p2, easing: 'linear' }, + { transform: `translateX(-${distancePercent}%)`, offset: p3, easing: 'ease-in-out' }, + { transform: 'translateX(0%)', offset: 1, easing: 'linear' } + ], { + duration: totalMs, + iterations: Infinity + }); + + // 2. Animate Mask Variables simultaneously on the container + container._anim = container.animate([ + { '--mask-left': 'black', '--mask-right': 'transparent', offset: 0 }, + { '--mask-left': 'black', '--mask-right': 'transparent', offset: p1 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: p1 + 0.02 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: p2 - 0.02 }, + { '--mask-left': 'transparent', '--mask-right': 'black', offset: p2 }, + { '--mask-left': 'transparent', '--mask-right': 'black', offset: p3 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: p3 + 0.02 }, + { '--mask-left': 'black', '--mask-right': 'transparent', offset: 1 } + ], { + duration: totalMs, + iterations: Infinity + }); - container.style.setProperty('--scroll-distance', `-${distancePercent}%`); - container.style.setProperty('--marquee-duration', `${totalDuration}s`); container.classList.add('is-overflowing'); } else { container.classList.remove('is-overflowing'); + if (scrollContent._anim) scrollContent._anim.cancel(); + if (container._anim) container._anim.cancel(); } }; updateMetrics(); - // Attach ResizeObserver once to update metrics only (No recursive function resets!) if (!container._resizeObserver) { container._resizeObserver = new ResizeObserver(() => { updateMetrics(); diff --git a/now-playing/themes/compact/style.css b/now-playing/themes/compact/style.css index 9b87c0c..31b651d 100644 --- a/now-playing/themes/compact/style.css +++ b/now-playing/themes/compact/style.css @@ -87,16 +87,4 @@ font-weight: 400; opacity: 0.7; display: var(--show-secondary); -} - -/* Marquee scroll animation */ -#song-label.is-overflowing .scroll-content, -#song-label-background.is-overflowing .scroll-content { - animation: ping-pong-scroll var(--marquee-duration, 8s) ease-in-out infinite; -} - -/* Mask animation applied to container */ -#song-label.is-overflowing, -#song-label-background.is-overflowing { - animation: ping-pong-mask var(--marquee-duration, 8s) ease-in-out infinite; } \ No newline at end of file From 4af3f9ef20bc9a32a3a834caa0bd9f3f54e10609 Mon Sep 17 00:00:00 2001 From: nutty Date: Sun, 16 Aug 2026 11:18:57 +1000 Subject: [PATCH 2/9] Changed progress bar appearance for 'Album Art' theme --- now-playing/themes/album-art/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/now-playing/themes/album-art/style.css b/now-playing/themes/album-art/style.css index 06ddf7b..1fc2175 100644 --- a/now-playing/themes/album-art/style.css +++ b/now-playing/themes/album-art/style.css @@ -81,7 +81,7 @@ #progress-bar { height: 1%; width: 0%; /* JS will control this */ - background: linear-gradient(to top, #ffffff00, var(--accent-color, #ffffff)); + background: var(--accent-color); /* background-color: var(--accent-color, #ffffff); */ transition: width 1s ease-in-out, background 1s ease-in-out; /* border-radius: 10000px; */ From fd3dfa647d71eb6f13461bcc554ee5462a9ed090 Mon Sep 17 00:00:00 2001 From: nutty Date: Sun, 16 Aug 2026 11:28:35 +1000 Subject: [PATCH 3/9] Uhhh this is what I meant lol --- now-playing/themes/album-art/style.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/now-playing/themes/album-art/style.css b/now-playing/themes/album-art/style.css index 1fc2175..bd86dd2 100644 --- a/now-playing/themes/album-art/style.css +++ b/now-playing/themes/album-art/style.css @@ -81,8 +81,8 @@ #progress-bar { height: 1%; width: 0%; /* JS will control this */ - background: var(--accent-color); - /* background-color: var(--accent-color, #ffffff); */ + /* background: linear-gradient(to top, #ffffff00, var(--accent-color, #ffffff)); */ + background-color: var(--accent-color, #ffffff); transition: width 1s ease-in-out, background 1s ease-in-out; /* border-radius: 10000px; */ position: absolute; From 5c994401e944e87e878b731152babc28e07093c9 Mon Sep 17 00:00:00 2001 From: nutty Date: Sun, 16 Aug 2026 11:57:11 +1000 Subject: [PATCH 4/9] Fixed marquee animation bug --- now-playing/script.js | 27 +++++++++++++++------------ now-playing/themes/compact/script.js | 11 +++++++---- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/now-playing/script.js b/now-playing/script.js index 78c8f2d..63cde23 100644 --- a/now-playing/script.js +++ b/now-playing/script.js @@ -543,19 +543,22 @@ function ApplyMarquee(label, text) { }); // 2. Animate Mask Variables simultaneously to keep soft edges synced + const maxOffset = 1; + const fadeBuffer = 0.02; + label.animate([ - { '--mask-left': 'black', '--mask-right': 'transparent', offset: 0 }, - { '--mask-left': 'black', '--mask-right': 'transparent', offset: p1 }, - { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: p1 + 0.02 }, - { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: p2 - 0.02 }, - { '--mask-left': 'transparent', '--mask-right': 'black', offset: p2 }, - { '--mask-left': 'transparent', '--mask-right': 'black', offset: p3 }, - { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: p3 + 0.02 }, - { '--mask-left': 'black', '--mask-right': 'transparent', offset: 1 } - ], { - duration: totalMs, - iterations: Infinity - }); + { '--mask-left': 'black', '--mask-right': 'transparent', offset: 0 }, + { '--mask-left': 'black', '--mask-right': 'transparent', offset: p1 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: Math.min(p1 + fadeBuffer, maxOffset) }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: Math.max(0, p2 - fadeBuffer) }, + { '--mask-left': 'transparent', '--mask-right': 'black', offset: p2 }, + { '--mask-left': 'transparent', '--mask-right': 'black', offset: p3 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: Math.min(p3 + fadeBuffer, maxOffset) }, + { '--mask-left': 'black', '--mask-right': 'transparent', offset: 1 } + ], { + duration: totalMs, + iterations: Infinity + }); label.classList.add('is-overflowing'); } diff --git a/now-playing/themes/compact/script.js b/now-playing/themes/compact/script.js index 4b10cb0..54b3d1f 100644 --- a/now-playing/themes/compact/script.js +++ b/now-playing/themes/compact/script.js @@ -198,15 +198,18 @@ function UpdateSingleSongLabel(containerId, trackName, artistName) { iterations: Infinity }); - // 2. Animate Mask Variables simultaneously on the container + // 2. Animate Mask Variables simultaneously to keep soft edges synced + const maxOffset = 1; + const fadeBuffer = 0.02; + container._anim = container.animate([ { '--mask-left': 'black', '--mask-right': 'transparent', offset: 0 }, { '--mask-left': 'black', '--mask-right': 'transparent', offset: p1 }, - { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: p1 + 0.02 }, - { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: p2 - 0.02 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: Math.min(p1 + fadeBuffer, maxOffset) }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: Math.max(0, p2 - fadeBuffer) }, { '--mask-left': 'transparent', '--mask-right': 'black', offset: p2 }, { '--mask-left': 'transparent', '--mask-right': 'black', offset: p3 }, - { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: p3 + 0.02 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: Math.min(p3 + fadeBuffer, maxOffset) }, { '--mask-left': 'black', '--mask-right': 'transparent', offset: 1 } ], { duration: totalMs, From 539a1aebf3c316756c27e01feb544c32c4468a2a Mon Sep 17 00:00:00 2001 From: nutty Date: Sun, 16 Aug 2026 17:13:15 +1000 Subject: [PATCH 5/9] Fixed again blehghghghwegh --- now-playing/script.js | 38 ++++++++++++++++++---------- now-playing/themes/compact/script.js | 27 +++++++++++++------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/now-playing/script.js b/now-playing/script.js index 63cde23..f910ced 100644 --- a/now-playing/script.js +++ b/now-playing/script.js @@ -544,21 +544,31 @@ function ApplyMarquee(label, text) { // 2. Animate Mask Variables simultaneously to keep soft edges synced const maxOffset = 1; - const fadeBuffer = 0.02; + // Dynamically scale buffer so it never overlaps text segments if overflow is small + const fadeBuffer = Math.min(0.02, (p2 - p1) / 4); - label.animate([ - { '--mask-left': 'black', '--mask-right': 'transparent', offset: 0 }, - { '--mask-left': 'black', '--mask-right': 'transparent', offset: p1 }, - { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: Math.min(p1 + fadeBuffer, maxOffset) }, - { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: Math.max(0, p2 - fadeBuffer) }, - { '--mask-left': 'transparent', '--mask-right': 'black', offset: p2 }, - { '--mask-left': 'transparent', '--mask-right': 'black', offset: p3 }, - { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: Math.min(p3 + fadeBuffer, maxOffset) }, - { '--mask-left': 'black', '--mask-right': 'transparent', offset: 1 } - ], { - duration: totalMs, - iterations: Infinity - }); + const off0 = 0; + const off1 = p1; + const off2 = Math.min(p1 + fadeBuffer, p2); + const off3 = Math.max(off2, p2 - fadeBuffer); + const off4 = p2; + const off5 = p3; + const off6 = Math.min(p3 + fadeBuffer, maxOffset); + const off7 = 1; + + label._anim = label.animate([ + { '--mask-left': 'black', '--mask-right': 'transparent', offset: off0 }, + { '--mask-left': 'black', '--mask-right': 'transparent', offset: off1 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: off2 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: off3 }, + { '--mask-left': 'transparent', '--mask-right': 'black', offset: off4 }, + { '--mask-left': 'transparent', '--mask-right': 'black', offset: off5 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: off6 }, + { '--mask-left': 'black', '--mask-right': 'transparent', offset: off7 } + ], { + duration: totalMs, + iterations: Infinity + }); label.classList.add('is-overflowing'); } diff --git a/now-playing/themes/compact/script.js b/now-playing/themes/compact/script.js index 54b3d1f..b6ed0f7 100644 --- a/now-playing/themes/compact/script.js +++ b/now-playing/themes/compact/script.js @@ -200,17 +200,26 @@ function UpdateSingleSongLabel(containerId, trackName, artistName) { // 2. Animate Mask Variables simultaneously to keep soft edges synced const maxOffset = 1; - const fadeBuffer = 0.02; + const fadeBuffer = Math.min(0.02, (p2 - p1) / 4); // Dynamically scale buffer if text overflow is tiny + + const off0 = 0; + const off1 = p1; + const off2 = Math.min(p1 + fadeBuffer, p2); + const off3 = Math.max(off2, p2 - fadeBuffer); + const off4 = p2; + const off5 = p3; + const off6 = Math.min(p3 + fadeBuffer, maxOffset); + const off7 = 1; container._anim = container.animate([ - { '--mask-left': 'black', '--mask-right': 'transparent', offset: 0 }, - { '--mask-left': 'black', '--mask-right': 'transparent', offset: p1 }, - { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: Math.min(p1 + fadeBuffer, maxOffset) }, - { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: Math.max(0, p2 - fadeBuffer) }, - { '--mask-left': 'transparent', '--mask-right': 'black', offset: p2 }, - { '--mask-left': 'transparent', '--mask-right': 'black', offset: p3 }, - { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: Math.min(p3 + fadeBuffer, maxOffset) }, - { '--mask-left': 'black', '--mask-right': 'transparent', offset: 1 } + { '--mask-left': 'black', '--mask-right': 'transparent', offset: off0 }, + { '--mask-left': 'black', '--mask-right': 'transparent', offset: off1 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: off2 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: off3 }, + { '--mask-left': 'transparent', '--mask-right': 'black', offset: off4 }, + { '--mask-left': 'transparent', '--mask-right': 'black', offset: off5 }, + { '--mask-left': 'transparent', '--mask-right': 'transparent', offset: off6 }, + { '--mask-left': 'black', '--mask-right': 'transparent', offset: off7 } ], { duration: totalMs, iterations: Infinity From abff66d3e2e8c4eab171e7d108e66df5017e45f7 Mon Sep 17 00:00:00 2001 From: nutty Date: Sun, 16 Aug 2026 17:22:21 +1000 Subject: [PATCH 6/9] Pinned progress bar to 100% for sessions that can't provide timeline info ('Compact' theme) --- now-playing/themes/compact/script.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/now-playing/themes/compact/script.js b/now-playing/themes/compact/script.js index b6ed0f7..9be4c9a 100644 --- a/now-playing/themes/compact/script.js +++ b/now-playing/themes/compact/script.js @@ -102,19 +102,20 @@ function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) { // Ensure we don't divide by zero or exceed 100% const durationMs = timelineProps.EndTime; - // If the duration is 0, that means the session isn't returning any timeline info, so just put the progress at 100% - if (durationMs <= 0 || !showProgressBar) - { - progressBarTrack.style.display = 'none'; - return; - } - else - progressBarTrack.style.display = ''; - // Calculate the progress percentage let progressPercent = durationMs > 0 ? (currentPositionMs / durationMs) * 100 : 0; progressPercent = Math.min(100, Math.max(0, progressPercent)); + // If the duration is 0, that means the session isn't returning any timeline info, so just put the progress at 100% + if (durationMs <= 0 || !showProgressBar) + // { + // progressBarTrack.style.display = 'none'; + // return; + // } + // else + // progressBarTrack.style.display = ''; + progressPercent = 100; + // Calculate how much needs to be hidden (the right-side offset) const clipRight = 100 - progressPercent; From f90a39a89d6df086615c5c4998002ec6d4a6352a Mon Sep 17 00:00:00 2001 From: nutty Date: Sun, 16 Aug 2026 17:22:48 +1000 Subject: [PATCH 7/9] BLAHAHAHAHA --- now-playing/themes/compact/script.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/now-playing/themes/compact/script.js b/now-playing/themes/compact/script.js index 9be4c9a..7945afb 100644 --- a/now-playing/themes/compact/script.js +++ b/now-playing/themes/compact/script.js @@ -108,12 +108,6 @@ function SetProgressInfo(timelineProps, currentPositionMs, accentColorPalette) { // If the duration is 0, that means the session isn't returning any timeline info, so just put the progress at 100% if (durationMs <= 0 || !showProgressBar) - // { - // progressBarTrack.style.display = 'none'; - // return; - // } - // else - // progressBarTrack.style.display = ''; progressPercent = 100; // Calculate how much needs to be hidden (the right-side offset) From 58728b8f56760ebe4fd2950aa80754e98f46a846 Mon Sep 17 00:00:00 2001 From: nutty Date: Tue, 18 Aug 2026 02:06:39 +1000 Subject: [PATCH 8/9] Removed errant ticks --- clocko/index.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clocko/index.html b/clocko/index.html index 8078048..f58af89 100644 --- a/clocko/index.html +++ b/clocko/index.html @@ -1,6 +1,7 @@ + nutty | Clocko @@ -19,6 +20,6 @@ -' -' + + \ No newline at end of file From e7d702c4c36c214765933e76e2a9145f18d0b1f7 Mon Sep 17 00:00:00 2001 From: nutty Date: Tue, 18 Aug 2026 02:15:09 +1000 Subject: [PATCH 9/9] Changed stock settings --- clocko/settings/settings.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clocko/settings/settings.json b/clocko/settings/settings.json index bf27ef7..de49bb5 100644 --- a/clocko/settings/settings.json +++ b/clocko/settings/settings.json @@ -52,7 +52,7 @@ { "value": "800", "label": "Extra Bold" }, { "value": "900", "label": "Black" } ], - "defaultValue": "700", + "defaultValue": "800", "showIf": "enableLine1", "group": "Appearance" }, @@ -119,7 +119,7 @@ "label": "Format", "description": "Click here for formatting options", "type": "text", - "defaultValue": "ddd, MMM D", + "defaultValue": "ddd D MMM YY", "showIf": "enableLine2", "group": "Appearance" }, @@ -168,7 +168,7 @@ "label": "Font Opacity", "description": "", "type": "number", - "defaultValue": "0.7", + "defaultValue": "0.9", "min": 0, "max": 1, "step": ".01",