insomnia/app/common/hotkeys.js
Gregory Schier f76e382387 Revamp Keyboard Shortcuts (#487)
* More shortcuts and accessibility tweaks

* Use hotkey objects everywhere

* A few last-minute tweaks
2017-09-17 16:04:56 +02:00

266 lines
5.3 KiB
JavaScript

// @flow
import keycodes from './keycodes';
import {isMac} from './constants';
import {trackEvent} from '../analytics/index';
export type Hotkey = {
description: string,
meta: boolean,
alt: boolean,
shift: boolean,
keycode: number | Array<number>
};
export const SHOW_WORKSPACE_SETTINGS: Hotkey = {
description: 'Show Workspace Settings',
meta: true,
alt: false,
shift: true,
keycode: keycodes.comma
};
export const SHOW_REQUEST_SETTINGS: Hotkey = {
description: 'Show Request Settings',
meta: true,
alt: true,
shift: true,
keycode: keycodes.comma
};
export const SHOW_SETTINGS: Hotkey = {
description: 'Show App Preferences',
meta: true,
alt: false,
shift: false,
keycode: keycodes.comma
};
export const TOGGLE_MAIN_MENU: Hotkey = {
description: 'Toggle Main Menu',
meta: true,
alt: true,
shift: false,
keycode: keycodes.comma
};
export const TOGGLE_SIDEBAR: Hotkey = {
description: 'Toggle Sidebar',
meta: true,
alt: false,
shift: false,
keycode: keycodes.backslash
};
export const SHOW_QUICK_SWITCHER: Hotkey = {
description: 'Switch Requests',
meta: true,
alt: false,
shift: false,
keycode: keycodes.p
};
export const SHOW_AUTOCOMPLETE: Hotkey = {
description: 'Show Autocomplete',
meta: true,
alt: false,
shift: false,
keycode: keycodes.space
};
export const SEND_REQUEST: Hotkey = {
description: 'Send Request',
meta: true,
alt: false,
shift: false,
keycode: [keycodes.enter, keycodes.r]
};
export const SEND_REQUEST_F5: Hotkey = {
description: 'Send Request',
meta: false,
alt: false,
shift: false,
keycode: keycodes.f5
};
export const SHOW_SEND_OPTIONS: Hotkey = {
description: 'Send Request (Options)',
meta: true,
alt: false,
shift: true,
keycode: keycodes.enter
};
export const SHOW_ENVIRONMENTS: Hotkey = {
description: 'Show Environment Editor',
meta: true,
alt: false,
shift: false,
keycode: keycodes.e
};
export const TOGGLE_ENVIRONMENTS_MENU: Hotkey = {
description: 'Switch Environments',
meta: true,
alt: false,
shift: true,
keycode: keycodes.e
};
export const TOGGLE_METHOD_DROPDOWN: Hotkey = {
description: 'Change HTTP Method',
meta: true,
alt: false,
shift: true,
keycode: keycodes.l
};
export const TOGGLE_HISTORY_DROPDOWN: Hotkey = {
description: 'Show Request History',
meta: true,
alt: false,
shift: true,
keycode: keycodes.h
};
export const FOCUS_URL: Hotkey = {
description: 'Focus URL',
meta: true,
alt: false,
shift: false,
keycode: keycodes.l
};
export const GENERATE_CODE: Hotkey = {
description: 'Generate Code',
meta: true,
alt: false,
shift: true,
keycode: keycodes.g
};
export const FOCUS_FILTER: Hotkey = {
description: 'Filter Sidebar',
meta: true,
alt: false,
shift: true,
keycode: keycodes.f
};
export const SHOW_COOKIES: Hotkey = {
description: 'Edit Cookies',
meta: true,
alt: false,
shift: false,
keycode: keycodes.k
};
export const CREATE_REQUEST: Hotkey = {
description: 'Create Request',
meta: true,
alt: false,
shift: false,
keycode: keycodes.n
};
export const CREATE_FOLDER: Hotkey = {
description: 'Create Folder',
meta: true,
alt: false,
shift: true,
keycode: keycodes.n
};
export const DUPLICATE_REQUEST: Hotkey = {
description: 'Duplicate Request',
meta: true,
alt: false,
shift: false,
keycode: keycodes.d
};
export const CLOSE_DROPDOWN: Hotkey = {
description: 'Close Dropdown',
meta: false,
alt: false,
shift: false,
keycode: keycodes.esc
};
export const CLOSE_MODAL: Hotkey = {
description: 'Close Modal',
meta: false,
alt: false,
shift: false,
keycode: keycodes.esc
};
export function pressedHotKey (e: KeyboardEvent, definition: Hotkey): boolean {
const isMetaPressed = isMac() ? e.metaKey : e.ctrlKey;
const isAltPressed = isMac() ? e.ctrlKey : e.altKey;
const isShiftPressed = e.shiftKey;
const {meta, alt, shift, keycode} = definition;
const codes = Array.isArray(keycode) ? keycode : [keycode];
for (const code of codes) {
if ((alt && !isAltPressed) || (!alt && isAltPressed)) {
continue;
}
if ((meta && !isMetaPressed) || (!meta && isMetaPressed)) {
continue;
}
if ((shift && !isShiftPressed) || (!shift && isShiftPressed)) {
continue;
}
if (code !== e.keyCode) {
continue;
}
return true;
}
return false;
}
export function executeHotKey (
e: KeyboardEvent,
definition: Hotkey,
callback: Function
): void {
if (pressedHotKey(e, definition)) {
callback();
trackEvent('Hotkey', definition.description);
}
}
export function getChar (hotkey: Hotkey) {
const codes = Array.isArray(hotkey.keycode) ? hotkey.keycode : [hotkey.keycode];
const chars = [];
for (const keycode of codes) {
const v = Object.keys(keycodes).find(k => keycodes[k] === keycode);
if (!v) {
console.error('Invalid hotkey', hotkey);
} else if (v.toUpperCase() === 'ENTER') {
chars.push('Enter');
} else if (v.toUpperCase() === 'COMMA') {
chars.push(',');
} else if (v.toUpperCase() === 'BACKSLASH') {
chars.push('\\');
} else if (v.toUpperCase() === 'FORWARDSLASH') {
chars.push('/');
} else if (v.toUpperCase() === 'SPACE') {
chars.push('Space');
} else {
chars.push(v.toUpperCase());
}
}
return chars[0] || 'unknown';
}