summaryrefslogtreecommitdiff
path: root/apps/web/src/hooks/use-keyboard-shortcuts-help.ts
blob: 29e3c09b7415a6024e16cd44720eb662040c424e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"use client";

import { useMemo } from "react";
import { useKeybindingsStore } from "@/stores/keybindings-store";
import { Action } from "@/constants/actions";
import { getPlatformAlternateKey, getPlatformSpecialKey } from "@/lib/utils";

export interface KeyboardShortcut {
  id: string;
  keys: string[];
  description: string;
  category: string;
  action: Action;
  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",
  },
};

// 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 const useKeyboardShortcutsHelp = () => {
  const { keybindings } = useKeybindingsStore();

  const shortcuts = useMemo(() => {
    const result: KeyboardShortcut[] = [];

    // Group keybindings by action
    const actionToKeys: Record<Action, string[]> = {} as any;

    Object.entries(keybindings).forEach(([key, action]) => {
      if (action) {
        if (!actionToKeys[action]) {
          actionToKeys[action] = [];
        }
        actionToKeys[action].push(formatKey(key));
      }
    });

    // 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,
        });
      }
    });

    // 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,
  };
};