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
|
||||
let _recommendedArtistsCache = null;
|
||||
let _recommendedArtistsSource = null;
|
||||
|
||||
async function openRecommendedArtistsModal() {
|
||||
let modal = document.getElementById('recommended-artists-modal');
|
||||
|
|
@ -404,7 +405,7 @@ async function openRecommendedArtistsModal() {
|
|||
// If cached, render instantly and refresh watchlist statuses
|
||||
if (_recommendedArtistsCache) {
|
||||
modal.style.display = 'flex';
|
||||
renderRecommendedArtistsModal(modal, _recommendedArtistsCache);
|
||||
renderRecommendedArtistsModal(modal, _recommendedArtistsCache, _recommendedArtistsSource);
|
||||
checkRecommendedWatchlistStatuses(_recommendedArtistsCache);
|
||||
return;
|
||||
}
|
||||
|
|
@ -444,13 +445,14 @@ async function openRecommendedArtistsModal() {
|
|||
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
|
||||
// Skip artists that already have cached metadata from the initial response
|
||||
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 allIds = data.artists
|
||||
.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 = `
|
||||
<div class="modal-container playlist-modal recommended-modal">
|
||||
<div class="playlist-modal-header">
|
||||
|
|
@ -555,10 +557,12 @@ function renderRecommendedArtistsModal(modal, artists) {
|
|||
const similarText = artist.occurrence_count > 1
|
||||
? `Similar to ${artist.occurrence_count} in your watchlist`
|
||||
: 'Similar to an artist in your watchlist';
|
||||
const artistSource = artist.source || source || _recommendedArtistsSource || '';
|
||||
return `
|
||||
<div class="recommended-artist-card"
|
||||
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"
|
||||
data-artist-id="${artist.artist_id}"
|
||||
data-artist-name="${escapeHtml(artist.artist_name)}">
|
||||
|
|
@ -601,9 +605,10 @@ function renderRecommendedArtistsModal(modal, artists) {
|
|||
const card = e.target.closest('.recommended-artist-card');
|
||||
if (card) {
|
||||
const artistId = card.getAttribute('data-artist-id');
|
||||
const artistSource = card.getAttribute('data-artist-source') || _recommendedArtistsSource || null;
|
||||
const nameEl = card.querySelector('.recommended-card-name');
|
||||
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();
|
||||
navigateToArtistDetail(artistId, artistName);
|
||||
navigateToArtistDetail(artistId, artistName, source || null);
|
||||
}
|
||||
|
||||
async function checkAllHeroWatchlistStatus() {
|
||||
|
|
@ -4354,6 +4359,31 @@ async function unblockDiscoveryArtist(id, name) {
|
|||
|
||||
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() {
|
||||
if (!_yourArtistsCtrl) {
|
||||
_yourArtistsCtrl = createDiscoverSectionController({
|
||||
|
|
@ -4454,11 +4484,12 @@ function _renderYourArtistCard(artist) {
|
|||
).join('');
|
||||
|
||||
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
|
||||
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
|
||||
|
|
|
|||
|
|
@ -633,8 +633,10 @@ async function openDownloadMissingModalForYouTube(virtualPlaylistId, playlistNam
|
|||
function _navigateToArtistFromModal(artistId, artistName, imageUrl, source, playlistId) {
|
||||
if (!artistName) return;
|
||||
// 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);
|
||||
navigateToArtistDetail(artistId || artistName, artistName, source || null);
|
||||
navigateToArtistDetail(artistId || artistName, artistName, resolvedSource || null);
|
||||
}
|
||||
|
||||
async function closeDownloadMissingModal(playlistId) {
|
||||
|
|
|
|||
|
|
@ -1016,6 +1016,7 @@ async function openDownloadMissingModalForArtistAlbum(virtualPlaylistId, playlis
|
|||
type: 'artist_album',
|
||||
artist: artist,
|
||||
album: album,
|
||||
source: artist?.source || album?.source || artistsPageState.artistDiscography?.source || null,
|
||||
trackCount: spotifyTracks.length,
|
||||
playlistId: virtualPlaylistId
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1992,6 +1992,7 @@ function generateDownloadModalHeroSection(context) {
|
|||
// Artist/album context - show artist + album images
|
||||
const artistImage = artist?.image_url || artist?.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
|
||||
if (albumImage) {
|
||||
|
|
@ -2006,7 +2007,7 @@ function generateDownloadModalHeroSection(context) {
|
|||
</div>
|
||||
<div class="download-missing-modal-hero-metadata">
|
||||
<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">
|
||||
<span class="download-missing-modal-hero-detail">${album.album_type || 'Album'}</span>
|
||||
<span class="download-missing-modal-hero-detail">${trackCount} tracks</span>
|
||||
|
|
|
|||
Loading…
Reference in a new issue