Add optionalModifiers parameter to registerShortcut

This commit is contained in:
Henrik Giesel 2021-04-22 17:28:38 +02:00
parent 7aaf7b7fe0
commit 31e4b79ff4
2 changed files with 26 additions and 16 deletions

View file

@ -62,11 +62,8 @@ function updateFocus(evt: FocusEvent) {
registerShortcut( registerShortcut(
() => document.addEventListener("focusin", updateFocus, { once: true }), () => document.addEventListener("focusin", updateFocus, { once: true }),
"Tab" "Tab",
); ["Shift"]
registerShortcut(
() => document.addEventListener("focusin", updateFocus, { once: true }),
"Shift+Tab"
); );
export function onKeyUp(evt: KeyboardEvent): void { export function onKeyUp(evt: KeyboardEvent): void {

View file

@ -2,7 +2,9 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import * as tr from "./i18n"; import * as tr from "./i18n";
const modifiers = ["Control", "Alt", "Shift", "Meta"]; type Modifier = "Control" | "Alt" | "Shift" | "Meta";
const modifiers: Modifier[] = ["Control", "Alt", "Shift", "Meta"];
// how modifiers are mapped // how modifiers are mapped
const platformModifiers = const platformModifiers =
@ -71,20 +73,29 @@ function checkKey(event: KeyboardEvent, key: string): boolean {
return event.code === key; return event.code === key;
} }
function checkModifiers(event: KeyboardEvent, activeModifiers: string[]): boolean { function checkModifiers(
event: KeyboardEvent,
optionalModifiers: Modifier[],
activeModifiers: string[]
): boolean {
return modifiers.reduce( return modifiers.reduce(
(matches: boolean, modifier: string, currentIndex: number): boolean => (matches: boolean, modifier: string, currentIndex: number): boolean =>
matches && matches &&
(optionalModifiers.includes(modifier as Modifier) ||
event.getModifierState(platformModifiers[currentIndex]) === event.getModifierState(platformModifiers[currentIndex]) ===
activeModifiers.includes(modifier), activeModifiers.includes(modifier)),
true true
); );
} }
function check(event: KeyboardEvent, modifiersAndKey: string[]): boolean { function check(
event: KeyboardEvent,
optionalModifiers: Modifier[],
modifiersAndKey: string[]
): boolean {
return ( return (
checkKey(event, modifiersAndKey[modifiersAndKey.length - 1]) && checkKey(event, modifiersAndKey[modifiersAndKey.length - 1]) &&
checkModifiers(event, modifiersAndKey.slice(0, -1)) checkModifiers(event, optionalModifiers, modifiersAndKey.slice(0, -1))
); );
} }
@ -93,6 +104,7 @@ const shortcutTimeoutMs = 400;
function innerShortcut( function innerShortcut(
lastEvent: KeyboardEvent, lastEvent: KeyboardEvent,
callback: (event: KeyboardEvent) => void, callback: (event: KeyboardEvent) => void,
optionalModifiers: Modifier[],
...keyCombination: string[][] ...keyCombination: string[][]
): void { ): void {
let interval: number; let interval: number;
@ -103,8 +115,8 @@ function innerShortcut(
const [nextKey, ...restKeys] = keyCombination; const [nextKey, ...restKeys] = keyCombination;
const handler = (event: KeyboardEvent): void => { const handler = (event: KeyboardEvent): void => {
if (check(event, nextKey)) { if (check(event, optionalModifiers, nextKey)) {
innerShortcut(event, callback, ...restKeys); innerShortcut(event, callback, optionalModifiers, ...restKeys);
clearTimeout(interval); clearTimeout(interval);
} }
}; };
@ -120,14 +132,15 @@ function innerShortcut(
export function registerShortcut( export function registerShortcut(
callback: (event: KeyboardEvent) => void, callback: (event: KeyboardEvent) => void,
keyCombinationString: string keyCombinationString: string,
optionalModifiers: Modifier[] = []
): () => void { ): () => void {
const keyCombination = splitKeyCombinationString(keyCombinationString); const keyCombination = splitKeyCombinationString(keyCombinationString);
const [firstKey, ...restKeys] = keyCombination; const [firstKey, ...restKeys] = keyCombination;
const handler = (event: KeyboardEvent): void => { const handler = (event: KeyboardEvent): void => {
if (check(event, firstKey)) { if (check(event, optionalModifiers, firstKey)) {
innerShortcut(event, callback, ...restKeys); innerShortcut(event, callback, optionalModifiers, ...restKeys);
} }
}; };