feat(spotify): lazy-load per-track iTunes artwork for playlists/albums
Adds POST /api/spotify/track-artwork endpoint that takes an array of
{idx, trackName, artistName} and returns iTunes artwork URLs in batches
of 8 concurrent requests.
Frontend calls this after rendering the track list, then patches each
.gtrack-art element with the correct album cover as results arrive.
Also updates _spotifyResolved.tracks so downloads use the right artwork.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
a305ec98e2
commit
5446d83ab3
2 files changed
+49
No files matched your search
@@ -484,6 +484,22 @@ function _spTrackItem(t, defaultAlbum, defaultArt, defaultAlbumArtist) {
|
|||||||
|
|
||||||
// ─── ROUTES ──────────────────────────────────────────────────────────────────
|
// ─── ROUTES ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
app.post('/api/spotify/track-artwork', async (req, res) => {
|
||||||
|
const tracks = req.body.tracks || [];
|
||||||
|
if (!tracks.length) return res.json({ results: [] });
|
||||||
|
const CONC = 8;
|
||||||
|
const results = [];
|
||||||
|
for (let i = 0; i < tracks.length; i += CONC) {
|
||||||
|
const batch = tracks.slice(i, i + CONC);
|
||||||
|
const batchRes = await Promise.all(batch.map(async t => {
|
||||||
|
const meta = await lookupItunesTrackMeta(t.artistName || '', t.trackName || '');
|
||||||
|
return { idx: t.idx, artworkUrl: meta.artworkUrl || '' };
|
||||||
|
}));
|
||||||
|
results.push(...batchRes);
|
||||||
|
}
|
||||||
|
res.json({ results });
|
||||||
|
});
|
||||||
|
|
||||||
app.get('/api/health', (req, res) => {
|
app.get('/api/health', (req, res) => {
|
||||||
res.json({ status: 'ok', ytdlpVersion, musicPath: CONFIG.musicPath, audioFormat: CONFIG.audioFmt, activeJobs: activeDownloads, queueLength: downloadQueue.length });
|
res.json({ status: 'ok', ytdlpVersion, musicPath: CONFIG.musicPath, audioFormat: CONFIG.audioFmt, activeJobs: activeDownloads, queueLength: downloadQueue.length });
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1043,6 +1043,39 @@ function _renderSpotifyPreview(data) {
|
|||||||
list.innerHTML = '';
|
list.innerHTML = '';
|
||||||
(data.tracks || []).forEach((t, i) => list.appendChild(makeGlobalTrackItem(t, i, data.tracks)));
|
(data.tracks || []).forEach((t, i) => list.appendChild(makeGlobalTrackItem(t, i, data.tracks)));
|
||||||
section.style.display = '';
|
section.style.display = '';
|
||||||
|
|
||||||
|
// Lazy-load correct per-track artwork via iTunes in the background
|
||||||
|
if ((data.type === 'playlist' || data.type === 'album') && count > 0 && S.cfg.backendUrl) {
|
||||||
|
_loadSpotifyTrackArtwork(data.tracks, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function _loadSpotifyTrackArtwork(tracks, listEl) {
|
||||||
|
try {
|
||||||
|
const payload = tracks.map((t, i) => ({ idx: i, trackName: t.trackName, artistName: t.artistName }));
|
||||||
|
const res = await fetch(`${S.cfg.backendUrl}/api/spotify/track-artwork`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ tracks: payload }),
|
||||||
|
});
|
||||||
|
if (!res.ok) return;
|
||||||
|
const { results } = await res.json();
|
||||||
|
const artEls = listEl.querySelectorAll('.gtrack-art');
|
||||||
|
for (const r of results) {
|
||||||
|
if (!r.artworkUrl || r.idx == null) continue;
|
||||||
|
const el = artEls[r.idx];
|
||||||
|
if (!el) continue;
|
||||||
|
const img = document.createElement('img');
|
||||||
|
img.src = r.artworkUrl;
|
||||||
|
img.loading = 'lazy';
|
||||||
|
el.innerHTML = '';
|
||||||
|
el.appendChild(img);
|
||||||
|
// Update resolved data so downloads use the correct artwork
|
||||||
|
if (window._spotifyResolved?.tracks?.[r.idx]) {
|
||||||
|
window._spotifyResolved.tracks[r.idx].artworkUrl100 = r.artworkUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch { /* artwork loading is non-critical */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── HELPERS ───
|
// ─── HELPERS ───
|
||||||
|
|||||||
Reference in new issue
Block a user