Add getPlatformString for making shortcuts to platform string

This commit is contained in:
Henrik Giesel 2021-04-22 13:04:24 +02:00
parent 2109b67caf
commit e95e78da9c
3 changed files with 89 additions and 19 deletions

2
ftl/core/keyboard.ftl Normal file
View file

@ -0,0 +1,2 @@
keyboard-ctrl = Ctrl
keyboard-shift = Shift

View file

@ -7,13 +7,23 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { ToolbarItem } from "./types";
import { onDestroy } from "svelte";
import { registerShortcut } from "anki/shortcuts";
import { registerShortcut, getPlatformString } from "anki/shortcuts";
export let button: ToolbarItem;
export let shortcuts: string[];
function extend({ ...rest }: DynamicSvelteComponent): DynamicSvelteComponent {
function extend({
tooltip,
...rest
}: DynamicSvelteComponent): DynamicSvelteComponent {
const platformShortcut = getPlatformString(shortcuts[0]);
if (tooltip) {
tooltip = `${tooltip} (${platformShortcut})`;
}
return {
tooltip,
...rest,
};
}

View file

@ -1,7 +1,69 @@
import * as tr from "./i18n";
const modifiers = ["Control", "Alt", "Shift", "Meta"];
// how modifiers are mapped
const platformModifiers =
navigator.platform === "MacIntel" ? ["Meta", "Alt", "Shift", "Control"] : modifiers;
navigator.platform === "MacIntel"
? ["Meta", "Alt", "Shift", "Control"]
: ["Control", "Alt", "Shift", "OS"];
function splitKeyCombinationString(keyCombinationString: string): string[][] {
return keyCombinationString.split(", ").map((segment) => segment.split("+"));
}
function modifiersToPlatformString(modifiers: string[]): string {
const displayModifiers =
navigator.platform === "MacIntel"
? ["^", "⌥", "⇧", "⌘"]
: [`${tr.keyboardCtrl()}+`, "Alt+", `${tr.keyboardShift()}+`, "Win+"];
let result = "";
for (const modifier of modifiers) {
result += displayModifiers[platformModifiers.indexOf(modifier)];
}
return result;
}
const alphabeticPrefix = "Key";
const numericPrefix = "Digit";
const keyToCharacterMap = {
Backslash: "\\",
Backquote: "`",
BracketLeft: "[",
BrackerRight: "]",
Quote: "'",
Semicolon: ";",
Minus: "-",
Equal: "=",
Comma: ",",
Period: ".",
Slash: "/",
};
function keyToPlatformString(key: string): string {
return key.startsWith(alphabeticPrefix)
? key.slice(alphabeticPrefix.length)
: key.startsWith(numericPrefix)
? key.slice(numericPrefix.length)
: Object.prototype.hasOwnProperty.call(keyToCharacterMap, key)
? keyToCharacterMap[key]
: key;
}
function toPlatformString(modifiersAndKey: string[]) {
return `${modifiersToPlatformString(
modifiersAndKey.slice(0, -1)
)}${keyToPlatformString(modifiersAndKey[modifiersAndKey.length - 1])}`;
}
export function getPlatformString(keyCombinationString: string): string {
return splitKeyCombinationString(keyCombinationString)
.map(toPlatformString)
.join(", ");
}
function checkKey(event: KeyboardEvent, key: string): boolean {
return event.code === key;
@ -24,32 +86,28 @@ function check(event: KeyboardEvent, modifiersAndKey: string[]): boolean {
);
}
function normalizeShortcutString(shortcutString: string): string[][] {
return shortcutString.split(", ").map((segment) => segment.split("+"));
}
const shortcutTimeoutMs = 350;
function innerShortcut(
lastEvent: KeyboardEvent,
callback: (event: KeyboardEvent) => void,
...shortcuts: string[][]
...keyCombination: string[][]
): void {
if (shortcuts.length === 0) {
if (keyCombination.length === 0) {
callback(lastEvent);
} else {
const [nextShortcut, ...restShortcuts] = shortcuts;
const [nextKey, ...restKeys] = keyCombination;
let ivl: number;
const handler = (event: KeyboardEvent): void => {
if (check(event, nextShortcut)) {
innerShortcut(event, callback, ...restShortcuts);
clearInterval(ivl);
if (check(event, nextKey)) {
innerShortcut(event, callback, ...restKeys);
clearTimeout(ivl);
}
};
ivl = setInterval(
ivl = setTimeout(
(): void => document.removeEventListener("keydown", handler),
shortcutTimeoutMs
);
@ -60,14 +118,14 @@ function innerShortcut(
export function registerShortcut(
callback: (event: KeyboardEvent) => void,
shortcutString: string
keyCombinationString: string
): () => void {
const shortcuts = normalizeShortcutString(shortcutString);
const [firstShortcut, ...restShortcuts] = shortcuts;
const keyCombination = splitKeyCombinationString(keyCombinationString);
const [firstKey, ...restKeys] = keyCombination;
const handler = (event: KeyboardEvent): void => {
if (check(event, firstShortcut)) {
innerShortcut(event, callback, ...restShortcuts);
if (check(event, firstKey)) {
innerShortcut(event, callback, ...restKeys);
}
};