"use client"; import { Keyboard } from "lucide-react"; import { useEffect, useState } from "react"; import { toast } from "sonner"; import { type KeyboardShortcut, useKeyboardShortcutsHelp, } from "@/hooks/use-keyboard-shortcuts-help"; import { useKeybindingsStore } from "@/stores/keybindings-store"; import { Button } from "./ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "./ui/dialog"; const ShortcutItem = ({ shortcut, isRecording, onStartRecording, }: { shortcut: KeyboardShortcut; isRecording: boolean; onStartRecording: (shortcut: KeyboardShortcut) => void; }) => { // Filter out lowercase duplicates for display - if both "j" and "J" exist, only show "J" const displayKeys = shortcut.keys.filter((key: string) => { if ( key.includes("Cmd") && shortcut.keys.includes(key.replace("Cmd", "Ctrl")) ) return false; return true; }); return (
{shortcut.icon && (
{shortcut.icon}
)} {shortcut.description}
{displayKeys.map((key: string, index: number) => (
{key.split("+").map((keyPart: string, partIndex: number) => { const keyId = `${shortcut.id}-${index}-${partIndex}`; return ( onStartRecording(shortcut)} > {keyPart} ); })}
{index < displayKeys.length - 1 && ( or )}
))}
); }; const EditableShortcutKey = ({ children, isRecording, onStartRecording, }: { children: React.ReactNode; isRecording: boolean; onStartRecording: () => void; }) => { const handleClick = (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); onStartRecording(); }; return ( ); }; export const KeyboardShortcutsHelp = () => { const [open, setOpen] = useState(false); const [recordingShortcut, setRecordingShortcut] = useState(null); const { updateKeybinding, removeKeybinding, getKeybindingString, validateKeybinding, getKeybindingsForAction, setIsRecording, resetToDefaults, isRecording, } = useKeybindingsStore(); // Get shortcuts from centralized hook const { shortcuts } = useKeyboardShortcutsHelp(); const categories = Array.from(new Set(shortcuts.map((s) => s.category))); useEffect(() => { if (!isRecording || !recordingShortcut) return; const handleKeyDown = (e: KeyboardEvent) => { e.preventDefault(); e.stopPropagation(); const keyString = getKeybindingString(e); if (keyString) { // Auto-save the new keybinding const conflict = validateKeybinding( keyString, recordingShortcut.action ); if (conflict) { toast.error( `Key "${keyString}" is already bound to "${conflict.existingAction}"` ); setRecordingShortcut(null); return; } // Remove old keybindings for this action const oldKeys = getKeybindingsForAction(recordingShortcut.action); oldKeys.forEach((key) => removeKeybinding(key)); // Add new keybinding updateKeybinding(keyString, recordingShortcut.action); setIsRecording(false); setRecordingShortcut(null); } }; const handleClickOutside = () => { setRecordingShortcut(null); setIsRecording(false); }; document.addEventListener("keydown", handleKeyDown); document.addEventListener("click", handleClickOutside); return () => { document.removeEventListener("keydown", handleKeyDown); document.removeEventListener("click", handleClickOutside); }; }, [ recordingShortcut, getKeybindingString, updateKeybinding, removeKeybinding, validateKeybinding, getKeybindingsForAction, setIsRecording, isRecording, ]); const handleStartRecording = (shortcut: KeyboardShortcut) => { setRecordingShortcut(shortcut); setIsRecording(true); }; return ( Keyboard Shortcuts Speed up your video editing workflow with these keyboard shortcuts. Click any shortcut key to edit it.
{categories.map((category) => (

{category}

{shortcuts .filter((shortcut) => shortcut.category === category) .map((shortcut) => ( ))}
))}
); };