diff options
Diffstat (limited to 'app/assets/javascripts/behaviors')
-rw-r--r-- | app/assets/javascripts/behaviors/shortcuts/keybindings.js | 96 | ||||
-rw-r--r-- | app/assets/javascripts/behaviors/shortcuts/shortcuts.js | 3 |
2 files changed, 98 insertions, 1 deletions
diff --git a/app/assets/javascripts/behaviors/shortcuts/keybindings.js b/app/assets/javascripts/behaviors/shortcuts/keybindings.js new file mode 100644 index 00000000000..bbcc40ab9fe --- /dev/null +++ b/app/assets/javascripts/behaviors/shortcuts/keybindings.js @@ -0,0 +1,96 @@ +import { flatten } from 'lodash'; +import { s__ } from '~/locale'; +import AccessorUtilities from '~/lib/utils/accessor'; +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'; + +/** 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'], + }, + ], + }, +] + + // 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]; +}; diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js index 3cb2d6719c8..a53150f8d61 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js @@ -9,6 +9,7 @@ import axios from '../../lib/utils/axios_utils'; import { refreshCurrentPage, visitUrl } from '../../lib/utils/url_utility'; import findAndFollowLink from '../../lib/utils/navigation_utility'; import { parseBoolean, getCspNonceValue } from '~/lib/utils/common_utils'; +import { keysFor, TOGGLE_PERFORMANCE_BAR } from './keybindings'; const defaultStopCallback = Mousetrap.prototype.stopCallback; Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) { @@ -70,7 +71,7 @@ export default class Shortcuts { Mousetrap.bind('s', Shortcuts.focusSearch); Mousetrap.bind('/', Shortcuts.focusSearch); Mousetrap.bind('f', this.focusFilter.bind(this)); - Mousetrap.bind('p b', Shortcuts.onTogglePerfBar); + Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), Shortcuts.onTogglePerfBar); const findFileURL = document.body.dataset.findFile; |