From fbc1af56edf300cf1ca828f13d298f10c51db502 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Thu, 14 Aug 2025 17:36:11 +0300 Subject: [PATCH] feat(react/settings): basic hook to read Trilium option --- .../src/widgets/react/FormRadioGroup.tsx | 4 ++- apps/client/src/widgets/react/hooks.tsx | 14 +++++++- .../{content_widget.ts => content_widget.tsx} | 8 ++--- .../type_widgets/options/appearance.tsx | 32 ++++++++++++++++++- .../type_widgets/options/appearance/theme.ts | 22 ------------- .../options/components/OptionsSection.tsx | 16 ++++++++++ 6 files changed, 67 insertions(+), 29 deletions(-) rename apps/client/src/widgets/type_widgets/{content_widget.ts => content_widget.tsx} (97%) create mode 100644 apps/client/src/widgets/type_widgets/options/components/OptionsSection.tsx diff --git a/apps/client/src/widgets/react/FormRadioGroup.tsx b/apps/client/src/widgets/react/FormRadioGroup.tsx index a6fd0ebbb..600ed8d5e 100644 --- a/apps/client/src/widgets/react/FormRadioGroup.tsx +++ b/apps/client/src/widgets/react/FormRadioGroup.tsx @@ -1,9 +1,11 @@ +import type { ComponentChildren } from "preact"; + interface FormRadioProps { name: string; currentValue?: string; values: { value: string; - label: string; + label: string | ComponentChildren; }[]; onChange(newValue: string): void; } diff --git a/apps/client/src/widgets/react/hooks.tsx b/apps/client/src/widgets/react/hooks.tsx index 1a37d6576..1af5485b3 100644 --- a/apps/client/src/widgets/react/hooks.tsx +++ b/apps/client/src/widgets/react/hooks.tsx @@ -1,7 +1,9 @@ -import { useContext, useEffect, useRef } from "preact/hooks"; +import { type Dispatch, type StateUpdater, useContext, useEffect, useRef, useState } from "preact/hooks"; import { EventData, EventNames } from "../../components/app_context"; import { ParentComponent } from "./ReactBasicWidget"; import SpacedUpdate from "../../services/spaced_update"; +import { OptionNames } from "@triliumnext/commons"; +import options from "../../services/options"; /** * Allows a React component to react to Trilium events (e.g. `entitiesReloaded`). When the desired event is triggered, the handler is invoked with the event parameters. @@ -63,4 +65,14 @@ export function useSpacedUpdate(callback: () => Promise, interval = 1000) }, [interval]); return spacedUpdateRef.current; +} + +export function useTriliumOption(name: OptionNames): [string, Dispatch>] { + const initialValue = options.get(name); + const [ value, setValue ] = useState(initialValue); + + return [ + value, + setValue + ] } \ No newline at end of file diff --git a/apps/client/src/widgets/type_widgets/content_widget.ts b/apps/client/src/widgets/type_widgets/content_widget.tsx similarity index 97% rename from apps/client/src/widgets/type_widgets/content_widget.ts rename to apps/client/src/widgets/type_widgets/content_widget.tsx index 7f1b675bf..badb6860a 100644 --- a/apps/client/src/widgets/type_widgets/content_widget.ts +++ b/apps/client/src/widgets/type_widgets/content_widget.tsx @@ -76,8 +76,8 @@ const TPL = /*html*/`
JSX.Element))> = { - _optionsAppearance: AppearanceSettings, +const CONTENT_WIDGETS: Record = { + _optionsAppearance: , _optionsShortcuts: [ KeyboardShortcutsOptions ], @@ -169,7 +169,7 @@ export default class ContentWidgetTypeWidget extends TypeWidget { this.$content.empty(); this.children = []; - const contentWidgets = (CONTENT_WIDGETS as Record JSX.Element))>)[note.noteId]; + const contentWidgets = (CONTENT_WIDGETS as Record)[note.noteId]; this.$content.toggleClass("options", note.noteId.startsWith("_options")); // Unknown widget. @@ -196,7 +196,7 @@ export default class ContentWidgetTypeWidget extends TypeWidget { } // React widget. - this.$content.append(renderReactWidget(this, contentWidgets())); + this.$content.append(renderReactWidget(this, contentWidgets)); } } diff --git a/apps/client/src/widgets/type_widgets/options/appearance.tsx b/apps/client/src/widgets/type_widgets/options/appearance.tsx index f69af5512..ee95e15b1 100644 --- a/apps/client/src/widgets/type_widgets/options/appearance.tsx +++ b/apps/client/src/widgets/type_widgets/options/appearance.tsx @@ -1,3 +1,33 @@ +import { t } from "../../../services/i18n"; +import FormRadioGroup from "../../react/FormRadioGroup"; +import { useTriliumOption } from "../../react/hooks"; +import OptionsSection from "./components/OptionsSection"; + export default function AppearanceSettings() { - return

Hi

+ const [ layoutOrientation, setLayoutOrientation ] = useTriliumOption("layoutOrientation"); + + return ( + + + {t("theme.layout-vertical-title")} + - {t("theme.layout-vertical-description")} + , + value: "vertical" + }, + { + label: <> + {t("theme.layout-horizontal-title")} + - {t("theme.layout-horizontal-description")} + , + value: "horizontal" + } + ]} + currentValue={layoutOrientation} onChange={setLayoutOrientation} + /> + + ) } \ No newline at end of file diff --git a/apps/client/src/widgets/type_widgets/options/appearance/theme.ts b/apps/client/src/widgets/type_widgets/options/appearance/theme.ts index 9eda867d9..fb98f00e3 100644 --- a/apps/client/src/widgets/type_widgets/options/appearance/theme.ts +++ b/apps/client/src/widgets/type_widgets/options/appearance/theme.ts @@ -5,28 +5,6 @@ import { t } from "../../../../services/i18n.js"; import type { OptionMap } from "@triliumnext/commons"; const TPL = /*html*/` -
-

${t("theme.layout")}

- -
-
- -
- -
- -
-
-
-

${t("theme.title")}

diff --git a/apps/client/src/widgets/type_widgets/options/components/OptionsSection.tsx b/apps/client/src/widgets/type_widgets/options/components/OptionsSection.tsx new file mode 100644 index 000000000..3f54cd6af --- /dev/null +++ b/apps/client/src/widgets/type_widgets/options/components/OptionsSection.tsx @@ -0,0 +1,16 @@ +import type { ComponentChildren } from "preact"; + +interface OptionsSectionProps { + title: string; + children: ComponentChildren; +} + +export default function OptionsSection({ title, children }: OptionsSectionProps) { + return ( +
+

{title}

+ + {children} +
+ ); +}