From 71a2c5be9373121c87e62a25e47de0d99d0e026a Mon Sep 17 00:00:00 2001 From: Samidy Date: Wed, 11 Mar 2026 08:23:27 +0300 Subject: [PATCH] make le diddy infinite radio better kinda --- js/api.js | 25 ++++++++++++----------- js/player.js | 56 +++++++++++++++++++++++++++------------------------- js/ui.js | 16 +++++++++++++-- 3 files changed, 57 insertions(+), 40 deletions(-) diff --git a/js/api.js b/js/api.js index 8972969..201bcff 100644 --- a/js/api.js +++ b/js/api.js @@ -1097,13 +1097,8 @@ export class LosslessAPI { const recommendedTracks = []; const seenTrackIds = new Set(tracks.map((t) => t.id)); - // Shuffle artists if refreshing to get different results - let shuffledArtists = artists; - if (options.refresh) { - shuffledArtists = [...artists].sort(() => Math.random() - 0.5); - } - - const artistsToProcess = shuffledArtists.slice(0, Math.min(5, shuffledArtists.length)); + const shuffledArtists = [...artists].sort(() => Math.random() - 0.5); + const artistsToProcess = shuffledArtists.slice(0, Math.min(15, shuffledArtists.length)); const artistPromises = artistsToProcess.map(async (artist) => { try { @@ -1111,11 +1106,19 @@ export class LosslessAPI { const artistData = await this.getArtist(artist.id, { lightweight: true, skipCache: options.refresh }); if (artistData && artistData.tracks && artistData.tracks.length > 0) { const availableTracks = artistData.tracks.filter((track) => !seenTrackIds.has(track.id)); - // Shuffle and pick different tracks when refreshing - const shuffled = options.refresh - ? availableTracks.sort(() => Math.random() - 0.5) + + const newTracks = options.knownTrackIds + ? availableTracks.filter(t => !options.knownTrackIds.has(t.id)) : availableTracks; - return shuffled.slice(0, 4); + const knownTracks = options.knownTrackIds + ? availableTracks.filter(t => options.knownTrackIds.has(t.id)) + : []; + + const shuffledNew = [...newTracks].sort(() => Math.random() - 0.5); + const shuffledKnown = [...knownTracks].sort(() => Math.random() - 0.5); + + const combined = [...shuffledNew, ...shuffledKnown]; + return combined.slice(0, 2); } else { console.warn(`No tracks found for artist ${artist.name}`); return []; diff --git a/js/player.js b/js/player.js index 3701eff..2cc977d 100644 --- a/js/player.js +++ b/js/player.js @@ -984,13 +984,15 @@ export class Player { const pickedSeeds = await this.pickRadioSeeds(); if (pickedSeeds.length > 0) { this.radioSeeds = pickedSeeds; - this.setQueue(pickedSeeds, 0, true); + const initialQueue = [...pickedSeeds].sort(() => 0.5 - Math.random()).slice(0, 5); + this.setQueue(initialQueue, 0, true); this.playAtIndex(0); } } else { this.radioSeeds = Array.isArray(seeds) ? seeds : [seeds]; this.wipeQueue(); - this.setQueue(this.radioSeeds, 0, true); + const initialQueue = Array.isArray(seeds) ? seeds.slice(0, 5) : [seeds]; + this.setQueue(initialQueue, 0, true); this.playAtIndex(0); } @@ -1021,41 +1023,41 @@ export class Player { this.radioSeeds = await this.pickRadioSeeds(); } - const seeds = - this.radioSeeds.length > 0 ? this.radioSeeds : this.currentTrack ? [this.currentTrack] : []; + const shuffledSeeds = [...this.radioSeeds].sort(() => 0.5 - Math.random()); + const seeds = shuffledSeeds.length > 0 + ? shuffledSeeds.slice(0, 5) + : this.currentTrack ? [this.currentTrack] : []; if (seeds.length === 0) { return; } - const recommendations = await this.api.getRecommendedTracksForPlaylist(seeds, 10); + const [favorites, userPlaylists, history] = await Promise.all([ + db.getFavorites('track'), + db.getAll('user_playlists'), + db.getHistory(), + ]); + + const knownTrackIds = new Set([ + ...favorites.map((t) => t.id), + ...userPlaylists.flatMap((p) => (p.tracks || []).map((t) => t.id)), + ...history.map((t) => t.id), + ]); + + const recommendations = await this.api.getRecommendedTracksForPlaylist(seeds, 20, { + knownTrackIds: knownTrackIds + }); + if (recommendations && recommendations.length > 0) { const currentQueueIds = new Set(this.getCurrentQueue().map((t) => t.id)); - const [favorites, userPlaylists, history] = await Promise.all([ - db.getFavorites('track'), - db.getAll('user_playlists'), - db.getHistory(), - ]); - - const knownTrackIds = new Set([ - ...favorites.map((t) => t.id), - ...userPlaylists.flatMap((p) => (p.tracks || []).map((t) => t.id)), - ...history.map((t) => t.id), - ]); - - const newTracks = recommendations.filter((t) => { - if (currentQueueIds.has(t.id)) return false; - - if (knownTrackIds.has(t.id)) { - return Math.random() < 0.05; - } - - return true; + let newTracks = recommendations.filter((t) => { + return !currentQueueIds.has(t.id); }); if (newTracks.length > 0) { - this.addToQueue(newTracks); + const tracksToAdd = newTracks.sort(() => 0.5 - Math.random()).slice(0, 5); + this.addToQueue(tracksToAdd); } } } catch (error) { @@ -1112,7 +1114,7 @@ export class Player { potentialSeeds.find((s) => s.id === id) ); - return uniqueSeeds.sort(() => 0.5 - Math.random()).slice(0, 5); + return uniqueSeeds.sort(() => 0.5 - Math.random()).slice(0, 50); } catch (error) { console.error('Failed to pick radio seeds:', error); return this.currentTrack ? [this.currentTrack] : []; diff --git a/js/ui.js b/js/ui.js index 99d0b55..6f90acb 100644 --- a/js/ui.js +++ b/js/ui.js @@ -2188,9 +2188,21 @@ export class UIRenderer { try { const seeds = providedSeeds || (await this.getSeeds()); - const trackSeeds = seeds.slice(0, 5); - const recommendedTracks = await this.api.getRecommendedTracksForPlaylist(trackSeeds, 20, { + + const [favorites, playlists, history] = await Promise.all([ + db.getFavorites('track'), + db.getPlaylists(true), + db.getHistory(), + ]); + const knownTrackIds = new Set([ + ...favorites.map(t => t.id), + ...playlists.flatMap(p => (p.tracks || []).map(t => t.id)), + ...history.map(t => t.id) + ]); + + const recommendedTracks = await this.api.getRecommendedTracksForPlaylist(seeds, 20, { skipCache: forceRefresh, + knownTrackIds: knownTrackIds }); const filteredTracks = await this.filterUserContent(recommendedTracks, 'track');