feat: Add keyboard shortcuts and queue management features

- Implement global keyboard shortcuts for playback controls, volume adjustments, and navigation.
- Introduce drag-and-drop functionality for queue reordering with visual feedback.
- Add context menus for tracks, albums, and artists with quick action options.
- Develop Spotlight Search feature with Last.fm integration for enhanced music discovery.
- Create GlobalSearchProvider for managing search state and keyboard shortcuts.
- Ensure accessibility and keyboard navigation support across all new features.
This commit is contained in:
2025-08-12 13:09:33 +00:00
committed by GitHub
parent d467796b31
commit 9e7cc703bd
15 changed files with 1733 additions and 130 deletions

View File

@@ -33,12 +33,14 @@ interface AudioPlayerContextProps {
playTrack: (track: Track, autoPlay?: boolean) => void;
queue: Track[];
addToQueue: (track: Track) => void;
insertAtBeginningOfQueue: (track: Track) => void;
playNextTrack: () => void;
clearQueue: () => void;
addAlbumToQueue: (albumId: string) => Promise<void>;
playAlbum: (albumId: string) => Promise<void>;
playAlbumFromTrack: (albumId: string, startingSongId: string) => Promise<void>;
removeTrackFromQueue: (index: number) => void;
reorderQueue: (oldIndex: number, newIndex: number) => void;
skipToTrackInQueue: (index: number) => void;
addArtistToQueue: (artistId: string) => Promise<void>;
playPreviousTrack: () => void;
@@ -291,6 +293,10 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
});
}, [shuffle]);
const insertAtBeginningOfQueue = useCallback((track: Track) => {
setQueue((prevQueue) => [track, ...prevQueue]);
}, []);
const clearQueue = useCallback(() => {
setQueue([]);
}, []);
@@ -299,6 +305,15 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
setQueue((prevQueue) => prevQueue.filter((_, i) => i !== index));
}, []);
const reorderQueue = useCallback((oldIndex: number, newIndex: number) => {
setQueue((prevQueue) => {
const newQueue = [...prevQueue];
const [movedItem] = newQueue.splice(oldIndex, 1);
newQueue.splice(newIndex, 0, movedItem);
return newQueue;
});
}, []);
const playNextTrack = useCallback(() => {
// Clear saved timestamp when changing tracks
localStorage.removeItem('navidrome-current-track-time');
@@ -736,10 +751,12 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
playTrack,
queue,
addToQueue,
insertAtBeginningOfQueue,
playNextTrack,
clearQueue,
addAlbumToQueue,
removeTrackFromQueue,
reorderQueue,
addArtistToQueue,
playPreviousTrack,
isLoading,
@@ -835,10 +852,12 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
isLoading,
playTrack,
addToQueue,
insertAtBeginningOfQueue,
playNextTrack,
clearQueue,
addAlbumToQueue,
removeTrackFromQueue,
reorderQueue,
addArtistToQueue,
playPreviousTrack,
playAlbum,