mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
codebase overhaul (#697)
This commit is contained in:
@@ -2,138 +2,81 @@
|
||||
|
||||
import { useMemo } from "react";
|
||||
import { useKeybindingsStore } from "@/stores/keybindings-store";
|
||||
import { Action } from "@/constants/actions";
|
||||
import { getPlatformAlternateKey, getPlatformSpecialKey } from "@/lib/utils";
|
||||
import { ACTIONS, type TAction } from "@/lib/actions";
|
||||
import {
|
||||
getPlatformAlternateKey,
|
||||
getPlatformSpecialKey,
|
||||
} from "@/utils/platform";
|
||||
|
||||
export interface KeyboardShortcut {
|
||||
id: string;
|
||||
keys: string[];
|
||||
description: string;
|
||||
category: string;
|
||||
action: Action;
|
||||
icon?: React.ReactNode;
|
||||
id: string;
|
||||
keys: string[];
|
||||
description: string;
|
||||
category: string;
|
||||
action: TAction;
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
|
||||
// Map actions to their descriptions and categories
|
||||
const actionDescriptions: Record<
|
||||
Action,
|
||||
{ description: string; category: string }
|
||||
> = {
|
||||
"toggle-play": { description: "Play/Pause", category: "Playback" },
|
||||
"stop-playback": { description: "Stop playback", category: "Playback" },
|
||||
"seek-forward": {
|
||||
description: "Seek forward 1 second",
|
||||
category: "Playback",
|
||||
},
|
||||
"seek-backward": {
|
||||
description: "Seek backward 1 second",
|
||||
category: "Playback",
|
||||
},
|
||||
"frame-step-forward": {
|
||||
description: "Frame step forward",
|
||||
category: "Navigation",
|
||||
},
|
||||
"frame-step-backward": {
|
||||
description: "Frame step backward",
|
||||
category: "Navigation",
|
||||
},
|
||||
"jump-forward": {
|
||||
description: "Jump forward 5 seconds",
|
||||
category: "Navigation",
|
||||
},
|
||||
"jump-backward": {
|
||||
description: "Jump backward 5 seconds",
|
||||
category: "Navigation",
|
||||
},
|
||||
"goto-start": { description: "Go to timeline start", category: "Navigation" },
|
||||
"goto-end": { description: "Go to timeline end", category: "Navigation" },
|
||||
"split-element": {
|
||||
description: "Split element at playhead",
|
||||
category: "Editing",
|
||||
},
|
||||
"delete-selected": {
|
||||
description: "Delete selected elements",
|
||||
category: "Editing",
|
||||
},
|
||||
"select-all": { description: "Select all elements", category: "Selection" },
|
||||
"duplicate-selected": {
|
||||
description: "Duplicate selected element",
|
||||
category: "Selection",
|
||||
},
|
||||
"toggle-snapping": { description: "Toggle snapping", category: "Editing" },
|
||||
undo: { description: "Undo", category: "History" },
|
||||
redo: { description: "Redo", category: "History" },
|
||||
"copy-selected": {
|
||||
description: "Copy selected elements",
|
||||
category: "Editing",
|
||||
},
|
||||
"paste-selected": {
|
||||
description: "Paste elements at playhead",
|
||||
category: "Editing",
|
||||
},
|
||||
};
|
||||
function formatKey({ key }: { key: string }): string {
|
||||
return key
|
||||
.replace("ctrl", getPlatformSpecialKey())
|
||||
.replace("alt", getPlatformAlternateKey())
|
||||
.replace("shift", "Shift")
|
||||
.replace("left", "←")
|
||||
.replace("right", "→")
|
||||
.replace("up", "↑")
|
||||
.replace("down", "↓")
|
||||
.replace("space", "Space")
|
||||
.replace("home", "Home")
|
||||
.replace("enter", "Enter")
|
||||
.replace("end", "End")
|
||||
.replace("delete", "Delete")
|
||||
.replace("backspace", "Backspace")
|
||||
.replace("-", "+");
|
||||
}
|
||||
|
||||
// Convert key binding format to display format
|
||||
const formatKey = (key: string): string => {
|
||||
return key
|
||||
.replace("ctrl", getPlatformSpecialKey())
|
||||
.replace("alt", getPlatformAlternateKey())
|
||||
.replace("shift", "Shift")
|
||||
.replace("left", "←")
|
||||
.replace("right", "→")
|
||||
.replace("up", "↑")
|
||||
.replace("down", "↓")
|
||||
.replace("space", "Space")
|
||||
.replace("home", "Home")
|
||||
.replace("enter", "Enter")
|
||||
.replace("end", "End")
|
||||
.replace("delete", "Delete")
|
||||
.replace("backspace", "Backspace")
|
||||
.replace("-", "+");
|
||||
};
|
||||
export function useKeyboardShortcutsHelp() {
|
||||
const { keybindings } = useKeybindingsStore();
|
||||
|
||||
export const useKeyboardShortcutsHelp = () => {
|
||||
const { keybindings } = useKeybindingsStore();
|
||||
const shortcuts = useMemo(() => {
|
||||
const result: KeyboardShortcut[] = [];
|
||||
const actionToKeys: Record<string, string[]> = {};
|
||||
|
||||
const shortcuts = useMemo(() => {
|
||||
const result: KeyboardShortcut[] = [];
|
||||
for (const [key, action] of Object.entries(keybindings)) {
|
||||
if (action) {
|
||||
if (!actionToKeys[action]) {
|
||||
actionToKeys[action] = [];
|
||||
}
|
||||
actionToKeys[action].push(formatKey({ key }));
|
||||
}
|
||||
}
|
||||
|
||||
// Group keybindings by action
|
||||
const actionToKeys: Record<Action, string[]> = {} as any;
|
||||
for (const [actionId, keys] of Object.entries(actionToKeys)) {
|
||||
if (!isAction(actionId)) continue;
|
||||
|
||||
Object.entries(keybindings).forEach(([key, action]) => {
|
||||
if (action) {
|
||||
if (!actionToKeys[action]) {
|
||||
actionToKeys[action] = [];
|
||||
}
|
||||
actionToKeys[action].push(formatKey(key));
|
||||
}
|
||||
});
|
||||
const actionDef = ACTIONS[actionId];
|
||||
result.push({
|
||||
id: actionId,
|
||||
keys,
|
||||
description: actionDef.description,
|
||||
category: actionDef.category,
|
||||
action: actionId,
|
||||
});
|
||||
}
|
||||
|
||||
// Convert to shortcuts format
|
||||
Object.entries(actionToKeys).forEach(([action, keys]) => {
|
||||
const actionInfo = actionDescriptions[action as Action];
|
||||
if (actionInfo) {
|
||||
result.push({
|
||||
id: action,
|
||||
keys,
|
||||
description: actionInfo.description,
|
||||
category: actionInfo.category,
|
||||
action: action as Action,
|
||||
});
|
||||
}
|
||||
});
|
||||
return result.sort((a, b) => {
|
||||
if (a.category !== b.category) {
|
||||
return a.category.localeCompare(b.category);
|
||||
}
|
||||
return a.description.localeCompare(b.description);
|
||||
});
|
||||
}, [keybindings]);
|
||||
|
||||
// Sort shortcuts by category first, then by description to ensure consistent ordering
|
||||
return result.sort((a, b) => {
|
||||
if (a.category !== b.category) {
|
||||
return a.category.localeCompare(b.category);
|
||||
}
|
||||
return a.description.localeCompare(b.description);
|
||||
});
|
||||
}, [keybindings]);
|
||||
return {
|
||||
shortcuts,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
shortcuts,
|
||||
};
|
||||
};
|
||||
function isAction(id: string): id is TAction {
|
||||
return id in ACTIONS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user