diff --git a/apps/client/src/widgets/react/hooks.tsx b/apps/client/src/widgets/react/hooks.tsx index 3d62b3985..8071c962e 100644 --- a/apps/client/src/widgets/react/hooks.tsx +++ b/apps/client/src/widgets/react/hooks.tsx @@ -15,29 +15,31 @@ import { RefObject, VNode } from "preact"; import { Tooltip } from "bootstrap"; import { CSSProperties } from "preact/compat"; -type TriliumEventHandler = (data: EventData) => void; +export function useTriliumEvent(eventName: T, handler: (data: EventData) => void) { + const parentComponent = useContext(ParentComponent)!; + parentComponent.registerHandler(eventName, handler); + return (() => parentComponent.removeHandler(eventName, handler)); +} -export function useTriliumEvent(eventName: T | T[], handler: TriliumEventHandler) { - const parentComponent = useContext(ParentComponent); +export function useTriliumEvents(eventNames: T[], handler: (data: EventData, eventName: T) => void) { + const parentComponent = useContext(ParentComponent)!; + const handlers: ({ eventName: T, callback: (data: EventData) => void })[] = []; - if (!parentComponent) { - console.error("React widget has no legacy parent component. Event handling will not work.", new Error().stack); - return; + for (const eventName of eventNames) { + handlers.push({ eventName, callback: (data) => { + handler(data, eventName); + }}) } - if (Array.isArray(eventName)) { - for (const eventSingleName of eventName) { - parentComponent.registerHandler(eventSingleName, handler); + for (const { eventName, callback } of handlers) { + parentComponent.registerHandler(eventName, callback); + } + + return (() => { + for (const { eventName, callback } of handlers) { + parentComponent.removeHandler(eventName, callback); } - return (() => { - for (const eventSingleName of eventName) { - parentComponent.removeHandler(eventSingleName, handler) - } - }); - } else { - parentComponent.registerHandler(eventName, handler); - return (() => parentComponent.removeHandler(eventName, handler)); - } + }); } export function useSpacedUpdate(callback: () => void | Promise, interval = 1000) { diff --git a/apps/client/src/widgets/ribbon/Ribbon.tsx b/apps/client/src/widgets/ribbon/Ribbon.tsx index e439529f3..2a64d34de 100644 --- a/apps/client/src/widgets/ribbon/Ribbon.tsx +++ b/apps/client/src/widgets/ribbon/Ribbon.tsx @@ -1,6 +1,6 @@ -import { useEffect, useMemo, useState } from "preact/hooks"; +import { useCallback, useEffect, useMemo, useState } from "preact/hooks"; import { t } from "../../services/i18n"; -import { useNoteContext } from "../react/hooks"; +import { useNoteContext, useTriliumEvent, useTriliumEvents } from "../react/hooks"; import "./style.css"; import { VNode } from "preact"; import BasicPropertiesTab from "./BasicPropertiesTab"; @@ -8,7 +8,7 @@ import FormattingTab from "./FormattingTab"; import { numberObjectsInPlace } from "../../services/utils"; import { TabContext } from "./ribbon-interface"; import options from "../../services/options"; -import { CommandNames } from "../../components/app_context"; +import { CommandNames, EventNames } from "../../components/app_context"; import FNote from "../../entities/fnote"; import ScriptTab from "./ScriptTab"; import EditedNotesTab from "./EditedNotesTab"; @@ -170,6 +170,19 @@ export default function Ribbon() { } }, [ note?.noteId ]); + // Register keyboard shortcuts. + const eventsToListenTo = useMemo(() => TAB_CONFIGURATION.filter(config => config.toggleCommand).map(config => config.toggleCommand) as EventNames[], []); + useTriliumEvents(eventsToListenTo, useCallback((e, toggleCommand) => { + const correspondingTab = filteredTabs.find(tab => tab.toggleCommand === toggleCommand); + if (correspondingTab) { + if (activeTabIndex !== correspondingTab.index) { + setActiveTabIndex(correspondingTab.index); + } else { + setActiveTabIndex(undefined); + } + } + }, [ filteredTabs, activeTabIndex ])); + return (