Preserve source when opening artist detail
This commit is contained in:
parent
6af5d191cd
commit
cd715f8697
4 changed files with 49 additions and 14 deletions
|
|
@ -387,6 +387,7 @@ async function watchAllHeroArtists(btn) {
|
||||||
|
|
||||||
// Cache for recommended artists data so reopening is instant
|
// Cache for recommended artists data so reopening is instant
|
||||||
let _recommendedArtistsCache = null;
|
let _recommendedArtistsCache = null;
|
||||||
|
let _recommendedArtistsSource = null;
|
||||||
|
|
||||||
async function openRecommendedArtistsModal() {
|
async function openRecommendedArtistsModal() {
|
||||||
let modal = document.getElementById('recommended-artists-modal');
|
let modal = document.getElementById('recommended-artists-modal');
|
||||||
|
|
@ -404,7 +405,7 @@ async function openRecommendedArtistsModal() {
|
||||||
// If cached, render instantly and refresh watchlist statuses
|
// If cached, render instantly and refresh watchlist statuses
|
||||||
if (_recommendedArtistsCache) {
|
if (_recommendedArtistsCache) {
|
||||||
modal.style.display = 'flex';
|
modal.style.display = 'flex';
|
||||||
renderRecommendedArtistsModal(modal, _recommendedArtistsCache);
|
renderRecommendedArtistsModal(modal, _recommendedArtistsCache, _recommendedArtistsSource);
|
||||||
checkRecommendedWatchlistStatuses(_recommendedArtistsCache);
|
checkRecommendedWatchlistStatuses(_recommendedArtistsCache);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -444,13 +445,14 @@ async function openRecommendedArtistsModal() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render cards immediately with fallback images
|
|
||||||
_recommendedArtistsCache = data.artists;
|
|
||||||
renderRecommendedArtistsModal(modal, data.artists);
|
|
||||||
|
|
||||||
// Phase 2: Enrich with images/genres progressively in batches of 50
|
// Phase 2: Enrich with images/genres progressively in batches of 50
|
||||||
// Skip artists that already have cached metadata from the initial response
|
// Skip artists that already have cached metadata from the initial response
|
||||||
const source = data.source || 'spotify';
|
const source = data.source || 'spotify';
|
||||||
|
// Render cards immediately with fallback images
|
||||||
|
_recommendedArtistsCache = data.artists;
|
||||||
|
_recommendedArtistsSource = source;
|
||||||
|
renderRecommendedArtistsModal(modal, data.artists, source);
|
||||||
|
|
||||||
const idKey = source === 'spotify' ? 'spotify_artist_id' : source === 'deezer' ? 'deezer_artist_id' : 'itunes_artist_id';
|
const idKey = source === 'spotify' ? 'spotify_artist_id' : source === 'deezer' ? 'deezer_artist_id' : 'itunes_artist_id';
|
||||||
const allIds = data.artists
|
const allIds = data.artists
|
||||||
.filter(a => !a.image_url) // Only enrich artists without cached images
|
.filter(a => !a.image_url) // Only enrich artists without cached images
|
||||||
|
|
@ -521,7 +523,7 @@ async function openRecommendedArtistsModal() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderRecommendedArtistsModal(modal, artists) {
|
function renderRecommendedArtistsModal(modal, artists, source = null) {
|
||||||
modal.innerHTML = `
|
modal.innerHTML = `
|
||||||
<div class="modal-container playlist-modal recommended-modal">
|
<div class="modal-container playlist-modal recommended-modal">
|
||||||
<div class="playlist-modal-header">
|
<div class="playlist-modal-header">
|
||||||
|
|
@ -555,10 +557,12 @@ function renderRecommendedArtistsModal(modal, artists) {
|
||||||
const similarText = artist.occurrence_count > 1
|
const similarText = artist.occurrence_count > 1
|
||||||
? `Similar to ${artist.occurrence_count} in your watchlist`
|
? `Similar to ${artist.occurrence_count} in your watchlist`
|
||||||
: 'Similar to an artist in your watchlist';
|
: 'Similar to an artist in your watchlist';
|
||||||
|
const artistSource = artist.source || source || _recommendedArtistsSource || '';
|
||||||
return `
|
return `
|
||||||
<div class="recommended-artist-card"
|
<div class="recommended-artist-card"
|
||||||
data-artist-name="${escapeHtml(artist.artist_name).toLowerCase()}"
|
data-artist-name="${escapeHtml(artist.artist_name).toLowerCase()}"
|
||||||
data-artist-id="${artist.artist_id}">
|
data-artist-id="${artist.artist_id}"
|
||||||
|
data-artist-source="${escapeHtml(artistSource)}">
|
||||||
<button class="recommended-card-watchlist-btn"
|
<button class="recommended-card-watchlist-btn"
|
||||||
data-artist-id="${artist.artist_id}"
|
data-artist-id="${artist.artist_id}"
|
||||||
data-artist-name="${escapeHtml(artist.artist_name)}">
|
data-artist-name="${escapeHtml(artist.artist_name)}">
|
||||||
|
|
@ -601,9 +605,10 @@ function renderRecommendedArtistsModal(modal, artists) {
|
||||||
const card = e.target.closest('.recommended-artist-card');
|
const card = e.target.closest('.recommended-artist-card');
|
||||||
if (card) {
|
if (card) {
|
||||||
const artistId = card.getAttribute('data-artist-id');
|
const artistId = card.getAttribute('data-artist-id');
|
||||||
|
const artistSource = card.getAttribute('data-artist-source') || _recommendedArtistsSource || null;
|
||||||
const nameEl = card.querySelector('.recommended-card-name');
|
const nameEl = card.querySelector('.recommended-card-name');
|
||||||
const artistName = nameEl ? nameEl.textContent : '';
|
const artistName = nameEl ? nameEl.textContent : '';
|
||||||
viewRecommendedArtistDiscography(artistId, artistName);
|
viewRecommendedArtistDiscography(artistId, artistName, artistSource);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -734,9 +739,9 @@ async function checkRecommendedWatchlistStatuses(artists) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function viewRecommendedArtistDiscography(artistId, artistName) {
|
async function viewRecommendedArtistDiscography(artistId, artistName, source = null) {
|
||||||
closeRecommendedArtistsModal();
|
closeRecommendedArtistsModal();
|
||||||
navigateToArtistDetail(artistId, artistName);
|
navigateToArtistDetail(artistId, artistName, source || null);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkAllHeroWatchlistStatus() {
|
async function checkAllHeroWatchlistStatus() {
|
||||||
|
|
@ -4354,6 +4359,31 @@ async function unblockDiscoveryArtist(id, name) {
|
||||||
|
|
||||||
let _yourArtistsCtrl = null;
|
let _yourArtistsCtrl = null;
|
||||||
|
|
||||||
|
function _pickArtistDetailSource(artist) {
|
||||||
|
if (!artist) return { id: '', source: '' };
|
||||||
|
const sourceFields = {
|
||||||
|
spotify: 'spotify_artist_id',
|
||||||
|
deezer: 'deezer_artist_id',
|
||||||
|
itunes: 'itunes_artist_id',
|
||||||
|
discogs: 'discogs_artist_id',
|
||||||
|
amazon: 'amazon_artist_id',
|
||||||
|
musicbrainz: 'musicbrainz_artist_id',
|
||||||
|
hydrabase: 'soul_id',
|
||||||
|
};
|
||||||
|
const active = String(artist.active_source || artist.source || '').toLowerCase();
|
||||||
|
const activeField = sourceFields[active];
|
||||||
|
if (activeField && artist[activeField]) {
|
||||||
|
return { id: String(artist[activeField]), source: active };
|
||||||
|
}
|
||||||
|
for (const [source, field] of Object.entries(sourceFields)) {
|
||||||
|
if (artist[field]) return { id: String(artist[field]), source };
|
||||||
|
}
|
||||||
|
if (artist.active_source_id && activeField) {
|
||||||
|
return { id: String(artist.active_source_id), source: active };
|
||||||
|
}
|
||||||
|
return { id: '', source: '' };
|
||||||
|
}
|
||||||
|
|
||||||
async function loadYourArtists() {
|
async function loadYourArtists() {
|
||||||
if (!_yourArtistsCtrl) {
|
if (!_yourArtistsCtrl) {
|
||||||
_yourArtistsCtrl = createDiscoverSectionController({
|
_yourArtistsCtrl = createDiscoverSectionController({
|
||||||
|
|
@ -4454,11 +4484,12 @@ function _renderYourArtistCard(artist) {
|
||||||
).join('');
|
).join('');
|
||||||
|
|
||||||
const watchlistClass = artist.on_watchlist ? 'active' : '';
|
const watchlistClass = artist.on_watchlist ? 'active' : '';
|
||||||
const hasId = artist.active_source_id && artist.active_source_id !== '';
|
const detailSource = _pickArtistDetailSource(artist);
|
||||||
|
const hasId = detailSource.id && detailSource.id !== '';
|
||||||
|
|
||||||
// Navigate to Artists page (name click) — source artist id, needs inline view
|
// Navigate to Artists page (name click) — source artist id, needs inline view
|
||||||
const navAction = hasId
|
const navAction = hasId
|
||||||
? `event.stopPropagation(); navigateToArtistDetail('${escapeForInlineJs(artist.active_source_id)}', '${escapeForInlineJs(artist.artist_name)}')`
|
? `event.stopPropagation(); navigateToArtistDetail('${escapeForInlineJs(detailSource.id)}', '${escapeForInlineJs(artist.artist_name)}', '${escapeForInlineJs(detailSource.source)}' || null)`
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
// Open info modal (card body click) — pass pool ID so we can look up all data
|
// Open info modal (card body click) — pass pool ID so we can look up all data
|
||||||
|
|
|
||||||
|
|
@ -633,8 +633,10 @@ async function openDownloadMissingModalForYouTube(virtualPlaylistId, playlistNam
|
||||||
function _navigateToArtistFromModal(artistId, artistName, imageUrl, source, playlistId) {
|
function _navigateToArtistFromModal(artistId, artistName, imageUrl, source, playlistId) {
|
||||||
if (!artistName) return;
|
if (!artistName) return;
|
||||||
// Close the download modal
|
// Close the download modal
|
||||||
|
const process = playlistId ? activeDownloadProcesses[playlistId] : null;
|
||||||
|
const resolvedSource = source || process?.artist?.source || process?.album?.source || process?.source || null;
|
||||||
if (playlistId) closeDownloadMissingModal(playlistId);
|
if (playlistId) closeDownloadMissingModal(playlistId);
|
||||||
navigateToArtistDetail(artistId || artistName, artistName, source || null);
|
navigateToArtistDetail(artistId || artistName, artistName, resolvedSource || null);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function closeDownloadMissingModal(playlistId) {
|
async function closeDownloadMissingModal(playlistId) {
|
||||||
|
|
|
||||||
|
|
@ -1016,6 +1016,7 @@ async function openDownloadMissingModalForArtistAlbum(virtualPlaylistId, playlis
|
||||||
type: 'artist_album',
|
type: 'artist_album',
|
||||||
artist: artist,
|
artist: artist,
|
||||||
album: album,
|
album: album,
|
||||||
|
source: artist?.source || album?.source || artistsPageState.artistDiscography?.source || null,
|
||||||
trackCount: spotifyTracks.length,
|
trackCount: spotifyTracks.length,
|
||||||
playlistId: virtualPlaylistId
|
playlistId: virtualPlaylistId
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1992,6 +1992,7 @@ function generateDownloadModalHeroSection(context) {
|
||||||
// Artist/album context - show artist + album images
|
// Artist/album context - show artist + album images
|
||||||
const artistImage = artist?.image_url || artist?.images?.[0]?.url;
|
const artistImage = artist?.image_url || artist?.images?.[0]?.url;
|
||||||
const albumImage = album?.image_url || album?.images?.[0]?.url;
|
const albumImage = album?.image_url || album?.images?.[0]?.url;
|
||||||
|
const artistSource = artist?.source || album?.source || context.source || '';
|
||||||
|
|
||||||
// Use album image as background if available
|
// Use album image as background if available
|
||||||
if (albumImage) {
|
if (albumImage) {
|
||||||
|
|
@ -2006,7 +2007,7 @@ function generateDownloadModalHeroSection(context) {
|
||||||
</div>
|
</div>
|
||||||
<div class="download-missing-modal-hero-metadata">
|
<div class="download-missing-modal-hero-metadata">
|
||||||
<h1 class="download-missing-modal-hero-title">${escapeHtml(album.name || 'Unknown Album')}</h1>
|
<h1 class="download-missing-modal-hero-title">${escapeHtml(album.name || 'Unknown Album')}</h1>
|
||||||
<div class="download-missing-modal-hero-subtitle">by <a href="#" class="hero-artist-link" onclick="event.preventDefault();_navigateToArtistFromModal('${escapeHtml(artist.id || '')}','${escapeForInlineJs(artist.name || '')}','${escapeHtml(artist.image_url || '')}','${escapeHtml(artist.source || '')}','${escapeHtml(context.playlistId || '')}')">${escapeHtml(artist.name || 'Unknown Artist')}</a></div>
|
<div class="download-missing-modal-hero-subtitle">by <a href="#" class="hero-artist-link" onclick="event.preventDefault();_navigateToArtistFromModal('${escapeHtml(artist.id || '')}','${escapeForInlineJs(artist.name || '')}','${escapeHtml(artist.image_url || '')}','${escapeHtml(artistSource)}','${escapeHtml(context.playlistId || '')}')">${escapeHtml(artist.name || 'Unknown Artist')}</a></div>
|
||||||
<div class="download-missing-modal-hero-details">
|
<div class="download-missing-modal-hero-details">
|
||||||
<span class="download-missing-modal-hero-detail">${album.album_type || 'Album'}</span>
|
<span class="download-missing-modal-hero-detail">${album.album_type || 'Album'}</span>
|
||||||
<span class="download-missing-modal-hero-detail">${trackCount} tracks</span>
|
<span class="download-missing-modal-hero-detail">${trackCount} tracks</span>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue