Files
mice/hooks/use-keyboard-shortcuts.ts
angel 9e7cc703bd 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.
2025-08-12 13:09:33 +00:00

126 lines
2.9 KiB
TypeScript

'use client';
import { useEffect, useCallback } from 'react';
import { useRouter } from 'next/navigation';
interface KeyboardShortcutsOptions {
onPlayPause?: () => void;
onNextTrack?: () => void;
onPreviousTrack?: () => void;
onVolumeUp?: () => void;
onVolumeDown?: () => void;
onToggleMute?: () => void;
onSpotlightSearch?: () => void;
disabled?: boolean;
}
export function useKeyboardShortcuts({
onPlayPause,
onNextTrack,
onPreviousTrack,
onVolumeUp,
onVolumeDown,
onToggleMute,
onSpotlightSearch,
disabled = false
}: KeyboardShortcutsOptions = {}) {
const router = useRouter();
const handleKeyDown = useCallback((event: KeyboardEvent) => {
// Don't trigger shortcuts if user is typing in an input field
const target = event.target as HTMLElement;
const isInputField = target.tagName === 'INPUT' ||
target.tagName === 'TEXTAREA' ||
target.contentEditable === 'true' ||
target.closest('[data-cmdk-input]'); // Command palette input
if (disabled || isInputField) return;
// Prevent default behavior for our shortcuts
const preventDefault = () => {
event.preventDefault();
event.stopPropagation();
};
switch (event.key) {
case ' ': // Space - Play/Pause
if (onPlayPause) {
preventDefault();
onPlayPause();
}
break;
case 'ArrowRight': // Right Arrow - Next Track
if (onNextTrack) {
preventDefault();
onNextTrack();
}
break;
case 'ArrowLeft': // Left Arrow - Previous Track
if (onPreviousTrack) {
preventDefault();
onPreviousTrack();
}
break;
case 'ArrowUp': // Up Arrow - Volume Up
if (onVolumeUp) {
preventDefault();
onVolumeUp();
}
break;
case 'ArrowDown': // Down Arrow - Volume Down
if (onVolumeDown) {
preventDefault();
onVolumeDown();
}
break;
case 'm': // M - Toggle Mute
case 'M':
if (onToggleMute) {
preventDefault();
onToggleMute();
}
break;
case 'k': // Cmd+K or Ctrl+K - Spotlight Search
case 'K':
if ((event.metaKey || event.ctrlKey) && onSpotlightSearch) {
preventDefault();
onSpotlightSearch();
}
break;
default:
break;
}
}, [
disabled,
onPlayPause,
onNextTrack,
onPreviousTrack,
onVolumeUp,
onVolumeDown,
onToggleMute,
onSpotlightSearch,
router
]);
useEffect(() => {
if (typeof window === 'undefined') return;
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
};
}, [handleKeyDown]);
return {
// Return any utility functions if needed
isShortcutActive: !disabled
};
}