veza/apps/web/src/features/player/hooks/useKeyboardShortcuts.ts
2025-12-12 21:34:34 -05:00

135 lines
3.2 KiB
TypeScript

/**
* Hook pour gérer les raccourcis clavier du player
* - Espace : play/pause
* - Flèches gauche/droite : seek backward/forward
* - Flèches haut/bas : volume up/down
*/
import { useEffect, useCallback } from 'react';
import type { PlayerHook } from '../types';
export interface UseKeyboardShortcutsOptions {
enabled?: boolean;
seekStep?: number; // En secondes
volumeStep?: number; // En pourcentage
preventDefault?: boolean;
}
const DEFAULT_SEEK_STEP = 5; // 5 secondes
const DEFAULT_VOLUME_STEP = 5; // 5%
export function useKeyboardShortcuts(
player: PlayerHook,
options: UseKeyboardShortcutsOptions = {},
) {
const {
enabled = true,
seekStep = DEFAULT_SEEK_STEP,
volumeStep = DEFAULT_VOLUME_STEP,
preventDefault = true,
} = options;
const handleKeyDown = useCallback(
(e: KeyboardEvent) => {
if (!enabled) return;
// Ignorer si l'utilisateur est en train de taper dans un input/textarea
const target = e.target as HTMLElement;
if (
target &&
(target.tagName === 'INPUT' ||
target.tagName === 'TEXTAREA' ||
target.isContentEditable === true)
) {
return;
}
switch (e.code) {
case 'Space': {
// Espace : play/pause
if (preventDefault) {
e.preventDefault();
}
if (player.isPlaying) {
player.pause();
} else {
player.resume();
}
break;
}
case 'ArrowLeft': {
// Flèche gauche : reculer
if (preventDefault) {
e.preventDefault();
}
const newTime = Math.max(0, player.currentTime - seekStep);
player.seek(newTime);
break;
}
case 'ArrowRight': {
// Flèche droite : avancer
if (preventDefault) {
e.preventDefault();
}
const newTime = Math.min(
player.duration || 0,
player.currentTime + seekStep,
);
player.seek(newTime);
break;
}
case 'ArrowUp': {
// Flèche haut : augmenter le volume
if (preventDefault) {
e.preventDefault();
}
const newVolume = Math.min(100, player.volume + volumeStep);
player.setVolume(newVolume);
break;
}
case 'ArrowDown': {
// Flèche bas : diminuer le volume
if (preventDefault) {
e.preventDefault();
}
const newVolume = Math.max(0, player.volume - volumeStep);
player.setVolume(newVolume);
break;
}
default:
break;
}
},
[
enabled,
preventDefault,
seekStep,
volumeStep,
player.isPlaying,
player.currentTime,
player.duration,
player.volume,
player.pause,
player.resume,
player.seek,
player.setVolume,
],
);
useEffect(() => {
if (!enabled) return;
window.addEventListener('keydown', handleKeyDown);
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, [enabled, handleKeyDown]);
}
export default useKeyboardShortcuts;