From 253e4d1e4a0e22bdf7143e4516f4e24c940d770a Mon Sep 17 00:00:00 2001 From: Broque Thomas <26755000+Nezreka@users.noreply.github.com> Date: Thu, 23 Apr 2026 23:04:39 -0700 Subject: [PATCH] Fix Discover hero 'View Discography' 404ing on source-only artists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clicking 'View Discography' on the Discover hero slideshow was calling navigateToArtistDetail(id, name) without the third 'source' argument. loadArtistDetailData then omits the `source` query param, so /api/artist-detail falls through to a local DB lookup and returns 404 for artists that don't exist in the library — which is nearly every hero artist, since they come from discover similar-artists. Regression from the unification PR (93f1941) that rewrote the click handler to route through the standalone /artist-detail page instead of the old inline Artists view. The rewrite didn't thread the source. Backend already includes `artist.source` on each hero entry. Fix: - Stash artist.source as data-source on #discover-hero-discography when displayDiscoverHeroArtist populates the card. - Read data-source in viewDiscoverHeroDiscography and pass it as the third arg to navigateToArtistDetail, so the eventual API call includes `?source=itunes/deezer/etc.` and returns the synthesized discography. Reproduced by clicking View Discography on a non-Spotify hero artist (log showed `GET /api/artist-detail/76258852?name=ДЕТИ+RAVE → 404, Getting artist detail for ID: 76258852 (source=library)`). --- webui/static/discover.js | 14 ++++++++++++-- webui/static/helper.js | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/webui/static/discover.js b/webui/static/discover.js index d322cc81..eb50d2ba 100644 --- a/webui/static/discover.js +++ b/webui/static/discover.js @@ -278,6 +278,12 @@ function displayDiscoverHeroArtist(artist) { if (discographyBtn && artistId) { discographyBtn.setAttribute('data-artist-id', artistId); discographyBtn.setAttribute('data-artist-name', artist.artist_name); + // Source the click handler will pass to navigateToArtistDetail. Without + // this, source-only hero artists (which is the typical case — they + // come from discover similar-artists, not the library) get looked up + // as library IDs and 404. Backend always includes artist.source. + if (artist.source) discographyBtn.setAttribute('data-source', artist.source); + else discographyBtn.removeAttribute('data-source'); // Also store both IDs for cross-source operations if (artist.spotify_artist_id) discographyBtn.setAttribute('data-spotify-id', artist.spotify_artist_id); if (artist.itunes_artist_id) discographyBtn.setAttribute('data-itunes-id', artist.itunes_artist_id); @@ -815,14 +821,18 @@ async function viewDiscoverHeroDiscography() { const artistId = button.getAttribute('data-artist-id'); const artistName = button.getAttribute('data-artist-name'); + // Pass the source so /api/artist-detail knows to synthesize from that + // metadata provider instead of doing a local DB lookup. Hero similar + // artists are almost always source-only (not in the library). + const source = button.getAttribute('data-source') || null; if (!artistId || !artistName) { console.error('No artist data found for discography view'); return; } - console.log(`🎵 Navigating to artist detail for: ${artistName}`); - navigateToArtistDetail(artistId, artistName); + console.log(`🎵 Navigating to artist detail for: ${artistName} (source: ${source || 'library'})`); + navigateToArtistDetail(artistId, artistName, source); } function showDiscoverHeroEmpty() { diff --git a/webui/static/helper.js b/webui/static/helper.js index 411bbe1b..8a13ad18 100644 --- a/webui/static/helper.js +++ b/webui/static/helper.js @@ -3461,6 +3461,7 @@ const WHATS_NEW = { { title: 'Fix Soulseek Handoff from Global Search Going Through Metadata Flow', desc: 'When you clicked the Soulseek icon in the sidebar global search popover, it navigated to /search and wrote the query into the enhanced-search input — which then ran the metadata flow against whatever your default source was (Spotify, Deezer, etc.) instead of the raw Soulseek file search you actually wanted. Cin flagged it during PR review. Now the handoff pre-fills the basic-search input directly and clicks the Search page\'s Soulseek icon so the controller\'s onSoulseekSelected callback owns the section swap and runs performDownloadsSearch with the right query', page: 'search', unreleased: true }, { title: 'Stale Search Requests No Longer Flash Empty Results on Fast Retype', desc: 'Cin flagged a race in createSearchController: when you typed a query then quickly re-typed before the first fetch returned, the first fetch\'s catch block (firing on AbortError after the second submitQuery aborted it) cleared loadingSources and notified the UI, causing a brief flash of empty/error state while the new query\'s fetch was still mid-flight. Added a monotonic _requestSeq token — each fetch captures the next value, and stale completions bail before mutating shared state. The controller still aborts in-flight fetches on supersession; this just keeps the abort-cleanup of the old request from clobbering the new one\'s spinner', page: 'search', unreleased: true }, { title: 'Source Picker Dims Soulseek When slskd Isn\'t Configured', desc: 'Cin pointed out that the Soulseek icon was always rendered as configured, so users without slskd set up could click it and fire searches that would never succeed. Soulseek is now in the backend config-status registry as `required: [slskd_url]` and removed from the frontend\'s always-configured set. Without slskd, the icon dims and clicking it routes to Settings → Downloads tab (where the slskd URL field lives, gated behind the download-source dropdown) instead of Settings → Connections', page: 'search', unreleased: true }, + { title: 'Fix Discover Hero "View Discography" 404ing on Source Artists', desc: 'Clicking "View Discography" on the Discover page hero slideshow was calling navigateToArtistDetail without a source, so /api/artist-detail defaulted to a library lookup and returned 404 for artists that don\'t exist in your library (which is nearly every hero artist — they come from discover similar-artists, not the library). Regression from the unification PR that rewrote the click handler to route to /artist-detail but forgot to pass the source. Backend already sends artist.source on each hero entry; we now stash it as data-source on the discography button and thread it through to navigateToArtistDetail so the API call includes source=itunes/deezer/etc. and returns the synthesized discography', page: 'discover', unreleased: true }, ], '2.39': [ // --- April 22, 2026 ---