Merge pull request #356 from kettui/fix/album-track-source-propagation

Fix album track source propagation
This commit is contained in:
BoulderBadgeDad 2026-04-22 11:39:16 -07:00 committed by GitHub
commit 200b68e65e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 58 additions and 12 deletions

View file

@ -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) {
}
// ===============================

View file

@ -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) {
}
// =================================

View file

@ -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) {
}
// ==================================================================================

View file

@ -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) {
}
// ===================================================================