From 18146098a7e084de6624b195897905c7c646632c Mon Sep 17 00:00:00 2001 From: Broque Thomas <26755000+Nezreka@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:52:54 -0700 Subject: [PATCH] Revert "Route source-artist clicks to standalone /artist-detail page" This reverts commit 1c345e4eb591e747b987eac99de0ee1e588e26bd. --- webui/static/api-monitor.js | 10 +++++++++- webui/static/discover.js | 34 +++++++++++++++++++++++++++------- webui/static/downloads.js | 25 ++++++++++++++++++++++--- webui/static/search.js | 12 +++++++++++- 4 files changed, 69 insertions(+), 12 deletions(-) diff --git a/webui/static/api-monitor.js b/webui/static/api-monitor.js index c900d824..bc86b223 100644 --- a/webui/static/api-monitor.js +++ b/webui/static/api-monitor.js @@ -2385,8 +2385,16 @@ async function openWatchlistArtistDetailView(artistId, artistName) { source = spotify_artist_id ? 'spotify' : discogs_artist_id ? 'discogs' : deezer_artist_id ? 'deezer' : 'itunes'; } if (discogId) { + // Watchlist discogId is a metadata-source id (Spotify/Deezer/iTunes), + // not a library PK — route through the Artists page inline view. closeWatchlistArtistDetailView(); - navigateToArtistDetail(discogId, artistName, source); + navigateToPage('artists'); + setTimeout(() => { + selectArtistForDetail( + { id: discogId, name: artistName, image_url: artist.image_url || '' }, + { source: source } + ); + }, 200); } }); diff --git a/webui/static/discover.js b/webui/static/discover.js index e70e3b65..e0293a60 100644 --- a/webui/static/discover.js +++ b/webui/static/discover.js @@ -739,7 +739,14 @@ async function checkRecommendedWatchlistStatuses(artists) { async function viewRecommendedArtistDiscography(artistId, artistName) { closeRecommendedArtistsModal(); - navigateToArtistDetail(artistId, artistName); + + const artist = { id: artistId, name: artistName }; + + // Recommended artists come from the metadata source — route through the + // Artists page's inline view so the source-provided id resolves correctly. + navigateToPage('artists'); + await new Promise(resolve => setTimeout(resolve, 100)); + await selectArtistForDetail(artist); } async function checkAllHeroWatchlistStatus() { @@ -821,8 +828,21 @@ async function viewDiscoverHeroDiscography() { return; } + const artist = { + id: artistId, + name: artistName, + image_url: discoverHeroArtists[discoverHeroIndex]?.image_url || '', + genres: discoverHeroArtists[discoverHeroIndex]?.genres || [], + popularity: discoverHeroArtists[discoverHeroIndex]?.popularity || 0 + }; + console.log(`🎵 Navigating to artist detail for: ${artistName}`); - navigateToArtistDetail(artistId, artistName); + + // Hero artists are source-provided recommendations — route through the + // Artists page's inline view so the source id resolves correctly. + navigateToPage('artists'); + await new Promise(resolve => setTimeout(resolve, 100)); + await selectArtistForDetail(artist); } function showDiscoverHeroEmpty() { @@ -4613,9 +4633,9 @@ function _renderYourArtistCard(artist) { const watchlistClass = artist.on_watchlist ? 'active' : ''; const hasId = artist.active_source_id && artist.active_source_id !== ''; - // Navigate to standalone artist detail page (name click) + // Navigate to Artists page (name click) — source artist id, needs inline view const navAction = hasId - ? `event.stopPropagation(); navigateToArtistDetail('${escapeForInlineJs(artist.active_source_id)}', '${escapeForInlineJs(artist.artist_name)}')` + ? `event.stopPropagation(); navigateToPage('artists'); setTimeout(() => selectArtistForDetail({id:'${escapeForInlineJs(artist.active_source_id)}', name:'${escapeForInlineJs(artist.artist_name)}', image_url:'${escapeForInlineJs(img)}'}), 200)` : ''; // Open info modal (card body click) — pass pool ID so we can look up all data @@ -4794,7 +4814,7 @@ async function openYourArtistInfoModal(poolId) { Explore - @@ -6694,7 +6714,7 @@ function _artMapSetupInteraction(canvas) {
Artist Info
-
+
💿 View Discography
@@ -7382,7 +7402,7 @@ async function openGenreDeepDive(genre) { // Always open on Artists page with discography — pass source for correct routing const imgUrl = _esc(a.image_url || ''); const artSource = _esc(a.source || ''); - const clickAction = `onclick="document.getElementById('genre-deep-dive-modal').remove();navigateToArtistDetail('${_esc(a.entity_id)}','${_esc(a.name)}','${artSource}' || null)"`; + const clickAction = `onclick="document.getElementById('genre-deep-dive-modal').remove();navigateToPage('artists');setTimeout(()=>selectArtistForDetail({id:'${_esc(a.entity_id)}',name:'${_esc(a.name)}',image_url:'${imgUrl}'},{source:'${artSource}'}),300)"`; const srcClass = (a.source || '').toLowerCase(); return `
diff --git a/webui/static/downloads.js b/webui/static/downloads.js index f13bfb2e..86d0ad24 100644 --- a/webui/static/downloads.js +++ b/webui/static/downloads.js @@ -634,7 +634,15 @@ function _navigateToArtistFromModal(artistId, artistName, imageUrl, source, play if (!artistName) return; // Close the download modal if (playlistId) closeDownloadMissingModal(playlistId); - navigateToArtistDetail(artistId || artistName, artistName, source || null); + // The id from a download modal is typically a metadata-source id; route via + // the Artists page inline view so the source-aware discography endpoint runs. + navigateToPage('artists'); + setTimeout(() => { + selectArtistForDetail( + { id: artistId || artistName, name: artistName, image_url: imageUrl || '' }, + source ? { source: source } : undefined + ); + }, 200); } async function closeDownloadMissingModal(playlistId) { @@ -5425,8 +5433,19 @@ function _gsSwitchSource(src) { function _gsClickArtist(id, name, isLibrary) { _gsDeactivate(); - const source = isLibrary ? null : (_gsState.activeSource || null); - navigateToArtistDetail(id, name, source); + if (isLibrary) { + // Library artists: id is a local DB PK — use the standalone artist-detail page. + navigateToArtistDetail(id, name); + } else { + // Source artists: id is a Deezer/Spotify/iTunes id — route to the Artists + // page's inline view which fetches discography from the source. + navigateToPage('artists'); + setTimeout(() => { + selectArtistForDetail({ id, name, image_url: '' }, { + source: _gsState.activeSource || '', + }); + }, 150); + } } async function _gsClickAlbum(albumId, albumName, artistName, imageUrl, source) { diff --git a/webui/static/search.js b/webui/static/search.js index be9147c5..fd8b0b37 100644 --- a/webui/static/search.js +++ b/webui/static/search.js @@ -340,7 +340,17 @@ function initializeSearchModeToggle() { const sourceOverride = _activeSearchSource; console.log(`🎵 Opening artist detail: ${artist.name} (ID: ${artist.id}, source: ${sourceOverride})`); hideDropdown(); - navigateToArtistDetail(artist.id, artist.name, sourceOverride || null); + + // Source artists are NOT library entries — their id is a Deezer/ + // Spotify/iTunes id, not a library PK. Route to the Artists page's + // inline selectArtistForDetail which fetches discography from the + // source directly, not the library's /api/artist-detail endpoint. + navigateToPage('artists'); + await new Promise(resolve => setTimeout(resolve, 100)); + await selectArtistForDetail(artist, { + source: sourceOverride, + plugin: artist.external_urls?.hydrabase_plugin, + }); } }) );