diff --git a/apps/client/src/widgets/react/FormText.tsx b/apps/client/src/widgets/react/FormText.tsx index 76ea6c3e6..4fbf4b3c3 100644 --- a/apps/client/src/widgets/react/FormText.tsx +++ b/apps/client/src/widgets/react/FormText.tsx @@ -1,5 +1,5 @@ import { ComponentChildren } from "preact"; export default function FormText({ children }: { children: ComponentChildren }) { - return

{children}

+ return

{children}

} \ No newline at end of file diff --git a/apps/client/src/widgets/type_widgets/content_widget.tsx b/apps/client/src/widgets/type_widgets/content_widget.tsx index e34fa2a6b..0d38426f6 100644 --- a/apps/client/src/widgets/type_widgets/content_widget.tsx +++ b/apps/client/src/widgets/type_widgets/content_widget.tsx @@ -39,6 +39,7 @@ import EtapiSettings from "./options/etapi.js"; import BackupSettings from "./options/backup.js"; import SpellcheckSettings from "./options/spellcheck.js"; import PasswordSettings from "./options/password.jsx"; +import ShortcutSettings from "./options/shortcuts.js"; const TPL = /*html*/`
- -

${t("shortcuts.keyboard_shortcuts")}

- - - -
- -
- -
- - - - - - - - - - -
${t("shortcuts.action_name")}${t("shortcuts.shortcuts")}${t("shortcuts.default_shortcuts")}${t("shortcuts.description")}
-
- -
- - - -
-
`; - -let globActions: KeyboardShortcut[]; - -export default class KeyboardShortcutsOptions extends OptionsWidget { - doRender() { - this.$widget = $(TPL); - - this.$widget.find(".options-keyboard-shortcuts-reload-app").on("click", () => utils.reloadFrontendApp()); - - const $table = this.$widget.find(".keyboard-shortcut-table tbody"); - - server.get("keyboard-actions").then((actions) => { - globActions = actions; - - for (const action of actions) { - const $tr = $(""); - - if ("separator" in action) { - $tr.append($('').attr("style", "background-color: var(--accented-background-color); font-weight: bold;").text(action.separator)); - } else if (action.defaultShortcuts && action.actionName) { - $tr.append($("").text(action.friendlyName)) - .append( - $("").append( - $(``) - .val((action.effectiveShortcuts ?? []).join(", ")) - .attr("data-keyboard-action-name", action.actionName) - .attr("data-default-keyboard-shortcuts", action.defaultShortcuts.join(", ")) - ) - ) - .append($("").text(action.defaultShortcuts.join(", "))) - .append($("").text(action.description ?? "")); - } - - $table.append($tr); - } - }); - - $table.on("change", "input.form-control", (e) => { - const $input = this.$widget.find(e.target); - const actionName = $input.attr("data-keyboard-action-name"); - if (!actionName) { - return; - } - - const shortcuts = ($input.val() as String) - .replace("+,", "+Comma") - .split(",") - .map((shortcut) => shortcut.replace("+Comma", "+,")) - .filter((shortcut) => !!shortcut); - - const optionName = `keyboardShortcuts${actionName.substr(0, 1).toUpperCase()}${actionName.substr(1)}`; - - this.updateOption(optionName as OptionNames, JSON.stringify(shortcuts)); - }); - - this.$widget.find(".options-keyboard-shortcuts-set-all-to-default").on("click", async () => { - if (!(await dialogService.confirm(t("shortcuts.confirm_reset")))) { - return; - } - - $table.find("input.form-control").each((_index, el) => { - const defaultShortcuts = this.$widget.find(el).attr("data-default-keyboard-shortcuts"); - - if (defaultShortcuts && this.$widget.find(el).val() !== defaultShortcuts) { - this.$widget.find(el).val(defaultShortcuts).trigger("change"); - } - }); - }); - - const $filter = this.$widget.find(".keyboard-shortcut-filter"); - - $filter.on("keyup", () => { - const filter = String($filter.val()).trim().toLowerCase(); - - $table.find("tr").each((i, el) => { - if (!filter) { - this.$widget.find(el).show(); - return; - } - - const actionName = this.$widget.find(el).find("input").attr("data-keyboard-action-name"); - - if (!actionName) { - this.$widget.find(el).hide(); - return; - } - - const action = globActions.find((act) => "actionName" in act && act.actionName === actionName) as KeyboardShortcutWithRequiredActionName; - - if (!action) { - this.$widget.find(el).hide(); - return; - } - - this.$widget - .find(el) - .toggle( - !!( - action.actionName.toLowerCase().includes(filter) || - (action.friendlyName && action.friendlyName.toLowerCase().includes(filter)) || - (action.defaultShortcuts ?? []).some((shortcut) => shortcut.toLowerCase().includes(filter)) || - (action.effectiveShortcuts ?? []).some((shortcut) => shortcut.toLowerCase().includes(filter)) || - (action.description && action.description.toLowerCase().includes(filter)) - ) - ); - }); - }); - } -} diff --git a/apps/client/src/widgets/type_widgets/options/shortcuts.tsx b/apps/client/src/widgets/type_widgets/options/shortcuts.tsx new file mode 100644 index 000000000..770ebce87 --- /dev/null +++ b/apps/client/src/widgets/type_widgets/options/shortcuts.tsx @@ -0,0 +1,140 @@ +import { ActionKeyboardShortcut, KeyboardShortcut } from "@triliumnext/commons"; +import { t } from "../../../services/i18n"; +import { reloadFrontendApp } from "../../../services/utils"; +import Button from "../../react/Button"; +import FormGroup from "../../react/FormGroup"; +import FormText from "../../react/FormText"; +import FormTextBox from "../../react/FormTextBox"; +import RawHtml from "../../react/RawHtml"; +import OptionsSection from "./components/OptionsSection"; +import { useCallback, useEffect, useState } from "preact/hooks"; +import server from "../../../services/server"; +import options from "../../../services/options"; +import dialog from "../../../services/dialog"; + +export default function ShortcutSettings() { + const [ keyboardShortcuts, setKeyboardShortcuts ] = useState([]); + const [ filter, setFilter ] = useState(); + + useEffect(() => { + server.get("keyboard-actions").then(setKeyboardShortcuts); + }, []) + + const resetShortcuts = useCallback(async () => { + if (!(await dialog.confirm(t("shortcuts.confirm_reset")))) { + return; + } + + const newKeyboardShortcuts = []; + for (const keyboardShortcut of keyboardShortcuts) { + if (!("effectiveShortcuts" in keyboardShortcut)) { + continue; + } + + } + }, [ keyboardShortcuts ]); + + return ( + + + {t("shortcuts.multiple_shortcuts")} + + + + + setFilter(value.toLowerCase())} + /> + + +
+ +
+ +
+
+
+ ) +} + +function filterKeyboardAction(action: ActionKeyboardShortcut, filter: string) { + return action.actionName.toLowerCase().includes(filter) || + (action.friendlyName && action.friendlyName.toLowerCase().includes(filter)) || + (action.defaultShortcuts ?? []).some((shortcut) => shortcut.toLowerCase().includes(filter)) || + (action.effectiveShortcuts ?? []).some((shortcut) => shortcut.toLowerCase().includes(filter)) || + (action.description && action.description.toLowerCase().includes(filter)); +} + +function KeyboardShortcutTable({ filter, keyboardShortcuts }: { filter?: string, keyboardShortcuts: KeyboardShortcut[] }) { + return ( + + + + + + + + + + + {keyboardShortcuts.map(action => ( + + {"separator" in action ? ( !filter && + + ) : ( (!filter || filterKeyboardAction(action, filter)) && + <> + + + + + + )} + + ))} + +
{t("shortcuts.action_name")}{t("shortcuts.shortcuts")}{t("shortcuts.default_shortcuts")}{t("shortcuts.description")}
+ {action.separator} + {action.friendlyName} + + {action.defaultShortcuts?.join(", ")}{action.description}
+ ); +} + +function ShortcutEditor({ keyboardShortcut: action }: { keyboardShortcut: ActionKeyboardShortcut }) { + const [ shortcuts, setShortcuts ] = useState((action.effectiveShortcuts ?? []).join(", ")); + + useEffect(() => { + const { actionName } = action; + const optionName = `keyboardShortcuts${actionName.substr(0, 1).toUpperCase()}${actionName.substr(1)}`; + const newShortcuts = shortcuts + .replace("+,", "+Comma") + .split(",") + .map((shortcut) => shortcut.replace("+Comma", "+,")) + .filter((shortcut) => !!shortcut); + options.save(optionName, JSON.stringify(newShortcuts)); + }, [ shortcuts ]) + + return ( + + ) +} \ No newline at end of file