diff --git a/apps/client/src/entities/fnote.ts b/apps/client/src/entities/fnote.ts index cd1a8b7a7..5170e0af2 100644 --- a/apps/client/src/entities/fnote.ts +++ b/apps/client/src/entities/fnote.ts @@ -989,6 +989,10 @@ export default class FNote { ); } + isJsx() { + return (this.type === "code" && this.mime === "text/jsx"); + } + /** @returns true if this note is HTML */ isHtml() { return (this.type === "code" || this.type === "file" || this.type === "render") && this.mime === "text/html"; @@ -996,7 +1000,7 @@ export default class FNote { /** @returns JS script environment - either "frontend" or "backend" */ getScriptEnv() { - if (this.isHtml() || (this.isJavaScript() && this.mime.endsWith("env=frontend"))) { + if (this.isHtml() || (this.isJavaScript() && this.mime.endsWith("env=frontend")) || this.isJsx()) { return "frontend"; } @@ -1018,7 +1022,7 @@ export default class FNote { * @returns a promise that resolves when the script has been run. Additionally, for front-end notes, the promise will contain the value that is returned by the script. */ async executeScript() { - if (!this.isJavaScript()) { + if (!(this.isJavaScript() || this.isJsx())) { throw new Error(`Note ${this.noteId} is of type ${this.type} and mime ${this.mime} and thus cannot be executed`); } diff --git a/apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx b/apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx index a0c379b22..908fe0bc0 100644 --- a/apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx +++ b/apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx @@ -1,17 +1,20 @@ import { useCallback, useContext, useEffect, useMemo, useState } from "preact/hooks"; + +import appContext, { CommandNames } from "../../components/app_context"; +import FNote from "../../entities/fnote"; +import date_notes from "../../services/date_notes"; +import dialog from "../../services/dialog"; +import { WidgetDefinition } from "../../services/frontend_script_api_preact"; +import { t } from "../../services/i18n"; +import toast from "../../services/toast"; +import { getErrorMessage, isMobile } from "../../services/utils"; +import BasicWidget from "../basic_widget"; +import NoteContextAwareWidget from "../note_context_aware_widget"; +import QuickSearchWidget from "../quick_search"; import { useGlobalShortcut, useLegacyWidget, useNoteLabel, useNoteRelationTarget, useTriliumOptionBool } from "../react/hooks"; import { ParentComponent } from "../react/react_utils"; -import BasicWidget from "../basic_widget"; -import FNote from "../../entities/fnote"; -import QuickSearchWidget from "../quick_search"; -import { getErrorMessage, isMobile } from "../../services/utils"; -import date_notes from "../../services/date_notes"; import { CustomNoteLauncher } from "./GenericButtons"; import { LaunchBarActionButton, LaunchBarContext, LauncherNoteProps, useLauncherIconAndTitle } from "./launch_bar_widgets"; -import dialog from "../../services/dialog"; -import { t } from "../../services/i18n"; -import appContext, { CommandNames } from "../../components/app_context"; -import toast from "../../services/toast"; export function CommandButton({ launcherNote }: LauncherNoteProps) { const { icon, title } = useLauncherIconAndTitle(launcherNote); @@ -23,7 +26,7 @@ export function CommandButton({ launcherNote }: LauncherNoteProps) { text={title} triggerCommand={command as CommandNames} /> - ) + ); } // we're intentionally displaying the launcher title and icon instead of the target, @@ -75,7 +78,7 @@ export function ScriptLauncher({ launcherNote }: LauncherNoteProps) { text={title} onClick={launch} /> - ) + ); } export function AiChatButton({ launcherNote }: LauncherNoteProps) { @@ -88,7 +91,7 @@ export function AiChatButton({ launcherNote }: LauncherNoteProps) { text={title} triggerCommand="createAiChat" /> - ) + ); } export function TodayLauncher({ launcherNote }: LauncherNoteProps) { @@ -114,12 +117,13 @@ export function QuickSearchLauncherWidget() {
{isEnabled && }
- ) + ); } export function CustomWidget({ launcherNote }: LauncherNoteProps) { const [ widgetNote ] = useNoteRelationTarget(launcherNote, "widget"); - const [ widget, setWidget ] = useState(); + const [ widget, setWidget ] = useState(); + const parentComponent = useContext(ParentComponent) as BasicWidget | null; parentComponent?.contentSized(); @@ -146,9 +150,13 @@ export function CustomWidget({ launcherNote }: LauncherNoteProps) { return (
- {widget && } + {widget && ( + ("type" in widget && widget.type === "preact-widget") + ? + : + )}
- ) + ); } export function LegacyWidgetRenderer({ widget }: { widget: BasicWidget }) { @@ -158,3 +166,8 @@ export function LegacyWidgetRenderer({ widget }: { widget: BasicWidget }) { return widgetEl; } + +function ReactWidgetRenderer({ widget }: { widget: WidgetDefinition }) { + const El = widget.render; + return ; +}