"use client"; import { useState, useEffect } from "react"; import { Button } from "./ui/button"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from "./ui/dialog"; import { getPlatformSpecialKey } from "@/lib/utils"; import { Keyboard } from "lucide-react"; import { useKeyboardShortcutsHelp, KeyboardShortcut, } from "@/hooks/use-keyboard-shortcuts-help"; import { useKeybindingsStore } from "@/stores/keybindings-store"; import { toast } from "sonner"; const modifier: { [key: string]: string; } = { Shift: "Shift", Alt: "Alt", ArrowLeft: "←", ArrowRight: "→", ArrowUp: "↑", ArrowDown: "↓", Space: "Space", }; function getKeyWithModifier(key: string) { if (key === "Ctrl") return getPlatformSpecialKey(); return modifier[key] || key; } const ShortcutItem = ({ shortcut, recordingKey, onStartRecording, }: { shortcut: KeyboardShortcut; recordingKey: string | null; onStartRecording: (keyId: string, 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(keyId, shortcut)} > {getKeyWithModifier(keyPart)} ); })}
{index < displayKeys.length - 1 && ( or )}
))}
); }; const EditableShortcutKey = ({ children, keyId, originalKey, shortcut, isRecording, onStartRecording, }: { children: React.ReactNode; keyId: string; originalKey: string; shortcut: KeyboardShortcut; isRecording: boolean; onStartRecording: () => void; }) => { const handleClick = (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); onStartRecording(); }; return ( {children} ); }; export const KeyboardShortcutsHelp = () => { const [open, setOpen] = useState(false); const [recordingKey, setRecordingKey] = useState(null); const [recordingShortcut, setRecordingShortcut] = useState(null); const { updateKeybinding, removeKeybinding, getKeybindingString, validateKeybinding, getKeybindingsForAction, } = useKeybindingsStore(); // Get shortcuts from centralized hook const { shortcuts } = useKeyboardShortcutsHelp(); const categories = Array.from(new Set(shortcuts.map((s) => s.category))); useEffect(() => { if (!recordingKey || !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}"` ); setRecordingKey(null); 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); setRecordingKey(null); setRecordingShortcut(null); } }; const handleClickOutside = (e: MouseEvent) => { setRecordingKey(null); setRecordingShortcut(null); }; document.addEventListener("keydown", handleKeyDown); document.addEventListener("click", handleClickOutside); return () => { document.removeEventListener("keydown", handleKeyDown); document.removeEventListener("click", handleClickOutside); }; }, [ recordingKey, recordingShortcut, getKeybindingString, updateKeybinding, removeKeybinding, validateKeybinding, getKeybindingsForAction, ]); const handleStartRecording = (keyId: string, shortcut: KeyboardShortcut) => { setRecordingKey(keyId); setRecordingShortcut(shortcut); }; 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, index) => ( ))}
))}
); };