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 9427a2a237
commit 7710bf3cc9
15 changed files with 1733 additions and 130 deletions

View File

@@ -9,6 +9,8 @@ import { Progress } from '@/components/ui/progress';
import { lrcLibClient } from '@/lib/lrclib';
import Link from 'next/link';
import { useIsMobile } from '@/hooks/use-mobile';
import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts';
import { useGlobalSearch } from './GlobalSearchProvider';
import { AudioSettingsDialog } from './AudioSettingsDialog';
import {
FaPlay,
@@ -419,6 +421,54 @@ export const FullScreenPlayer: React.FC<FullScreenPlayerProps> = ({ isOpen, onCl
} catch {}
};
// Volume control functions for keyboard shortcuts
const handleVolumeUp = () => {
const mainAudio = document.querySelector('audio') as HTMLAudioElement;
if (!mainAudio) return;
const newVolume = Math.min(1, mainAudio.volume + 0.1);
mainAudio.volume = newVolume;
setVolume(newVolume);
try {
localStorage.setItem('navidrome-volume', newVolume.toString());
} catch {}
};
const handleVolumeDown = () => {
const mainAudio = document.querySelector('audio') as HTMLAudioElement;
if (!mainAudio) return;
const newVolume = Math.max(0, mainAudio.volume - 0.1);
mainAudio.volume = newVolume;
setVolume(newVolume);
try {
localStorage.setItem('navidrome-volume', newVolume.toString());
} catch {}
};
const handleToggleMute = () => {
const mainAudio = document.querySelector('audio') as HTMLAudioElement;
if (!mainAudio) return;
const newVolume = mainAudio.volume === 0 ? 1 : 0;
mainAudio.volume = newVolume;
setVolume(newVolume);
try {
localStorage.setItem('navidrome-volume', newVolume.toString());
} catch {}
};
const { openSpotlight } = useGlobalSearch();
// Set up keyboard shortcuts for fullscreen player
useKeyboardShortcuts({
onPlayPause: togglePlayPause,
onNextTrack: playNextTrack,
onPreviousTrack: playPreviousTrack,
onVolumeUp: handleVolumeUp,
onVolumeDown: handleVolumeDown,
onToggleMute: handleToggleMute,
onSpotlightSearch: openSpotlight,
disabled: !isOpen || !currentTrack // Only active when fullscreen is open
});
const handleLyricClick = (time: number) => {
const mainAudio = document.querySelector('audio') as HTMLAudioElement;
if (!mainAudio) return;