fix: spotify importer artwork — split multi-artist before iTunes, render Spotify art immediately

- track-artwork endpoint: split artist on ,/•/ before iTunes search (same as download flow)
- track-artwork endpoint: fall back to existingArt when iTunes returns nothing
- frontend: render any artwork already in Spotify data immediately, don't wait for iTunes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-04-28 00:41:56 +02:00
1 parent e029a8f900
commit 8bb2b0d181
2 files changed
+24 -9

No files matched your search

+3 -2
View File
@@ -493,8 +493,9 @@ app.post('/api/spotify/track-artwork', async (req, res) => {
for (let i = 0; i < tracks.length; i += CONC) { for (let i = 0; i < tracks.length; i += CONC) {
const batch = tracks.slice(i, i + CONC); const batch = tracks.slice(i, i + CONC);
const batchRes = await Promise.all(batch.map(async t => { const batchRes = await Promise.all(batch.map(async t => {
const meta = await lookupItunesTrackMeta(t.artistName || '', t.trackName || ''); const searchArtist = (t.artistName || '').split(/\s*[,/•]\s*/)[0].trim();
return { idx: t.idx, artworkUrl: meta.artworkUrl || '' }; const meta = await lookupItunesTrackMeta(searchArtist, t.trackName || '');
return { idx: t.idx, artworkUrl: meta.artworkUrl || t.existingArt || '' };
})); }));
results.push(...batchRes); results.push(...batchRes);
} }
+21 -7
View File
@@ -160,7 +160,25 @@ function _renderSpotifyPreview(data) {
async function _loadSpotifyTrackArtwork(tracks, listEl) { async function _loadSpotifyTrackArtwork(tracks, listEl) {
try { try {
const payload = tracks.map((t, i) => ({ idx: i, trackName: t.trackName, artistName: t.artistName })); const artEls = listEl.querySelectorAll('.gtrack-art');
// Render any artwork already present in the Spotify data immediately
tracks.forEach((t, i) => {
const url = t.artworkUrl100 || t.artworkUrl60 || '';
if (!url) return;
const el = artEls[i];
if (!el) return;
const img = document.createElement('img');
img.src = url; img.loading = 'lazy';
el.innerHTML = ''; el.appendChild(img);
});
const payload = tracks.map((t, i) => ({
idx: i,
trackName: t.trackName,
artistName: t.artistName,
existingArt: t.artworkUrl100 || t.artworkUrl60 || '',
}));
const res = await fetch(`${S.cfg.backendUrl}/api/spotify/track-artwork`, { const res = await fetch(`${S.cfg.backendUrl}/api/spotify/track-artwork`, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
@@ -168,17 +186,13 @@ async function _loadSpotifyTrackArtwork(tracks, listEl) {
}); });
if (!res.ok) return; if (!res.ok) return;
const { results } = await res.json(); const { results } = await res.json();
const artEls = listEl.querySelectorAll('.gtrack-art');
for (const r of results) { for (const r of results) {
if (!r.artworkUrl || r.idx == null) continue; if (!r.artworkUrl || r.idx == null) continue;
const el = artEls[r.idx]; const el = artEls[r.idx];
if (!el) continue; if (!el) continue;
const img = document.createElement('img'); const img = document.createElement('img');
img.src = r.artworkUrl; img.src = r.artworkUrl; img.loading = 'lazy';
img.loading = 'lazy'; el.innerHTML = ''; el.appendChild(img);
el.innerHTML = '';
el.appendChild(img);
// Update resolved data so downloads use the correct artwork
if (window._spotifyResolved?.tracks?.[r.idx]) { if (window._spotifyResolved?.tracks?.[r.idx]) {
window._spotifyResolved.tracks[r.idx].artworkUrl100 = r.artworkUrl; window._spotifyResolved.tracks[r.idx].artworkUrl100 = r.artworkUrl;
} }