chore(react/launch_bar): port custom widget

This commit is contained in:
Elian Doran 2025-12-04 17:55:38 +02:00
parent b7d7fc8b67
commit 604488b166
No known key found for this signature in database
3 changed files with 42 additions and 6 deletions

View File

@ -11,10 +11,10 @@ import ProtectedSessionStatusWidget from "../launch_bar/ProtectedSessionStatusWi
import { VNode } from "preact"; import { VNode } from "preact";
import { CommandButton, CustomNoteLauncher, NoteLauncher } from "../launch_bar/GenericButtons.jsx"; import { CommandButton, CustomNoteLauncher, NoteLauncher } from "../launch_bar/GenericButtons.jsx";
import date_notes from "../../services/date_notes.js"; import date_notes from "../../services/date_notes.js";
import { useLegacyWidget } from "../react/hooks.jsx"; import { useLegacyWidget, useNoteContext, useNoteRelation, useNoteRelationTarget } from "../react/hooks.jsx";
import QuickSearchWidget from "../quick_search.js"; import QuickSearchWidget from "../quick_search.js";
import { ParentComponent } from "../react/react_utils.jsx"; import { ParentComponent } from "../react/react_utils.jsx";
import { useContext } from "preact/hooks"; import { useContext, useEffect, useMemo, useState } from "preact/hooks";
import { LaunchBarActionButton, useLauncherIconAndTitle } from "../launch_bar/launch_bar_widgets.jsx"; import { LaunchBarActionButton, useLauncherIconAndTitle } from "../launch_bar/launch_bar_widgets.jsx";
interface InnerWidget extends BasicWidget { interface InnerWidget extends BasicWidget {
@ -64,7 +64,7 @@ export default class LauncherWidget extends BasicWidget {
} else if (launcherType === "script") { } else if (launcherType === "script") {
widget = wrapReactWidgets<BasicWidget>([ <ScriptLauncher launcherNote={note} /> ])[0]; widget = wrapReactWidgets<BasicWidget>([ <ScriptLauncher launcherNote={note} /> ])[0];
} else if (launcherType === "customWidget") { } else if (launcherType === "customWidget") {
widget = await this.initCustomWidget(note); widget = wrapReactWidgets<BasicWidget>([ <CustomWidget launcherNote={note} /> ])[0];
} else if (launcherType === "builtinWidget") { } else if (launcherType === "builtinWidget") {
widget = wrapReactWidgets<BasicWidget>([ this.initBuiltinWidget(note) ])[0]; widget = wrapReactWidgets<BasicWidget>([ this.initBuiltinWidget(note) ])[0];
} else { } else {
@ -160,14 +160,39 @@ function TodayLauncher({ launcherNote }: { launcherNote: FNote }) {
} }
function QuickSearchLauncherWidget({ isHorizontalLayout }: { isHorizontalLayout: boolean }) { function QuickSearchLauncherWidget({ isHorizontalLayout }: { isHorizontalLayout: boolean }) {
const [ widgetEl ] = useLegacyWidget(() => new QuickSearchWidget()); const widget = useMemo(() => new QuickSearchWidget(), []);
const parentComponent = useContext(ParentComponent) as BasicWidget | null; const parentComponent = useContext(ParentComponent) as BasicWidget | null;
const isEnabled = isHorizontalLayout && !isMobile(); const isEnabled = isHorizontalLayout && !isMobile();
parentComponent?.contentSized(); parentComponent?.contentSized();
return ( return (
<div> <div>
{isEnabled && widgetEl} {isEnabled && <LegacyWidgetRenderer widget={widget} />}
</div> </div>
) )
} }
function CustomWidget({ launcherNote }: { launcherNote: FNote }) {
const [ widgetNote ] = useNoteRelationTarget(launcherNote, "widget");
const [ widget, setWidget ] = useState<BasicWidget>();
const parentComponent = useContext(ParentComponent) as BasicWidget | null;
parentComponent?.contentSized();
useEffect(() => {
widgetNote?.executeScript().then(setWidget);
}, [ widgetNote ]);
return (
<div>
{widget && <LegacyWidgetRenderer widget={widget} />}
</div>
)
}
function LegacyWidgetRenderer({ widget }: { widget: BasicWidget }) {
const { noteContext } = useNoteContext();
const [ widgetEl ] = useLegacyWidget(() => widget, {
noteContext
});
return widgetEl;
}

View File

@ -370,6 +370,16 @@ export function useNoteRelation(note: FNote | undefined | null, relationName: Re
] as const; ] as const;
} }
export function useNoteRelationTarget(note: FNote, relationName: RelationNames) {
const [ targetNote, setTargetNote ] = useState<FNote | null>();
useEffect(() => {
note.getRelationTarget(relationName).then(setTargetNote);
}, [ note ]);
return [ targetNote ] as const;
}
/** /**
* Allows a React component to read or write a note's label while also reacting to changes in value. * Allows a React component to read or write a note's label while also reacting to changes in value.
* *

View File

@ -62,7 +62,8 @@ type Relations = [
"ancestor", "ancestor",
// Launcher-specific // Launcher-specific
"target" "target",
"widget"
]; ];
export type LabelNames = keyof Labels; export type LabelNames = keyof Labels;