From 5558fa01bddf40558d3dd4f0c46b63a182848c08 Mon Sep 17 00:00:00 2001 From: Forrest Hartley <116300933+4444est@users.noreply.github.com> Date: Sun, 21 Dec 2025 17:54:39 -0700 Subject: [PATCH 1/3] last commit didn't go through as a pr. image recoloring issues should be fixed. --- src/lib/components/GrayscaleImageRenderer.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/GrayscaleImageRenderer.svelte b/src/lib/components/GrayscaleImageRenderer.svelte index 82fb298..0cf3d58 100644 --- a/src/lib/components/GrayscaleImageRenderer.svelte +++ b/src/lib/components/GrayscaleImageRenderer.svelte @@ -1,6 +1,6 @@ From 5629e0d64799afc6535bd756f2cd271d0ff2dc17 Mon Sep 17 00:00:00 2001 From: Forrest Hartley <116300933+4444est@users.noreply.github.com> Date: Tue, 10 Feb 2026 23:13:31 -0700 Subject: [PATCH 2/3] got song replay functionality working in trash and fixed recoloring issues for played songs --- functions/index.js | 2 +- src/lib/components/LyricDisplay.svelte | 74 +++++++---- src/lib/components/TrashDisplay.svelte | 167 ++++++++++++++++++++++++- src/lib/components/TypingTest.svelte | 135 ++++++++++++++------ src/lib/services/artistService.js | 77 ++++++++++++ src/lib/services/trashService.js | 65 +++++++--- 6 files changed, 439 insertions(+), 81 deletions(-) diff --git a/functions/index.js b/functions/index.js index bbd3358..00ac56f 100644 --- a/functions/index.js +++ b/functions/index.js @@ -7,7 +7,7 @@ import pako from 'pako'; import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'url'; -import { HttpsProxyAgent } from 'https-proxy-agent'; +import HttpsProxyAgent from 'https-proxy-agent'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/src/lib/components/LyricDisplay.svelte b/src/lib/components/LyricDisplay.svelte index a3f393f..07a5567 100644 --- a/src/lib/components/LyricDisplay.svelte +++ b/src/lib/components/LyricDisplay.svelte @@ -15,6 +15,7 @@ export let replaySong; export let geniusUrl; export let songId = null; // Song ID for trash functionality + export let artistUrlKey = null; // Artist URL key for loading from discography export let isPaused = false; export let capitalization = true; export let punctuation = true; @@ -25,7 +26,7 @@ export let onScrollDown = null; let currentScrollLine = 0; // Track which line we're starting from let lyricsLines = []; // Array of lyrics split by lines - let visibleLines = []; // Currently visible 4 lines + // visibleLines is now computed reactively from lyricsLines and currentScrollLine const VISIBLE_LINES_COUNT = 4; let userInput = ''; @@ -60,7 +61,14 @@ // Process lyrics into lines and manage scrolling function processLyricsIntoLines(lyricsText) { if (!lyricsText) return []; - return lyricsText.split('\n').filter(line => line.trim() !== ''); + const lines = lyricsText.split('\n').filter(line => line.trim() !== ''); + // Debug: show line count and first few lines with their character counts + console.log(`🎵 LYRICS DEBUG: ${lines.length} total lines`); + console.log(`🎵 First 6 lines preview:`); + lines.slice(0, 6).forEach((line, i) => { + console.log(` Line ${i}: "${line.substring(0, 50)}${line.length > 50 ? '...' : ''}" (${line.length} chars)`); + }); + return lines; } // Check if we have full lyrics available for scrolling @@ -123,16 +131,11 @@ } // Update the visible lines based on current scroll position + // Note: visibleLines is now computed reactively from lyricsLines and currentScrollLine + // This function just logs the change - the actual update happens via reactive statement function updateVisibleLines() { console.log("updating visible lines"); const endLine = Math.min(lyricsLines.length, currentScrollLine + VISIBLE_LINES_COUNT); - visibleLines = lyricsLines.slice(currentScrollLine, endLine); - - // If we don't have enough lines, pad with empty lines to maintain consistent display - while (visibleLines.length < VISIBLE_LINES_COUNT && lyricsLines.length > 0) { - visibleLines.push(''); - } - console.log(`Displaying lines ${currentScrollLine}-${endLine-1} of ${lyricsLines.length} total lines`); } @@ -172,19 +175,17 @@ }, 0); } - // Reactive statement to process lyrics when they change - $: { - // Use full lyrics for scrolling if available, otherwise use the provided lyrics - const lyricsToProcess = fullLyrics || lyrics; - if (lyricsToProcess) { - lyricsLines = processLyricsIntoLines(lyricsToProcess); - resetScrollPosition(); - console.log(`Processed lyrics: ${lyricsLines.length} lines total`, { - hasFullLyrics: !!fullLyrics, - usingFullLyrics: !!fullLyrics, - firstFewLines: lyricsLines.slice(0, 3) - }); - } + // Reactive assignment: process lyrics when they change + // Using reactive assignment (not block) ensures proper dependency tracking + $: lyricsSource = fullLyrics || lyrics; + $: lyricsLines = lyricsSource ? processLyricsIntoLines(lyricsSource) : []; + + // Track when lyrics source changes to reset scroll position + let lastLyricsSource = null; + $: if (lyricsSource !== lastLyricsSource) { + lastLyricsSource = lyricsSource; + currentScrollLine = 0; + console.log(`Processed lyrics: ${lyricsLines.length} lines total`); } // Expose scroll functions to parent components @@ -423,10 +424,34 @@ return normalized; } + // Compute visible lines reactively based on lyricsLines and currentScrollLine + // This ensures visibleLines is always in sync and doesn't rely on side effects + $: computedVisibleLines = (() => { + if (lyricsLines.length === 0) return []; + const endLine = Math.min(lyricsLines.length, currentScrollLine + VISIBLE_LINES_COUNT); + const lines = lyricsLines.slice(currentScrollLine, endLine); + // Pad with empty lines if needed + while (lines.length < VISIBLE_LINES_COUNT && lyricsLines.length > 0) { + lines.push(''); + } + console.log(`🔍 VISIBLE LINES DEBUG: showing lines ${currentScrollLine}-${endLine-1} (${lines.length} lines)`); + lines.forEach((line, i) => { + console.log(` Visible[${i}]: "${line.substring(0, 60)}${line.length > 60 ? '...' : ''}" (${line.length} chars)`); + }); + return lines; + })(); + + // Sync visibleLines with the computed value + $: visibleLines = computedVisibleLines; + // Derived lyrics based on toggles and scrolling + // IMPORTANT: Do NOT reference 'lyrics' prop here to avoid Svelte running this + // before lyricsLines is populated. Only use lyricsLines/computedVisibleLines. $: transformedLyrics = (() => { - // Use visible lines if scrolling is active, otherwise use full lyrics - const lyricsToUse = visibleLines.length > 0 ? visibleLines.join('\n') : lyrics; + // Always use computed visible lines - never fall back to raw lyrics + const lyricsToUse = computedVisibleLines.join('\n'); + console.log(`📝 TRANSFORMED DEBUG: ${computedVisibleLines.length} visible lines → ${lyricsToUse.length} total chars`); + console.log(`📝 Full transformed text preview: "${lyricsToUse.substring(0, 200)}${lyricsToUse.length > 200 ? '...' : ''}"`); let out = lyricsToUse ? (capitalization ? lyricsToUse : lyricsToUse.toLowerCase()) : ''; if (!punctuation) out = out.replace(/[^\p{L}\p{N}\s]/gu, ''); return out; @@ -548,6 +573,7 @@ function handleInput(event) { songId, songTitle, artistName, + artistUrlKey, // For loading song from artist's discography imageUrl, albumArtId, geniusUrl, diff --git a/src/lib/components/TrashDisplay.svelte b/src/lib/components/TrashDisplay.svelte index 6b6dd97..f5c1cc9 100644 --- a/src/lib/components/TrashDisplay.svelte +++ b/src/lib/components/TrashDisplay.svelte @@ -1,13 +1,23 @@
{#if selectedSong.imageUrl} - {selectedSong.title} + {#key selectedSong.imageUrl} + {#if $ditherImages && grayscaleImageData && imageMetadata && !useFallback} + + {:else} + {selectedSong.title} + {/if} + {/key} {:else}
@@ -274,6 +400,18 @@
Completed: {new Date(selectedSong.completedAt).toLocaleDateString()}
+ + +
{:else}
@@ -580,8 +718,31 @@ .completion-date { text-align: center; opacity: 0.6; + color: var(--primary-color); + } + + .replay-button { + display: flex; + align-items: center; + justify-content: center; + gap: 6px; margin-top: auto; + padding: 8px 16px; + background-color: var(--secondary-color); color: var(--primary-color); + border: 1px solid var(--primary-color); + cursor: pointer; + font-family: inherit; + transition: background-color 0.15s ease; + } + + .replay-button:hover { + background-color: var(--primary-color); + color: var(--secondary-color); + } + + .replay-button:hover svg path { + fill: var(--secondary-color); } .no-selection { diff --git a/src/lib/components/TypingTest.svelte b/src/lib/components/TypingTest.svelte index 927f695..ee9cb56 100644 --- a/src/lib/components/TypingTest.svelte +++ b/src/lib/components/TypingTest.svelte @@ -1,5 +1,5 @@