Merge pull request #356 from kettui/fix/album-track-source-propagation
Fix album track source propagation
This commit is contained in:
commit
200b68e65e
4 changed files with 58 additions and 12 deletions
|
|
@ -500,7 +500,7 @@ async function selectArtistForDetail(artist, options = {}) {
|
|||
// Update state
|
||||
artistsPageState.selectedArtist = artist;
|
||||
artistsPageState.currentView = 'detail';
|
||||
artistsPageState.sourceOverride = options.source || null;
|
||||
artistsPageState.sourceOverride = options.source || artist.source || null;
|
||||
artistsPageState.pluginOverride = options.plugin || null;
|
||||
|
||||
// Show detail state
|
||||
|
|
@ -510,7 +510,7 @@ async function selectArtistForDetail(artist, options = {}) {
|
|||
updateArtistDetailHeader(artist);
|
||||
|
||||
// Load discography (pass artist name for cross-source fallback)
|
||||
await loadArtistDiscography(artist.id, artist.name, options.source, options.plugin);
|
||||
await loadArtistDiscography(artist.id, artist.name, artistsPageState.sourceOverride, options.plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -528,6 +528,13 @@ async function loadArtistDiscography(artistId, artistName = null, sourceOverride
|
|||
if (artistsPageState.cache.discography[cacheKey]) {
|
||||
console.log('📦 Using cached discography');
|
||||
const cachedDiscography = artistsPageState.cache.discography[cacheKey];
|
||||
if (artistsPageState.selectedArtist) {
|
||||
artistsPageState.selectedArtist = {
|
||||
...artistsPageState.selectedArtist,
|
||||
source: cachedDiscography.source || sourceOverride || artistsPageState.selectedArtist.source || null,
|
||||
};
|
||||
}
|
||||
artistsPageState.sourceOverride = cachedDiscography.source || sourceOverride || artistsPageState.sourceOverride || null;
|
||||
displayArtistDiscography(cachedDiscography);
|
||||
|
||||
// Load similar artists in parallel (don't wait) — always uses primary source
|
||||
|
|
@ -574,6 +581,16 @@ async function loadArtistDiscography(artistId, artistName = null, sourceOverride
|
|||
source: data.source || sourceOverride || null,
|
||||
};
|
||||
|
||||
// Keep the resolved metadata source on the selected artist so album clicks
|
||||
// can pass it through to /api/album/<id>/tracks.
|
||||
if (artistsPageState.selectedArtist) {
|
||||
artistsPageState.selectedArtist = {
|
||||
...artistsPageState.selectedArtist,
|
||||
source: discography.source,
|
||||
};
|
||||
}
|
||||
artistsPageState.sourceOverride = discography.source || artistsPageState.sourceOverride || null;
|
||||
|
||||
// Update selected artist with full details from backend (includes MusicBrainz ID)
|
||||
if (data.artist) {
|
||||
console.log('✨ Updating artist details with fresh data from backend');
|
||||
|
|
@ -2127,8 +2144,9 @@ async function createArtistAlbumVirtualPlaylist(album, albumType) {
|
|||
|
||||
// Fetch album tracks from backend (pass name/artist for Hydrabase support)
|
||||
const _aat1 = new URLSearchParams({ name: album.name || '', artist: artist.name || '' });
|
||||
if (artistsPageState.sourceOverride) {
|
||||
_aat1.set('source', artistsPageState.sourceOverride);
|
||||
const albumSource = artistsPageState.sourceOverride || album.source || artist.source || artistsPageState.artistDiscography?.source || null;
|
||||
if (albumSource) {
|
||||
_aat1.set('source', albumSource);
|
||||
}
|
||||
if (artistsPageState.pluginOverride) {
|
||||
_aat1.set('plugin', artistsPageState.pluginOverride);
|
||||
|
|
@ -2227,7 +2245,8 @@ async function openDownloadMissingModalForArtistAlbum(virtualPlaylistId, playlis
|
|||
// Additional metadata for artist albums
|
||||
artist: artist,
|
||||
album: album,
|
||||
albumType: album.album_type
|
||||
albumType: album.album_type,
|
||||
source: artist?.source || album?.source || artistsPageState.artistDiscography?.source || null
|
||||
};
|
||||
|
||||
// Generate hero section — 'artist_album' for releases, 'playlist' for charts/compilations
|
||||
|
|
@ -4608,4 +4627,3 @@ function renderEnrichmentCards(enrichment) {
|
|||
}
|
||||
|
||||
// ===============================
|
||||
|
||||
|
|
|
|||
|
|
@ -639,6 +639,7 @@ let artistDetailPageState = {
|
|||
isInitialized: false,
|
||||
currentArtistId: null,
|
||||
currentArtistName: null,
|
||||
currentArtistSource: null,
|
||||
enhancedView: false,
|
||||
enhancedData: null,
|
||||
expandedAlbums: new Set(),
|
||||
|
|
@ -671,6 +672,7 @@ function navigateToArtistDetail(artistId, artistName) {
|
|||
// Store current artist info and reset enhanced view state
|
||||
artistDetailPageState.currentArtistId = artistId;
|
||||
artistDetailPageState.currentArtistName = artistName;
|
||||
artistDetailPageState.currentArtistSource = null;
|
||||
artistDetailPageState.enhancedData = null;
|
||||
artistDetailPageState.expandedAlbums = new Set();
|
||||
artistDetailPageState.selectedTracks = new Set();
|
||||
|
|
@ -788,6 +790,9 @@ async function loadArtistDetailData(artistId, artistName) {
|
|||
// Populate the page with data (which updates the hero section and sets textContent)
|
||||
populateArtistDetailPage(data);
|
||||
|
||||
// Keep the resolved metadata source for album-track lookups.
|
||||
artistDetailPageState.currentArtistSource = data.discography?.source || data.artist?.source || null;
|
||||
|
||||
// Update header with artist name and MusicBrainz link LAST to avoid overwrite
|
||||
updateArtistDetailPageHeaderWithData(data.artist);
|
||||
|
||||
|
|
@ -1504,7 +1509,8 @@ function createReleaseCard(release) {
|
|||
const currentArtist = artistDetailPageState.currentArtistName ? {
|
||||
id: artistDetailPageState.currentArtistId,
|
||||
name: artistDetailPageState.currentArtistName,
|
||||
image_url: getArtistImageFromPage() || '' // Get artist image from page
|
||||
image_url: getArtistImageFromPage() || '', // Get artist image from page
|
||||
source: artistDetailPageState.currentArtistSource || null
|
||||
} : null;
|
||||
|
||||
if (!currentArtist) {
|
||||
|
|
@ -1515,6 +1521,9 @@ function createReleaseCard(release) {
|
|||
|
||||
// Load tracks for the album (pass name/artist for Hydrabase support)
|
||||
const _aat2 = new URLSearchParams({ name: albumData.name || '', artist: currentArtist.name || '' });
|
||||
if (currentArtist.source) {
|
||||
_aat2.set('source', currentArtist.source);
|
||||
}
|
||||
const response = await fetch(`/api/album/${albumData.id}/tracks?${_aat2}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to load album tracks: ${response.status}`);
|
||||
|
|
@ -1997,8 +2006,10 @@ async function openDiscographyModal() {
|
|||
discography = { albums: data.albums || [], singles: data.singles || [] };
|
||||
if (discography.albums.length > 0 || discography.singles.length > 0) {
|
||||
artistsPageState.artistDiscography = discography;
|
||||
artistsPageState.sourceOverride = data.source || artistsPageState.sourceOverride || null;
|
||||
// Use metadata source ID for the modal (needed for download API calls)
|
||||
if (metadataArtistId) artist.id = metadataArtistId;
|
||||
artist.source = data.source || null;
|
||||
artistsPageState.selectedArtist = artist;
|
||||
} else {
|
||||
discography = null;
|
||||
|
|
@ -6650,4 +6661,3 @@ async function updateLibraryWatchlistButtonStatus(artistId) {
|
|||
}
|
||||
|
||||
// =================================
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,18 @@ async function rehydrateArtistAlbumModal(virtualPlaylistId, playlistName, batchI
|
|||
|
||||
// Fetch the album tracks to get proper artist and album data
|
||||
try {
|
||||
const response = await fetch(`/api/album/${albumId}/tracks`);
|
||||
const rehydrateProcess = activeDownloadProcesses[virtualPlaylistId];
|
||||
const albumSource = rehydrateProcess?.source || rehydrateProcess?.artist?.source || rehydrateProcess?.album?.source || null;
|
||||
const artistName = rehydrateProcess?.artist?.name || '';
|
||||
const params = new URLSearchParams({
|
||||
name: playlistName || '',
|
||||
artist: artistName
|
||||
});
|
||||
if (albumSource) {
|
||||
params.set('source', albumSource);
|
||||
}
|
||||
|
||||
const response = await fetch(`/api/album/${albumId}/tracks?${params}`);
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.success || !data.album || !data.tracks) {
|
||||
|
|
@ -139,12 +150,17 @@ async function rehydrateArtistAlbumModal(virtualPlaylistId, playlistName, batchI
|
|||
|
||||
const album = data.album;
|
||||
const tracks = data.tracks;
|
||||
const source = data.source || tracks[0]?._source || albumSource || null;
|
||||
|
||||
// Extract artist info from the first track (all tracks should have same artist)
|
||||
const artist = {
|
||||
id: artistId,
|
||||
name: tracks[0].artists[0] // Use first artist name from first track
|
||||
name: tracks[0].artists[0], // Use first artist name from first track
|
||||
source
|
||||
};
|
||||
if (source) {
|
||||
album.source = source;
|
||||
}
|
||||
|
||||
console.log(`✅ Retrieved album data: "${album.name}" by ${artist.name} (${tracks.length} tracks)`);
|
||||
|
||||
|
|
@ -2536,4 +2552,3 @@ function _extractM3UTracks(tracks) {
|
|||
}
|
||||
|
||||
// ==================================================================================
|
||||
|
||||
|
|
|
|||
|
|
@ -2389,6 +2389,10 @@ async function confirmMatch() {
|
|||
const artistId = currentMatchingData.selectedArtist.id;
|
||||
const albumId = currentMatchingData.selectedAlbum.id;
|
||||
const _aat3 = new URLSearchParams({ name: currentMatchingData.selectedAlbum.name || '', artist: currentMatchingData.selectedArtist.name || '' });
|
||||
const albumSource = currentMatchingData.selectedAlbum?.source || currentMatchingData.selectedArtist?.source || null;
|
||||
if (albumSource) {
|
||||
_aat3.set('source', albumSource);
|
||||
}
|
||||
const tracksResponse = await fetch(`/api/album/${albumId}/tracks?${_aat3}`);
|
||||
|
||||
if (!tracksResponse.ok) {
|
||||
|
|
@ -7167,4 +7171,3 @@ function updateDbProgressUI(state) {
|
|||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue