From 2e4383524fb6c3443e6ff1e01d4c4c79f9518257 Mon Sep 17 00:00:00 2001 From: Byron Gamatos Date: Thu, 2 Jul 2026 14:52:40 +0200 Subject: [PATCH] fix(v3): drawer fav-sync honours data-fav-idle (no dim-heart on List View) (#717) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _patchCardFav (the Song Details drawer's like -> card heart sync) hardcoded `classList.toggle('text-white', !fav)`, so toggling the like from the drawer left List-View rows' `text-fb-textDim` idle class in place — the exact dim-heart bug #654 fixed for the on-card click handler, reintroduced on the drawer path. Read the per-heart `data-fav-idle` and swap that class instead, mirroring wireCards. +regression assertion in v3_favorites_toggle.test.js. Co-authored-by: Claude Opus 4.8 (1M context) --- static/v3/songs.js | 7 ++++++- tests/js/v3_favorites_toggle.test.js | 10 ++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/static/v3/songs.js b/static/v3/songs.js index e9f2bb5..db965c2 100644 --- a/static/v3/songs.js +++ b/static/v3/songs.js @@ -2354,7 +2354,12 @@ document.querySelectorAll('[data-fn="' + sel + '"] [data-fav]').forEach((btn) => { btn.textContent = fav ? '♥' : '♡'; btn.setAttribute('aria-pressed', fav ? 'true' : 'false'); - btn.classList.toggle('text-fb-accent', fav); btn.classList.toggle('text-white', !fav); + // Swap exactly the idle colour this heart was rendered with (grid = + // text-white, tree/List view = text-fb-textDim) — mirrors wireCards. + // A hardcoded text-white toggle would leave List-View rows' text-fb-textDim + // in place, so the heart changed glyph but stayed dim (never turned red). + const idle = btn.getAttribute('data-fav-idle') || 'text-white'; + btn.classList.toggle('text-fb-accent', fav); btn.classList.toggle(idle, !fav); }); } diff --git a/tests/js/v3_favorites_toggle.test.js b/tests/js/v3_favorites_toggle.test.js index 81051ea..ad14bfd 100644 --- a/tests/js/v3_favorites_toggle.test.js +++ b/tests/js/v3_favorites_toggle.test.js @@ -40,6 +40,16 @@ test('the shared fav handler swaps the declared idle colour, not a hardcoded one 'the hardcoded text-white idle toggle must be removed'); }); +test('the drawer fav-sync (_patchCardFav) swaps the declared idle colour too', () => { + // Toggling the like from the Song Details drawer patches the rendered card's + // heart via _patchCardFav; it must honour each heart's data-fav-idle the same + // way the click handler does, or List-View rows keep the dim-heart bug (#654). + assert.match(src, /function _patchCardFav[\s\S]*?getAttribute\('data-fav-idle'\)[\s\S]*?classList\.toggle\(\s*idle\s*,\s*!fav\s*\)/, + '_patchCardFav must restore the per-context idle colour (idle), not a hardcoded text-white'); + assert.doesNotMatch(src, /classList\.toggle\('text-white',\s*!fav\)/, + '_patchCardFav must not hardcode the text-white idle toggle'); +}); + test('the fav toggle keeps the in-memory song model in sync', () => { // So a virtualized grid recycle / tree re-render renders the new state, // not a stale favorite=false read from state.songsById.