fix: address Copilot review feedback on pagination PR
- Add MAX_LIMIT=10000 constant to prevent DoS attacks while supporting large libraries through pagination - Apply MAX_LIMIT to /library/artists, /library/albums, /library/tracks - Add trackCount field to artists endpoint (fixes "Most Tracks" sort) - Add /library/tracks/shuffle endpoint for server-side shuffle - Update frontend to use server-side shuffle instead of fetching 10k tracks The shuffle endpoint uses Fisher-Yates algorithm and samples random tracks for large libraries to avoid loading the entire database into memory. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -112,21 +112,17 @@ export default function LibraryPage() {
|
||||
playTracks(formattedTracks, startIndex);
|
||||
};
|
||||
|
||||
// Shuffle entire library - fetches all tracks for true shuffle
|
||||
// Shuffle entire library - uses server-side shuffle for large libraries
|
||||
const handleShuffleLibrary = async () => {
|
||||
try {
|
||||
// Fetch a large batch of tracks for shuffling
|
||||
const { tracks: allTracks } = await api.getTracks({
|
||||
limit: 10000,
|
||||
});
|
||||
// Use server-side shuffle endpoint for better performance with large libraries
|
||||
const { tracks: shuffledTracks } = await api.getShuffledTracks(500);
|
||||
|
||||
if (allTracks.length === 0) {
|
||||
if (shuffledTracks.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Shuffle the tracks
|
||||
const shuffled = [...allTracks].sort(() => Math.random() - 0.5);
|
||||
const formattedTracks = formatTracksForAudio(shuffled);
|
||||
const formattedTracks = formatTracksForAudio(shuffledTracks);
|
||||
playTracks(formattedTracks, 0);
|
||||
} catch (error) {
|
||||
console.error("Failed to shuffle library:", error);
|
||||
|
||||
@@ -402,6 +402,14 @@ class ApiClient {
|
||||
}>(`/library/tracks?${new URLSearchParams(params as any).toString()}`);
|
||||
}
|
||||
|
||||
async getShuffledTracks(limit?: number) {
|
||||
const params = limit ? `?limit=${limit}` : "";
|
||||
return this.request<{
|
||||
tracks: any[];
|
||||
total: number;
|
||||
}>(`/library/tracks/shuffle${params}`);
|
||||
}
|
||||
|
||||
async deleteTrack(trackId: string) {
|
||||
return this.request<{ message: string }>(`/library/tracks/${trackId}`, {
|
||||
method: "DELETE",
|
||||
|
||||
Reference in New Issue
Block a user