summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/behaviors/shortcuts/keybindings.js
blob: 0513e807ed6a6b5e58e01de65e3d5fd19b9ceb7a (plain)
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
import { flatten } from 'lodash';
import AccessorUtilities from '~/lib/utils/accessor';
import { s__ } from '~/locale';
import { shouldDisableShortcuts } from './shortcuts_toggle';

export const LOCAL_STORAGE_KEY = 'gl-keyboard-shortcuts-customizations';

let parsedCustomizations = {};
const localStorageIsSafe = AccessorUtilities.isLocalStorageAccessSafe();

if (localStorageIsSafe) {
  try {
    parsedCustomizations = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY) || '{}');
  } catch (e) {
    /* do nothing */
  }
}

/**
 * A map of command => keys of all keyboard shortcuts
 * that have been customized by the user.
 *
 * @example
 * { "globalShortcuts.togglePerformanceBar": ["p e r f"] }
 *
 * @type { Object.<string, string[]> }
 */
export const customizations = parsedCustomizations;

// All available commands
export const TOGGLE_PERFORMANCE_BAR = 'globalShortcuts.togglePerformanceBar';
export const TOGGLE_CANARY = 'globalShortcuts.toggleCanary';

/** All keybindings, grouped and ordered with descriptions */
export const keybindingGroups = [
  {
    groupId: 'globalShortcuts',
    name: s__('KeyboardShortcuts|Global Shortcuts'),
    keybindings: [
      {
        description: s__('KeyboardShortcuts|Toggle the Performance Bar'),
        command: TOGGLE_PERFORMANCE_BAR,
        // eslint-disable-next-line @gitlab/require-i18n-strings
        defaultKeys: ['p b'],
      },
      {
        description: s__('KeyboardShortcuts|Toggle GitLab Next'),
        command: TOGGLE_CANARY,
        // eslint-disable-next-line @gitlab/require-i18n-strings
        defaultKeys: ['g x'],
      },
    ],
  },
]

  // For each keybinding object, add a `customKeys` property populated with the
  // user's custom keybindings (if the command has been customized).
  // `customKeys` will be `undefined` if the command hasn't been customized.
  .map((group) => {
    return {
      ...group,
      keybindings: group.keybindings.map((binding) => ({
        ...binding,
        customKeys: customizations[binding.command],
      })),
    };
  });

/**
 * A simple map of command => keys. All user customizations are included in this map.
 * This mapping is used to simplify `keysFor` below.
 *
 * @example
 * { "globalShortcuts.togglePerformanceBar": ["p e r f"] }
 */
const commandToKeys = flatten(keybindingGroups.map((group) => group.keybindings)).reduce(
  (acc, binding) => {
    acc[binding.command] = binding.customKeys || binding.defaultKeys;
    return acc;
  },
  {},
);

/**
 * Gets keyboard shortcuts associated with a command
 *
 * @param {string} command The command string. All command
 * strings are available as imports from this file.
 *
 * @returns {string[]} An array of keyboard shortcut strings bound to the command
 *
 * @example
 * import { keysFor, TOGGLE_PERFORMANCE_BAR } from '~/behaviors/shortcuts/keybindings'
 *
 * Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), handler);
 */
export const keysFor = (command) => {
  if (shouldDisableShortcuts()) {
    return [];
  }

  return commandToKeys[command];
};