Prefer optionalModifiers over register multiple shortcuts

This commit is contained in:
Henrik Giesel 2021-04-22 17:52:27 +02:00
parent 31e4b79ff4
commit 5197e3b779
9 changed files with 70 additions and 65 deletions

View file

@ -2,7 +2,8 @@
// 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 type { ToolbarItem } from "./types"; import type { ToolbarItem } from "./types";
export interface WithShortcutsProps { export interface WithShortcutProps {
button: ToolbarItem; button: ToolbarItem;
shortcuts: string[]; shortcut: string;
optionalModifiers: string[];
} }

View file

@ -7,13 +7,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { ToolbarItem } from "./types"; import type { ToolbarItem } from "./types";
import { onDestroy } from "svelte"; import { onDestroy } from "svelte";
import { registerShortcut, getPlatformString } from "anki/shortcuts"; import { Modifier, registerShortcut, getPlatformString } from "anki/shortcuts";
export let button: ToolbarItem; export let button: ToolbarItem;
export let shortcuts: string[]; export let shortcut: string;
export let optionalModifiers: Modifier[];
function extend({ ...rest }: DynamicSvelteComponent): DynamicSvelteComponent { function extend({ ...rest }: DynamicSvelteComponent): DynamicSvelteComponent {
const shortcutLabel = getPlatformString(shortcuts[0]); const shortcutLabel = getPlatformString(shortcut);
return { return {
shortcutLabel, shortcutLabel,
@ -21,19 +22,21 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
}; };
} }
let deregisters: (() => void)[]; let deregister: () => void;
function createShortcut({ detail }: CustomEvent): void { function createShortcut({ detail }: CustomEvent): void {
const mounted: HTMLButtonElement = detail.button; const mounted: HTMLButtonElement = detail.button;
deregisters = shortcuts.map((shortcut: string): (() => void) => deregister = registerShortcut(
registerShortcut((event) => { (event: KeyboardEvent) => {
mounted.dispatchEvent(new MouseEvent("click")); mounted.dispatchEvent(new KeyboardEvent("click", event));
event.preventDefault(); event.preventDefault();
}, shortcut) },
shortcut,
optionalModifiers
); );
} }
onDestroy(() => deregisters.forEach((dereg: () => void): void => dereg())); onDestroy(() => deregister());
</script> </script>
<svelte:component <svelte:component

View file

@ -20,8 +20,8 @@ import type { DropdownItemProps } from "./DropdownItem";
import WithDropdownMenu from "./WithDropdownMenu.svelte"; import WithDropdownMenu from "./WithDropdownMenu.svelte";
import type { WithDropdownMenuProps } from "./WithDropdownMenu"; import type { WithDropdownMenuProps } from "./WithDropdownMenu";
import WithShortcuts from "./WithShortcuts.svelte"; import WithShortcut from "./WithShortcut.svelte";
import type { WithShortcutsProps } from "./WithShortcuts"; import type { WithShortcutProps } from "./WithShortcut";
import { dynamicComponent } from "sveltelib/dynamicComponent"; import { dynamicComponent } from "sveltelib/dynamicComponent";
@ -59,6 +59,6 @@ export const withDropdownMenu = dynamicComponent<
WithDropdownMenuProps WithDropdownMenuProps
>(WithDropdownMenu); >(WithDropdownMenu);
export const withShortcuts = dynamicComponent<typeof WithShortcuts, WithShortcutsProps>( export const withShortcut = dynamicComponent<typeof WithShortcut, WithShortcutProps>(
WithShortcuts WithShortcut
); );

View file

