fix: radio mode uses getSimilarSongs2 for artist/genre-aware playback

- Dedup now checks only the last 50 queued songs instead of the entire
  queue, so the radio doesn't stall on small libraries once every similar
  song has been seen
- If every candidate is a recent duplicate (tiny library), allow up to 5
  repeats rather than returning empty and letting the queue run dry
- Add second _queueGen guard after the getRandomSongs fallback await

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-21 08:45:16 +02:00
1 parent 9fe8656a21
commit 377a6954e3
1 file changed
+15 -6
+15 -6
View File
@@ -641,22 +641,31 @@ export async function fillRadioQueue() {
try { try {
const seed = S.queue[S.qIdx]; const seed = S.queue[S.qIdx];
let newSongs = []; let newSongs = [];
// 1. Try similar songs seeded from the current track
if (seed?.id) { if (seed?.id) {
const r = await api('getSimilarSongs2', `&id=${seed.id}&count=20`); const r = await api('getSimilarSongs2', `&id=${seed.id}&count=20`);
newSongs = r.similarSongs2?.song || []; newSongs = r.similarSongs2?.song || [];
} }
// Fall back to random if similar songs unavailable (no Last.fm config, unknown track, etc.) if (gen !== _queueGen) return;
// 2. Fall back to random if similar songs unavailable or empty
if (!newSongs.length) { if (!newSongs.length) {
const r = await api('getRandomSongs', '&size=20'); const r = await api('getRandomSongs', '&size=20');
newSongs = r.randomSongs?.song || []; newSongs = r.randomSongs?.song || [];
} }
// Bail if playQueue() was called while we were awaiting — appending to a
// replaced queue would desync native (setQueue already wiped the old one).
if (gen !== _queueGen) return; if (gen !== _queueGen) return;
// Deduplicate against songs already queued
const existingIds = new Set(S.queue.map(s => s.id));
newSongs = newSongs.filter(s => !existingIds.has(s.id));
if (!newSongs.length) return; if (!newSongs.length) return;
// Deduplicate only against the last 50 queued songs so the radio never
// stalls on a small library. Songs cycle back after ~50 tracks rather than
// blocking forever once they've been seen once.
const recentIds = new Set(S.queue.slice(-50).map(s => s.id));
const deduped = newSongs.filter(s => !recentIds.has(s.id));
// If every candidate was a recent duplicate (very small library), allow
// repeats rather than letting the queue run dry and music stop.
newSongs = deduped.length > 0 ? deduped : newSongs.slice(0, 5);
const prevLen = S.queue.length; const prevLen = S.queue.length;
S.queue.push(...newSongs); S.queue.push(...newSongs);
renderQueue(); renderQueue();