diff --git a/apps/web/src/components/editor-provider.tsx b/apps/web/src/components/editor-provider.tsx index d970f86d..25d040db 100644 --- a/apps/web/src/components/editor-provider.tsx +++ b/apps/web/src/components/editor-provider.tsx @@ -3,7 +3,11 @@ import { useEffect } from "react"; import { Loader2 } from "lucide-react"; import { useEditorStore } from "@/stores/editor-store"; -import { useKeyboardShortcuts } from "@/hooks/use-keyboard-shortcuts"; +import { + useKeybindingsListener, + useKeybindingDisabler, +} from "@/hooks/use-keybindings"; +import { useEditorActions } from "@/hooks/use-editor-actions"; interface EditorProviderProps { children: React.ReactNode; @@ -11,11 +15,22 @@ interface EditorProviderProps { export function EditorProvider({ children }: EditorProviderProps) { const { isInitializing, isPanelsReady, initializeApp } = useEditorStore(); + const { disableKeybindings, enableKeybindings } = useKeybindingDisabler(); - useKeyboardShortcuts({ - enabled: !isInitializing && isPanelsReady, - context: "editor", - }); + // Set up action handlers + useEditorActions(); + + // Set up keybinding listener + useKeybindingsListener(); + + // Disable keybindings when initializing + useEffect(() => { + if (isInitializing || !isPanelsReady) { + disableKeybindings(); + } else { + enableKeybindings(); + } + }, [isInitializing, isPanelsReady, disableKeybindings, enableKeybindings]); useEffect(() => { initializeApp(); diff --git a/apps/web/src/components/keybinding-editor.tsx b/apps/web/src/components/keybinding-editor.tsx new file mode 100644 index 00000000..bc98c5fd --- /dev/null +++ b/apps/web/src/components/keybinding-editor.tsx @@ -0,0 +1,425 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Badge } from "@/components/ui/badge"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, +} from "@/components/ui/alert-dialog"; +import { useKeybindingsStore } from "@/stores/keybindings-store"; +import { Action } from "@/constants/actions"; +import { KeyboardShortcut } from "@/hooks/use-keyboard-shortcuts-help"; +import { + Settings, + RotateCcw, + Download, + Upload, + X, + Check, + AlertTriangle, +} from "lucide-react"; +import { toast } from "sonner"; + +interface KeybindingEditorProps { + shortcuts: KeyboardShortcut[]; + onClose: () => void; +} + +interface KeyRecorderProps { + value: string; + onValueChange: (value: string) => void; + onCancel: () => void; +} + +const KeyRecorder = ({ value, onValueChange, onCancel }: KeyRecorderProps) => { + const [isRecording, setIsRecording] = useState(false); + const [recordedKey, setRecordedKey] = useState(""); + const { getKeybindingString } = useKeybindingsStore(); + + useEffect(() => { + if (!isRecording) return; + + const handleKeyDown = (e: KeyboardEvent) => { + e.preventDefault(); + + const keyString = getKeybindingString(e); + if (keyString) { + setRecordedKey(keyString); + } + }; + + document.addEventListener("keydown", handleKeyDown); + return () => document.removeEventListener("keydown", handleKeyDown); + }, [isRecording, getKeybindingString]); + + const handleStartRecording = () => { + setIsRecording(true); + setRecordedKey(""); + }; + + const handleConfirm = () => { + onValueChange(recordedKey); + setIsRecording(false); + setRecordedKey(""); + }; + + const handleCancel = () => { + setIsRecording(false); + setRecordedKey(""); + onCancel(); + }; + + const displayKey = recordedKey || value; + + return ( +
+ {shortcut.category} +
+