@ -1,11 +1,11 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// 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 type WithShortcuts from "editor-toolbar/WithShortcuts.svelte"; import type WithShortcut from "editor-toolbar/WithShortcut.svelte";
import type { WithShortcutsProps } from "editor-toolbar/WithShortcuts"; import type { WithShortcutProps } from "editor-toolbar/WithShortcut";
import type { DynamicSvelteComponent } from "sveltelib/dynamicComponent"; import type { DynamicSvelteComponent } from "sveltelib/dynamicComponent";
import * as tr from "anki/i18n"; import * as tr from "anki/i18n";
import { iconButton, withShortcuts } from "editor-toolbar/dynamicComponents"; import { iconButton, withShortcut } from "editor-toolbar/dynamicComponents";
import bracketsIcon from "./code-brackets.svg"; import bracketsIcon from "./code-brackets.svg";
@ -35,16 +35,17 @@ function getCurrentHighestCloze(increment: boolean): number {
return Math.max(1, highest); return Math.max(1, highest);
} }
function onCloze(event: MouseEvent): void { function onCloze(event: KeyboardEvent | MouseEvent): void {
const highestCloze = getCurrentHighestCloze(!event.altKey); const highestCloze = getCurrentHighestCloze(!event.getModifierState("Alt"));
wrap(`{{c${highestCloze}::`, "}}"); wrap(`{{c${highestCloze}::`, "}}");
} }
export function getClozeButton(): DynamicSvelteComponent<typeof WithShortcuts> & export function getClozeButton(): DynamicSvelteComponent<typeof WithShortcut> &
WithShortcutsProps { WithShortcutProps {
return withShortcuts({ return withShortcut({
id: "cloze", id: "cloze",
shortcuts: ["Control+Shift+KeyC", "Control+Alt+Shift+KeyC"], shortcut: "Control+Shift+KeyC",
optionalModifiers: ["Alt"],
button: iconButton({ button: iconButton({
icon: bracketsIcon, icon: bracketsIcon,
onClick: onCloze, onClick: onCloze,

View file

@ -8,7 +8,7 @@ import {
iconButton, iconButton,
colorPicker, colorPicker,
buttonGroup, buttonGroup,
withShortcuts, withShortcut,
} from "editor-toolbar/dynamicComponents"; } from "editor-toolbar/dynamicComponents";
import * as tr from "anki/i18n"; import * as tr from "anki/i18n";
@ -31,8 +31,8 @@ function wrapWithForecolor(color: string): void {
export function getColorGroup(): DynamicSvelteComponent<typeof ButtonGroup> & export function getColorGroup(): DynamicSvelteComponent<typeof ButtonGroup> &
ButtonGroupProps { ButtonGroupProps {
const forecolorButton = withShortcuts({ const forecolorButton = withShortcut({
shortcuts: ["F7"], shortcut: "F7",
button: iconButton({ button: iconButton({
icon: squareFillIcon, icon: squareFillIcon,
className: "forecolor", className: "forecolor",
@ -41,8 +41,8 @@ export function getColorGroup(): DynamicSvelteComponent<typeof ButtonGroup> &
}), }),
}); });
const colorpickerButton = withShortcuts({ const colorpickerButton = withShortcut({
shortcuts: ["F8"], shortcut: "F8",
button: colorPicker({ button: colorPicker({
onChange: ({ currentTarget }) => onChange: ({ currentTarget }) =>
setForegroundColor((currentTarget as HTMLInputElement).value), setForegroundColor((currentTarget as HTMLInputElement).value),

View file

@ -9,7 +9,7 @@ import {
commandIconButton, commandIconButton,
iconButton, iconButton,
buttonGroup, buttonGroup,
withShortcuts, withShortcut,
} from "editor-toolbar/dynamicComponents"; } from "editor-toolbar/dynamicComponents";
import boldIcon from "./type-bold.svg"; import boldIcon from "./type-bold.svg";
@ -21,8 +21,8 @@ import eraserIcon from "./eraser.svg";
export function getFormatInlineGroup(): DynamicSvelteComponent<typeof ButtonGroup> & export function getFormatInlineGroup(): DynamicSvelteComponent<typeof ButtonGroup> &
ButtonGroupProps { ButtonGroupProps {
const boldButton = withShortcuts({ const boldButton = withShortcut({
shortcuts: ["Control+KeyB"], shortcut: "Control+KeyB",
button: commandIconButton({ button: commandIconButton({
icon: boldIcon, icon: boldIcon,
tooltip: tr.editingBoldText(), tooltip: tr.editingBoldText(),
@ -30,8 +30,8 @@ export function getFormatInlineGroup(): DynamicSvelteComponent<typeof ButtonGrou
}), }),
}); });
const italicButton = withShortcuts({ const italicButton = withShortcut({
shortcuts: ["Control+KeyI"], shortcut: "Control+KeyI",
button: commandIconButton({ button: commandIconButton({
icon: italicIcon, icon: italicIcon,
tooltip: tr.editingItalicText(), tooltip: tr.editingItalicText(),
@ -39,8 +39,8 @@ export function getFormatInlineGroup(): DynamicSvelteComponent<typeof ButtonGrou
}), }),
}); });
const underlineButton = withShortcuts({ const underlineButton = withShortcut({
shortcuts: ["Control+KeyU"], shortcut: "Control+KeyU",
button: commandIconButton({ button: commandIconButton({
icon: underlineIcon, icon: underlineIcon,
tooltip: tr.editingUnderlineText(), tooltip: tr.editingUnderlineText(),
@ -48,8 +48,8 @@ export function getFormatInlineGroup(): DynamicSvelteComponent<typeof ButtonGrou
}), }),
}); });
const superscriptButton = withShortcuts({ const superscriptButton = withShortcut({
shortcuts: ["Control+Shift+Equal"], shortcut: "Control+Shift+Equal",
button: commandIconButton({ button: commandIconButton({
icon: superscriptIcon, icon: superscriptIcon,
tooltip: tr.editingSuperscript(), tooltip: tr.editingSuperscript(),
@ -57,8 +57,8 @@ export function getFormatInlineGroup(): DynamicSvelteComponent<typeof ButtonGrou
}), }),
}); });
const subscriptButton = withShortcuts({ const subscriptButton = withShortcut({
shortcuts: ["Control+Equal"], shortcut: "Control+Equal",
button: commandIconButton({ button: commandIconButton({
icon: subscriptIcon, icon: subscriptIcon,
tooltip: tr.editingSubscript(), tooltip: tr.editingSubscript(),
@ -66,8 +66,8 @@ export function getFormatInlineGroup(): DynamicSvelteComponent<typeof ButtonGrou
}), }),
}); });
const removeFormatButton = withShortcuts({ const removeFormatButton = withShortcut({
shortcuts: ["Control+KeyR"], shortcut: "Control+KeyR",
button: iconButton({ button: iconButton({
icon: eraserIcon, icon: eraserIcon,
tooltip: tr.editingRemoveFormatting(), tooltip: tr.editingRemoveFormatting(),

View file

@ -9,7 +9,7 @@ import * as tr from "anki/i18n";
import { import {
labelButton, labelButton,
buttonGroup, buttonGroup,
withShortcuts, withShortcut,
} from "editor-toolbar/dynamicComponents"; } from "editor-toolbar/dynamicComponents";
export function getNotetypeGroup(): DynamicSvelteComponent<typeof ButtonGroup> & export function getNotetypeGroup(): DynamicSvelteComponent<typeof ButtonGroup> &
@ -21,8 +21,8 @@ export function getNotetypeGroup(): DynamicSvelteComponent<typeof ButtonGroup> &
tooltip: tr.editingCustomizeFields(), tooltip: tr.editingCustomizeFields(),
}); });
const cardsButton = withShortcuts({ const cardsButton = withShortcut({
shortcuts: ["Control+KeyL"], shortcut: "Control+KeyL",
button: labelButton({ button: labelButton({
onClick: () => bridgeCommand("cards"), onClick: () => bridgeCommand("cards"),
disables: false, disables: false,

View file

@ -13,7 +13,7 @@ import {
dropdownMenu, dropdownMenu,
dropdownItem, dropdownItem,
buttonGroup, buttonGroup,
withShortcuts, withShortcut,
} from "editor-toolbar/dynamicComponents"; } from "editor-toolbar/dynamicComponents";
import * as tr from "anki/i18n"; import * as tr from "anki/i18n";
@ -42,8 +42,8 @@ const mathjaxMenuId = "mathjaxMenu";
export function getTemplateGroup(): DynamicSvelteComponent<typeof ButtonGroup> & export function getTemplateGroup(): DynamicSvelteComponent<typeof ButtonGroup> &
ButtonGroupProps { ButtonGroupProps {
const attachmentButton = withShortcuts({ const attachmentButton = withShortcut({
shortcuts: ["F3"], shortcut: "F3",
button: iconButton({ button: iconButton({
icon: paperclipIcon, icon: paperclipIcon,
onClick: onAttachment, onClick: onAttachment,
@ -51,8 +51,8 @@ export function getTemplateGroup(): DynamicSvelteComponent<typeof ButtonGroup> &
}), }),
}); });
const recordButton = withShortcuts({ const recordButton = withShortcut({
shortcuts: ["F5"], shortcut: "F5",
button: iconButton({ button: iconButton({
icon: micIcon, icon: micIcon,
onClick: onRecord, onClick: onRecord,
@ -69,8 +69,8 @@ export function getTemplateGroup(): DynamicSvelteComponent<typeof ButtonGroup> &
menuId: mathjaxMenuId, menuId: mathjaxMenuId,
}); });
const htmlButton = withShortcuts({ const htmlButton = withShortcut({
shortcuts: ["Control+Shift+KeyX"], shortcut: "Control+Shift+KeyX",
button: iconButton({ button: iconButton({
icon: xmlIcon, icon: xmlIcon,
onClick: onHtmlEdit, onClick: onHtmlEdit,
@ -93,22 +93,22 @@ export function getTemplateGroup(): DynamicSvelteComponent<typeof ButtonGroup> &
export function getTemplateMenus(): (DynamicSvelteComponent<typeof DropdownMenu> & export function getTemplateMenus(): (DynamicSvelteComponent<typeof DropdownMenu> &
DropdownMenuProps)[] { DropdownMenuProps)[] {
const mathjaxMenuItems = [ const mathjaxMenuItems = [
withShortcuts({ withShortcut({
shortcuts: ["Control+KeyM, KeyM"], shortcut: "Control+KeyM, KeyM",
button: dropdownItem({ button: dropdownItem({
onClick: () => wrap("\\(", "\\)"), onClick: () => wrap("\\(", "\\)"),
label: tr.editingMathjaxInline(), label: tr.editingMathjaxInline(),
}), }),
}), }),
withShortcuts({ withShortcut({
shortcuts: ["Control+KeyM, KeyE"], shortcut: "Control+KeyM, KeyE",
button: dropdownItem({ button: dropdownItem({
onClick: () => wrap("\\[", "\\]"), onClick: () => wrap("\\[", "\\]"),
label: tr.editingMathjaxBlock(), label: tr.editingMathjaxBlock(),
}), }),
}), }),
withShortcuts({ withShortcut({
shortcuts: ["Control+KeyM, KeyC"], shortcut: "Control+KeyM, KeyC",
button: dropdownItem({ button: dropdownItem({
onClick: () => wrap("\\(\\ce{", "}\\)"), onClick: () => wrap("\\(\\ce{", "}\\)"),
label: tr.editingMathjaxChemistry(), label: tr.editingMathjaxChemistry(),
@ -117,22 +117,22 @@ export function getTemplateMenus(): (DynamicSvelteComponent<typeof DropdownMenu>
]; ];
const latexMenuItems = [ const latexMenuItems = [
withShortcuts({ withShortcut({
shortcuts: ["Control+KeyT, KeyT"], shortcut: "Control+KeyT, KeyT",
button: dropdownItem({ button: dropdownItem({
onClick: () => wrap("[latex]", "[/latex]"), onClick: () => wrap("[latex]", "[/latex]"),
label: tr.editingLatex(), label: tr.editingLatex(),
}), }),
}), }),
withShortcuts({ withShortcut({
shortcuts: ["Control+KeyT, KeyE"], shortcut: "Control+KeyT, KeyE",
button: dropdownItem({ button: dropdownItem({
onClick: () => wrap("[$]", "[/$]"), onClick: () => wrap("[$]", "[/$]"),
label: tr.editingLatexEquation(), label: tr.editingLatexEquation(),
}), }),
}), }),
withShortcuts({ withShortcut({
shortcuts: ["Control+KeyT, KeyM"], shortcut: "Control+KeyT, KeyM",
button: dropdownItem({ button: dropdownItem({
onClick: () => wrap("[$$]", "[/$$]"), onClick: () => wrap("[$$]", "[/$$]"),
label: tr.editingLatexMathEnv(), label: tr.editingLatexMathEnv(),

View file

@ -2,7 +2,7 @@
// 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";
type Modifier = "Control" | "Alt" | "Shift" | "Meta"; export type Modifier = "Control" | "Alt" | "Shift" | "Meta";
const modifiers: Modifier[] = ["Control", "Alt", "Shift", "Meta"]; const modifiers: Modifier[] = ["Control", "Alt", "Shift", "Meta"];