This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
breakpilot-pwa/studio-v2/hooks/companion/useKeyboardShortcuts.ts
BreakPilot Dev 754a812d4b feat(companion): Migrate Companion from admin-v2 to studio-v2 as pure lesson tool
Remove Companion module entirely from admin-v2. Rebuild in studio-v2 as a
focused lesson timer (no dashboard mode). Direct flow: start → active → ended.
Fix timer bug where lastTickRef reset prevented countdown. Add companion link
to Sidebar and i18n translations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 23:50:20 +01:00

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
}