Services: Admin-Lehrer, Backend-Lehrer, Studio v2, Website, Klausur-Service, School-Service, Voice-Service, Geo-Service, BreakPilot Drive, Agent-Core Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
114 lines
2.8 KiB
TypeScript
114 lines
2.8 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useCallback, useRef } from 'react'
|
|
import { KEYBOARD_SHORTCUTS } from '@/lib/companion/constants'
|
|
|
|
interface UseKeyboardShortcutsOptions {
|
|
onPauseResume?: () => void
|
|
onExtend?: () => void
|
|
onNextPhase?: () => void
|
|
onCloseModal?: () => void
|
|
onShowHelp?: () => void
|
|
enabled?: boolean
|
|
}
|
|
|
|
export function useKeyboardShortcuts({
|
|
onPauseResume,
|
|
onExtend,
|
|
onNextPhase,
|
|
onCloseModal,
|
|
onShowHelp,
|
|
enabled = true,
|
|
}: UseKeyboardShortcutsOptions) {
|
|
// Track if we're in an input field
|
|
const isInputFocused = useRef(false)
|
|
|
|
const handleKeyDown = useCallback(
|
|
(event: KeyboardEvent) => {
|
|
if (!enabled) return
|
|
|
|
// Don't trigger shortcuts when typing in inputs
|
|
const target = event.target as HTMLElement
|
|
const isInput =
|
|
target.tagName === 'INPUT' ||
|
|
target.tagName === 'TEXTAREA' ||
|
|
target.tagName === 'SELECT' ||
|
|
target.isContentEditable
|
|
|
|
if (isInput) {
|
|
isInputFocused.current = true
|
|
// Only allow Escape in inputs
|
|
if (event.key !== 'Escape') return
|
|
} else {
|
|
isInputFocused.current = false
|
|
}
|
|
|
|
// Handle shortcuts
|
|
switch (event.key) {
|
|
case KEYBOARD_SHORTCUTS.PAUSE_RESUME:
|
|
if (!isInput) {
|
|
event.preventDefault()
|
|
onPauseResume?.()
|
|
}
|
|
break
|
|
|
|
case KEYBOARD_SHORTCUTS.EXTEND_5MIN:
|
|
case KEYBOARD_SHORTCUTS.EXTEND_5MIN.toUpperCase():
|
|
if (!isInput) {
|
|
event.preventDefault()
|
|
onExtend?.()
|
|
}
|
|
break
|
|
|
|
case KEYBOARD_SHORTCUTS.NEXT_PHASE:
|
|
case KEYBOARD_SHORTCUTS.NEXT_PHASE.toUpperCase():
|
|
if (!isInput) {
|
|
event.preventDefault()
|
|
onNextPhase?.()
|
|
}
|
|
break
|
|
|
|
case KEYBOARD_SHORTCUTS.CLOSE_MODAL:
|
|
event.preventDefault()
|
|
onCloseModal?.()
|
|
break
|
|
|
|
case KEYBOARD_SHORTCUTS.SHOW_HELP:
|
|
if (!isInput) {
|
|
event.preventDefault()
|
|
onShowHelp?.()
|
|
}
|
|
break
|
|
}
|
|
},
|
|
[enabled, onPauseResume, onExtend, onNextPhase, onCloseModal, onShowHelp]
|
|
)
|
|
|
|
useEffect(() => {
|
|
if (!enabled) return
|
|
|
|
document.addEventListener('keydown', handleKeyDown)
|
|
return () => document.removeEventListener('keydown', handleKeyDown)
|
|
}, [enabled, handleKeyDown])
|
|
|
|
return {
|
|
isInputFocused: isInputFocused.current,
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Hook to display keyboard shortcut hints
|
|
*/
|
|
export function useKeyboardShortcutHints(show: boolean) {
|
|
const shortcuts = [
|
|
{ key: 'Leertaste', action: 'Pause/Fortsetzen', code: 'space' },
|
|
{ key: 'E', action: '+5 Minuten', code: 'e' },
|
|
{ key: 'N', action: 'Naechste Phase', code: 'n' },
|
|
{ key: 'Esc', action: 'Modal schliessen', code: 'escape' },
|
|
]
|
|
|
|
if (!show) return null
|
|
|
|
return shortcuts
|
|
}
|