| b69ab31 | | | 1 | /** |
| b69ab31 | | | 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
| b69ab31 | | | 3 | * |
| b69ab31 | | | 4 | * This source code is licensed under the MIT license found in the |
| b69ab31 | | | 5 | * LICENSE file in the root directory of this source tree. |
| b69ab31 | | | 6 | */ |
| b69ab31 | | | 7 | |
| b69ab31 | | | 8 | import {Kbd} from 'isl-components/Kbd'; |
| b69ab31 | | | 9 | import {KeyCode, makeCommandDispatcher, Modifier} from 'isl-components/KeyboardShortcuts'; |
| b69ab31 | | | 10 | import {isMac} from 'isl-components/OperatingSystem'; |
| b69ab31 | | | 11 | import {useMemo} from 'react'; |
| b69ab31 | | | 12 | import {TypedEventEmitter} from 'shared/TypedEventEmitter'; |
| b69ab31 | | | 13 | import {t} from './i18n'; |
| b69ab31 | | | 14 | import {useModal} from './useModal'; |
| b69ab31 | | | 15 | |
| b69ab31 | | | 16 | import './ISLShortcuts.css'; |
| b69ab31 | | | 17 | |
| b69ab31 | | | 18 | const CMD = isMac ? Modifier.CMD : Modifier.CTRL; |
| b69ab31 | | | 19 | |
| b69ab31 | | | 20 | /* eslint-disable no-bitwise */ |
| b69ab31 | | | 21 | export const [ISLCommandContext, useCommand, dispatchCommand, allCommands] = makeCommandDispatcher({ |
| b69ab31 | | | 22 | OpenShortcutHelp: [Modifier.SHIFT, KeyCode.QuestionMark], |
| b69ab31 | | | 23 | ToggleSidebar: [CMD, KeyCode.Period], |
| b69ab31 | | | 24 | OpenUncommittedChangesComparisonView: [CMD, KeyCode.SingleQuote], |
| b69ab31 | | | 25 | OpenHeadChangesComparisonView: [[CMD, Modifier.SHIFT], KeyCode.SingleQuote], |
| b69ab31 | | | 26 | Escape: [Modifier.NONE, KeyCode.Escape], |
| b69ab31 | | | 27 | SelectUpwards: [Modifier.NONE, KeyCode.UpArrow], |
| b69ab31 | | | 28 | SelectDownwards: [Modifier.NONE, KeyCode.DownArrow], |
| b69ab31 | | | 29 | OpenDetails: [Modifier.NONE, KeyCode.RightArrow], |
| b69ab31 | | | 30 | ContinueSelectionUpwards: [Modifier.SHIFT, KeyCode.UpArrow], |
| b69ab31 | | | 31 | ContinueSelectionDownwards: [Modifier.SHIFT, KeyCode.DownArrow], |
| b69ab31 | | | 32 | SelectAllCommits: [Modifier.ALT, KeyCode.A], |
| b69ab31 | | | 33 | HideSelectedCommits: [Modifier.NONE, KeyCode.Backspace], |
| b69ab31 | | | 34 | ZoomIn: [Modifier.ALT, KeyCode.Plus], |
| b69ab31 | | | 35 | ZoomOut: [Modifier.ALT, KeyCode.Minus], |
| b69ab31 | | | 36 | ToggleTheme: [Modifier.ALT, KeyCode.T], |
| b69ab31 | | | 37 | ToggleShelvedChangesDropdown: [Modifier.ALT, KeyCode.S], |
| b69ab31 | | | 38 | ToggleDownloadCommitsDropdown: [Modifier.ALT, KeyCode.D], |
| b69ab31 | | | 39 | ToggleCwdDropdown: [Modifier.ALT, KeyCode.C], |
| b69ab31 | | | 40 | ToggleBulkActionsDropdown: [Modifier.ALT, KeyCode.B], |
| b69ab31 | | | 41 | ToggleFocusMode: [Modifier.ALT, KeyCode.F], |
| b69ab31 | | | 42 | ToggleBookmarksManagerDropdown: [Modifier.ALT, KeyCode.M], |
| b69ab31 | | | 43 | RebaseOntoCurrentStackBase: [Modifier.ALT, KeyCode.R], |
| b69ab31 | | | 44 | }); |
| b69ab31 | | | 45 | |
| b69ab31 | | | 46 | export type ISLCommandName = Parameters<typeof useCommand>[0]; |
| b69ab31 | | | 47 | |
| b69ab31 | | | 48 | /** Like useCommand, but returns an eventEmitter you can subscribe to */ |
| b69ab31 | | | 49 | export function useCommandEvent(commandName: ISLCommandName): TypedEventEmitter<'change', null> { |
| b69ab31 | | | 50 | const emitter = useMemo(() => new TypedEventEmitter<'change', null>(), []); |
| b69ab31 | | | 51 | useCommand(commandName, () => { |
| b69ab31 | | | 52 | emitter.emit('change', null); |
| b69ab31 | | | 53 | }); |
| b69ab31 | | | 54 | return emitter; |
| b69ab31 | | | 55 | } |
| b69ab31 | | | 56 | |
| b69ab31 | | | 57 | export const ISLShortcutLabels: Partial<Record<ISLCommandName, string>> = { |
| b69ab31 | | | 58 | Escape: t('Dismiss Tooltips and Popups'), |
| b69ab31 | | | 59 | OpenShortcutHelp: t('Open Shortcut Help'), |
| b69ab31 | | | 60 | ToggleSidebar: t('Toggle Commit Info Sidebar'), |
| b69ab31 | | | 61 | OpenUncommittedChangesComparisonView: t('Open Uncommitted Changes Comparison View'), |
| b69ab31 | | | 62 | OpenHeadChangesComparisonView: t('Open Head Changes Comparison View'), |
| b69ab31 | | | 63 | SelectAllCommits: t('Select All Commits'), |
| b69ab31 | | | 64 | ToggleTheme: t('Toggle Light/Dark Theme'), |
| b69ab31 | | | 65 | ZoomIn: t('Zoom In'), |
| b69ab31 | | | 66 | ZoomOut: t('Zoom Out'), |
| b69ab31 | | | 67 | ToggleShelvedChangesDropdown: t('Toggle Shelved Changes Dropdown'), |
| b69ab31 | | | 68 | ToggleDownloadCommitsDropdown: t('Toggle Download Commits Dropdown'), |
| b69ab31 | | | 69 | ToggleCwdDropdown: t('Toggle CWD Dropdown'), |
| b69ab31 | | | 70 | ToggleBulkActionsDropdown: t('Toggle Bulk Actions Dropdown'), |
| b69ab31 | | | 71 | ToggleFocusMode: t('Toggle Focus Mode'), |
| b69ab31 | | | 72 | ToggleBookmarksManagerDropdown: t('Toggle Bookmarks Manager Dropdown'), |
| b69ab31 | | | 73 | RebaseOntoCurrentStackBase: t('Rebase Selected Commits onto Current Stack Base'), |
| b69ab31 | | | 74 | }; |
| b69ab31 | | | 75 | |
| b69ab31 | | | 76 | export function useShowKeyboardShortcutsHelp(): () => unknown { |
| b69ab31 | | | 77 | const showModal = useModal(); |
| b69ab31 | | | 78 | const showShortcutsModal = () => { |
| b69ab31 | | | 79 | showModal({ |
| b69ab31 | | | 80 | type: 'custom', |
| b69ab31 | | | 81 | component: () => ( |
| b69ab31 | | | 82 | <div className="keyboard-shortcuts-menu"> |
| b69ab31 | | | 83 | <table> |
| b69ab31 | | | 84 | {(Object.entries(ISLShortcutLabels) as Array<[ISLCommandName, string]>).map( |
| b69ab31 | | | 85 | ([name, label]) => { |
| b69ab31 | | | 86 | const [modifiers, keyCode] = allCommands[name]; |
| b69ab31 | | | 87 | { |
| b69ab31 | | | 88 | return ( |
| b69ab31 | | | 89 | <tr key={name}> |
| b69ab31 | | | 90 | <td>{label}</td> |
| b69ab31 | | | 91 | <td> |
| b69ab31 | | | 92 | <Kbd |
| b69ab31 | | | 93 | modifiers={Array.isArray(modifiers) ? modifiers : [modifiers]} |
| b69ab31 | | | 94 | keycode={keyCode} |
| b69ab31 | | | 95 | /> |
| b69ab31 | | | 96 | </td> |
| b69ab31 | | | 97 | </tr> |
| b69ab31 | | | 98 | ); |
| b69ab31 | | | 99 | } |
| b69ab31 | | | 100 | }, |
| b69ab31 | | | 101 | )} |
| b69ab31 | | | 102 | </table> |
| b69ab31 | | | 103 | </div> |
| b69ab31 | | | 104 | ), |
| b69ab31 | | | 105 | icon: 'keyboard', |
| b69ab31 | | | 106 | title: t('Keyboard Shortcuts'), |
| b69ab31 | | | 107 | }); |
| b69ab31 | | | 108 | }; |
| b69ab31 | | | 109 | useCommand('OpenShortcutHelp', showShortcutsModal); |
| b69ab31 | | | 110 | return showShortcutsModal; |
| b69ab31 | | | 111 | } |