diff --git a/public/sw.js b/public/sw.js index a0454ed..36c522e 100644 --- a/public/sw.js +++ b/public/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'ns-v74'; +const CACHE = 'ns-v75'; const PRECACHE = ['/', 'index.html', 'manifest.json', 'icon.svg']; const SKIP_PATHS = ['/rest/stream', '/rest/download', '/config.js']; // Auth token params stripped from cache keys so artwork survives across sessions/token refreshes. diff --git a/src/utils.js b/src/utils.js index 497ca12..139538c 100644 --- a/src/utils.js +++ b/src/utils.js @@ -36,7 +36,9 @@ export function md5(input) { } export function esc(s) { - return (s||'').replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); + // Coerce to string first — callers sometimes pass numbers (e.g. a Deezer artist id), which + // would throw on .replace. null/undefined → ''. + return String(s ?? '').replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); } export function formatDur(s) { diff --git a/src/views/detail.js b/src/views/detail.js index 147efdf..6b4a748 100644 --- a/src/views/detail.js +++ b/src/views/detail.js @@ -94,19 +94,16 @@ export async function loadArtistDetail(artist) { const knownFans = _pin?.fanCount ?? artist.deezerFanCount ?? null; if (knownFans) _showFans(knownFans); // from the global-search card / pin — show immediately - // "Falscher Künstler?" pin button (local artists only) — fix a wrong same-name Deezer match. - if (hasND) { - const infoEl = hero.querySelector('.artist-hero-info'); - infoEl?.querySelector('.artist-pin-btn')?.remove(); - if (infoEl) { - const pinBtn = document.createElement('button'); - pinBtn.className = 'artist-pin-btn'; - pinBtn.textContent = _pin ? '⚙ Künstler gepinnt' : '⚙ Falscher Künstler?'; - pinBtn.title = 'Richtigen Deezer-Künstler wählen'; - pinBtn.style.cssText = 'margin-top:8px;padding:5px 12px;border-radius:999px;border:1px solid var(--border2);background:rgba(0,0,0,.35);color:#fff;font-family:var(--font);font-size:12px;font-weight:600;cursor:pointer'; - pinBtn.onclick = () => openArtistPin(artist.id, artist.name); - infoEl.appendChild(pinBtn); - } + // "Falscher Künstler?" pin button (local artists only) — top-right of the banner. + if (hasND && hero) { + hero.querySelector('.artist-pin-btn')?.remove(); + const pinBtn = document.createElement('button'); + pinBtn.className = 'artist-pin-btn'; + pinBtn.textContent = _pin ? '⚙ Gepinnt' : '⚙ Falscher Künstler?'; + pinBtn.title = 'Richtigen Deezer-Künstler wählen'; + pinBtn.style.cssText = 'position:absolute;top:12px;right:12px;z-index:5;padding:5px 12px;border-radius:999px;border:1px solid rgba(255,255,255,.25);background:rgba(0,0,0,.45);color:#fff;font-family:var(--font);font-size:12px;font-weight:600;cursor:pointer;backdrop-filter:blur(4px)'; + pinBtn.onclick = () => openArtistPin(artist.id, artist.name); + hero.appendChild(pinBtn); } // Fire all requests immediately so they run in parallel.