mirror of
https://github.com/zadam/trilium.git
synced 2025-12-24 08:14:25 +01:00
161 lines
5.7 KiB
TypeScript
161 lines
5.7 KiB
TypeScript
import { useCallback, useContext, useEffect, useMemo, useState } from "preact/hooks";
|
|
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);
|
|
const [ command ] = useNoteLabel(launcherNote, "command");
|
|
|
|
return command && (
|
|
<LaunchBarActionButton
|
|
icon={icon}
|
|
text={title}
|
|
triggerCommand={command as CommandNames}
|
|
/>
|
|
)
|
|
}
|
|
|
|
// we're intentionally displaying the launcher title and icon instead of the target,
|
|
// e.g. you want to make launchers to 2 mermaid diagrams which both have mermaid icon (ok),
|
|
// but on the launchpad you want them distinguishable.
|
|
// for titles, the note titles may follow a different scheme than maybe desirable on the launchpad
|
|
// another reason is the discrepancy between what user sees on the launchpad and in the config (esp. icons).
|
|
// The only downside is more work in setting up the typical case
|
|
// where you actually want to have both title and icon in sync, but for those cases there are bookmarks
|
|
export function NoteLauncher({ launcherNote, ...restProps }: { launcherNote: FNote, hoistedNoteId?: string }) {
|
|
return (
|
|
<CustomNoteLauncher
|
|
launcherNote={launcherNote}
|
|
getTargetNoteId={(launcherNote) => {
|
|
const targetNoteId = launcherNote.getRelationValue("target");
|
|
if (!targetNoteId) {
|
|
dialog.info(t("note_launcher.this_launcher_doesnt_define_target_note"));
|
|
return null;
|
|
}
|
|
return targetNoteId;
|
|
}}
|
|
getHoistedNoteId={launcherNote => launcherNote.getRelationValue("hoistedNote")}
|
|
{...restProps}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export function ScriptLauncher({ launcherNote }: LauncherNoteProps) {
|
|
const { icon, title } = useLauncherIconAndTitle(launcherNote);
|
|
|
|
const launch = useCallback(async () => {
|
|
if (launcherNote.isLabelTruthy("scriptInLauncherContent")) {
|
|
await launcherNote.executeScript();
|
|
} else {
|
|
const script = await launcherNote.getRelationTarget("script");
|
|
if (script) {
|
|
await script.executeScript();
|
|
}
|
|
}
|
|
}, [ launcherNote ]);
|
|
|
|
// Keyboard shortcut.
|
|
const [ shortcut ] = useNoteLabel(launcherNote, "keyboardShortcut");
|
|
useGlobalShortcut(shortcut, launch);
|
|
|
|
return (
|
|
<LaunchBarActionButton
|
|
icon={icon}
|
|
text={title}
|
|
onClick={launch}
|
|
/>
|
|
)
|
|
}
|
|
|
|
export function AiChatButton({ launcherNote }: LauncherNoteProps) {
|
|
const [ aiEnabled ] = useTriliumOptionBool("aiEnabled");
|
|
const { icon, title } = useLauncherIconAndTitle(launcherNote);
|
|
|
|
return aiEnabled && (
|
|
<LaunchBarActionButton
|
|
icon={icon}
|
|
text={title}
|
|
triggerCommand="createAiChat"
|
|
/>
|
|
)
|
|
}
|
|
|
|
export function TodayLauncher({ launcherNote }: LauncherNoteProps) {
|
|
return (
|
|
<CustomNoteLauncher
|
|
launcherNote={launcherNote}
|
|
getTargetNoteId={async () => {
|
|
const todayNote = await date_notes.getTodayNote();
|
|
return todayNote?.noteId ?? null;
|
|
}}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export function QuickSearchLauncherWidget() {
|
|
const { isHorizontalLayout } = useContext(LaunchBarContext);
|
|
const widget = useMemo(() => new QuickSearchWidget(), []);
|
|
const parentComponent = useContext(ParentComponent) as BasicWidget | null;
|
|
const isEnabled = isHorizontalLayout && !isMobile();
|
|
parentComponent?.contentSized();
|
|
|
|
return (
|
|
<div>
|
|
{isEnabled && <LegacyWidgetRenderer widget={widget} />}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function CustomWidget({ launcherNote }: LauncherNoteProps) {
|
|
const [ widgetNote ] = useNoteRelationTarget(launcherNote, "widget");
|
|
const [ widget, setWidget ] = useState<BasicWidget>();
|
|
const parentComponent = useContext(ParentComponent) as BasicWidget | null;
|
|
parentComponent?.contentSized();
|
|
|
|
useEffect(() => {
|
|
(async function() {
|
|
let widget: BasicWidget;
|
|
try {
|
|
widget = await widgetNote?.executeScript();
|
|
} catch (e) {
|
|
toast.showError(t("toast.bundle-error.message", {
|
|
id: widgetNote?.noteId,
|
|
title: widgetNote?.title,
|
|
message: getErrorMessage(e)
|
|
}));
|
|
return;
|
|
}
|
|
|
|
if (widgetNote && widget instanceof BasicWidget) {
|
|
widget._noteId = widgetNote.noteId;
|
|
}
|
|
setWidget(widget);
|
|
})();
|
|
}, [ widgetNote ]);
|
|
|
|
return (
|
|
<div>
|
|
{widget && <LegacyWidgetRenderer widget={widget} />}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function LegacyWidgetRenderer({ widget }: { widget: BasicWidget }) {
|
|
const [ widgetEl ] = useLegacyWidget(() => widget, {
|
|
noteContext: appContext.tabManager.getActiveContext() ?? undefined
|
|
});
|
|
|
|
return widgetEl;
|
|
}
|