chore(launch_bar): reintroduce keyboard shortcuts

This commit is contained in:
Elian Doran 2025-12-05 19:23:40 +02:00
parent 17241be4bc
commit fdb6677153
No known key found for this signature in database
5 changed files with 47 additions and 18 deletions

View File

@ -1,7 +1,7 @@
import utils from "./utils.js";
type ElementType = HTMLElement | Document;
type Handler = (e: KeyboardEvent) => void;
export type Handler = (e: KeyboardEvent) => void;
export interface ShortcutBinding {
element: HTMLElement | Document;

View File

@ -2,16 +2,22 @@ import appContext from "../../components/app_context";
import FNote from "../../entities/fnote";
import link_context_menu from "../../menus/link_context_menu";
import { escapeHtml, isCtrlKey } from "../../services/utils";
import { useGlobalShortcut, useNoteLabel } from "../react/hooks";
import { LaunchBarActionButton, useLauncherIconAndTitle } from "./launch_bar_widgets";
export function CustomNoteLauncher({ launcherNote, getTargetNoteId, getHoistedNoteId }: {
launcherNote: FNote,
getTargetNoteId: (launcherNote: FNote) => string | null | Promise<string | null>,
getHoistedNoteId?: (launcherNote: FNote) => string | null
launcherNote: FNote;
getTargetNoteId: (launcherNote: FNote) => string | null | Promise<string | null>;
getHoistedNoteId?: (launcherNote: FNote) => string | null;
keyboardShortcut?: string;
}) {
const { icon, title } = useLauncherIconAndTitle(launcherNote);
async function launch(evt: MouseEvent) {
// Keyboard shortcut.
const [ shortcut ] = useNoteLabel(launcherNote, "keyboardShortcut");
useGlobalShortcut(shortcut, launch);
async function launch(evt: MouseEvent | KeyboardEvent) {
if (evt.which === 3) {
return;
}

View File

@ -1,5 +1,5 @@
import { useContext, useEffect, useMemo, useState } from "preact/hooks";
import { useLegacyWidget, useNoteContext, useNoteLabel, useNoteRelationTarget, useTriliumOptionBool } from "../react/hooks";
import { useGlobalShortcut, useLegacyWidget, useNoteContext, useNoteLabel, useNoteRelationTarget, useTriliumOptionBool } from "../react/hooks";
import { ParentComponent } from "../react/react_utils";
import BasicWidget from "../basic_widget";
import FNote from "../../entities/fnote";
@ -52,11 +52,8 @@ export function NoteLauncher({ launcherNote, ...restProps }: { launcherNote: FNo
export function ScriptLauncher({ launcherNote }: LauncherNoteProps) {
const { icon, title } = useLauncherIconAndTitle(launcherNote);
return (
<LaunchBarActionButton
icon={icon}
text={title}
onClick={async () => {
async function launch() {
if (launcherNote.isLabelTruthy("scriptInLauncherContent")) {
await launcherNote.executeScript();
} else {
@ -65,7 +62,17 @@ export function ScriptLauncher({ launcherNote }: LauncherNoteProps) {
await script.executeScript();
}
}
}}
}
// Keyboard shortcut.
const [ shortcut ] = useNoteLabel(launcherNote, "keyboardShortcut");
useGlobalShortcut(shortcut, launch);
return (
<LaunchBarActionButton
icon={icon}
text={title}
onClick={launch}
/>
)
}

View File

@ -20,9 +20,9 @@ import options, { type OptionValue } from "../../services/options";
import protected_session_holder from "../../services/protected_session_holder";
import SpacedUpdate from "../../services/spaced_update";
import toast, { ToastOptions } from "../../services/toast";
import utils, { escapeRegExp, reloadFrontendApp } from "../../services/utils";
import utils, { escapeRegExp, randomString, reloadFrontendApp } from "../../services/utils";
import server from "../../services/server";
import { removeIndividualBinding } from "../../services/shortcuts";
import shortcuts, { Handler, removeIndividualBinding } from "../../services/shortcuts";
import froca from "../../services/froca";
export function useTriliumEvent<T extends EventNames>(eventName: T, handler: (data: EventData<T>) => void) {
@ -812,6 +812,21 @@ export function useKeyboardShortcuts(scope: "code-detail" | "text-detail", conta
}, [ scope, containerRef, parentComponent, ntxId ]);
}
/**
* Register a global shortcut. Internally it uses the shortcut service and assignes a random namespace to make it unique.
*
* @param keyboardShortcut the keyboard shortcut combination to register.
* @param handler the corresponding handler to be called when the keyboard shortcut is invoked by the user.
*/
export function useGlobalShortcut(keyboardShortcut: string | null | undefined, handler: Handler) {
useEffect(() => {
if (!keyboardShortcut) return;
const namespace = randomString(10);
shortcuts.bindGlobalShortcut(keyboardShortcut, handler, namespace);
return () => shortcuts.removeGlobalShortcut(namespace);
}, [ keyboardShortcut, handler ]);
}
/**
* Indicates that the current note is in read-only mode, while an editing mode is available,
* and provides a way to switch to editing mode.

View File

@ -27,6 +27,7 @@ type Labels = {
// Launch bar
bookmarkFolder: boolean;
command: string;
keyboardShortcut: string;
// Collection-specific
viewType: string;