mirror of
https://github.com/zadam/trilium.git
synced 2025-12-06 15:34:26 +01:00
chore(react/launch_bar): port launcher container & launcher
This commit is contained in:
parent
caaa3583a7
commit
d511085db3
@ -10,7 +10,6 @@ import FlexContainer from "../widgets/containers/flex_container.js";
|
|||||||
import FloatingButtons from "../widgets/FloatingButtons.jsx";
|
import FloatingButtons from "../widgets/FloatingButtons.jsx";
|
||||||
import GlobalMenu from "../widgets/buttons/global_menu.jsx";
|
import GlobalMenu from "../widgets/buttons/global_menu.jsx";
|
||||||
import HighlightsListWidget from "../widgets/highlights_list.js";
|
import HighlightsListWidget from "../widgets/highlights_list.js";
|
||||||
import LauncherContainer from "../widgets/containers/launcher_container.js";
|
|
||||||
import LeftPaneContainer from "../widgets/containers/left_pane_container.js";
|
import LeftPaneContainer from "../widgets/containers/left_pane_container.js";
|
||||||
import LeftPaneToggle from "../widgets/buttons/left_pane_toggle.js";
|
import LeftPaneToggle from "../widgets/buttons/left_pane_toggle.js";
|
||||||
import MovePaneButton from "../widgets/buttons/move_pane_button.js";
|
import MovePaneButton from "../widgets/buttons/move_pane_button.js";
|
||||||
@ -44,6 +43,7 @@ import WatchedFileUpdateStatusWidget from "../widgets/watched_file_update_status
|
|||||||
import NoteDetail from "../widgets/NoteDetail.jsx";
|
import NoteDetail from "../widgets/NoteDetail.jsx";
|
||||||
import PromotedAttributes from "../widgets/PromotedAttributes.jsx";
|
import PromotedAttributes from "../widgets/PromotedAttributes.jsx";
|
||||||
import SpacerWidget from "../widgets/launch_bar/SpacerWidget.jsx";
|
import SpacerWidget from "../widgets/launch_bar/SpacerWidget.jsx";
|
||||||
|
import LauncherContainer from "../widgets/launch_bar/LauncherContainer.jsx";
|
||||||
|
|
||||||
export default class DesktopLayout {
|
export default class DesktopLayout {
|
||||||
|
|
||||||
@ -184,14 +184,14 @@ export default class DesktopLayout {
|
|||||||
launcherPane = new FlexContainer("row")
|
launcherPane = new FlexContainer("row")
|
||||||
.css("height", "53px")
|
.css("height", "53px")
|
||||||
.class("horizontal")
|
.class("horizontal")
|
||||||
.child(new LauncherContainer(true))
|
.child(<LauncherContainer isHorizontalLayout={true} />)
|
||||||
.child(<GlobalMenu isHorizontalLayout={true} />);
|
.child(<GlobalMenu isHorizontalLayout={true} />);
|
||||||
} else {
|
} else {
|
||||||
launcherPane = new FlexContainer("column")
|
launcherPane = new FlexContainer("column")
|
||||||
.css("width", "53px")
|
.css("width", "53px")
|
||||||
.class("vertical")
|
.class("vertical")
|
||||||
.child(<GlobalMenu isHorizontalLayout={false} />)
|
.child(<GlobalMenu isHorizontalLayout={false} />)
|
||||||
.child(new LauncherContainer(false))
|
.child(<LauncherContainer isHorizontalLayout={false} />)
|
||||||
.child(<LeftPaneToggle isHorizontalLayout={false} />);
|
.child(<LeftPaneToggle isHorizontalLayout={false} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import FilePropertiesTab from "../widgets/ribbon/FilePropertiesTab.jsx";
|
|||||||
import FlexContainer from "../widgets/containers/flex_container.js";
|
import FlexContainer from "../widgets/containers/flex_container.js";
|
||||||
import FloatingButtons from "../widgets/FloatingButtons.jsx";
|
import FloatingButtons from "../widgets/FloatingButtons.jsx";
|
||||||
import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
|
import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
|
||||||
import LauncherContainer from "../widgets/containers/launcher_container.js";
|
|
||||||
import MobileDetailMenu from "../widgets/mobile_widgets/mobile_detail_menu.js";
|
import MobileDetailMenu from "../widgets/mobile_widgets/mobile_detail_menu.js";
|
||||||
import NoteList from "../widgets/collections/NoteList.jsx";
|
import NoteList from "../widgets/collections/NoteList.jsx";
|
||||||
import NoteTitleWidget from "../widgets/note_title.js";
|
import NoteTitleWidget from "../widgets/note_title.js";
|
||||||
@ -30,6 +29,7 @@ import NoteDetail from "../widgets/NoteDetail.jsx";
|
|||||||
import MobileEditorToolbar from "../widgets/type_widgets/text/mobile_editor_toolbar.jsx";
|
import MobileEditorToolbar from "../widgets/type_widgets/text/mobile_editor_toolbar.jsx";
|
||||||
import PromotedAttributes from "../widgets/PromotedAttributes.jsx";
|
import PromotedAttributes from "../widgets/PromotedAttributes.jsx";
|
||||||
import SplitNoteContainer from "../widgets/containers/split_note_container.js";
|
import SplitNoteContainer from "../widgets/containers/split_note_container.js";
|
||||||
|
import LauncherContainer from "../widgets/launch_bar/LauncherContainer.jsx";
|
||||||
|
|
||||||
const MOBILE_CSS = `
|
const MOBILE_CSS = `
|
||||||
<style>
|
<style>
|
||||||
@ -183,7 +183,7 @@ export default class MobileLayout {
|
|||||||
.child(new FlexContainer("row")
|
.child(new FlexContainer("row")
|
||||||
.class("horizontal")
|
.class("horizontal")
|
||||||
.css("height", "53px")
|
.css("height", "53px")
|
||||||
.child(new LauncherContainer(true))
|
.child(<LauncherContainer isHorizontalLayout />)
|
||||||
.child(<GlobalMenuWidget isHorizontalLayout />)
|
.child(<GlobalMenuWidget isHorizontalLayout />)
|
||||||
.id("launcher-pane"))
|
.id("launcher-pane"))
|
||||||
)
|
)
|
||||||
|
|||||||
@ -236,7 +236,7 @@ export function isIOS() {
|
|||||||
return /iPad|iPhone|iPod/.test(navigator.userAgent);
|
return /iPad|iPhone|iPod/.test(navigator.userAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isDesktop() {
|
export function isDesktop() {
|
||||||
return (
|
return (
|
||||||
window.glob?.device === "desktop" ||
|
window.glob?.device === "desktop" ||
|
||||||
// window.glob.device is not available in setup
|
// window.glob.device is not available in setup
|
||||||
|
|||||||
@ -1,198 +0,0 @@
|
|||||||
import BasicWidget, { wrapReactWidgets } from "../basic_widget.js";
|
|
||||||
import utils, { isMobile } from "../../services/utils.js";
|
|
||||||
import type FNote from "../../entities/fnote.js";
|
|
||||||
import BookmarkButtons from "../launch_bar/BookmarkButtons.jsx";
|
|
||||||
import SpacerWidget from "../launch_bar/SpacerWidget.jsx";
|
|
||||||
import HistoryNavigationButton from "../launch_bar/HistoryNavigation.jsx";
|
|
||||||
import AiChatButton from "../launch_bar/AiChatButton.jsx";
|
|
||||||
import ProtectedSessionStatusWidget from "../launch_bar/ProtectedSessionStatusWidget.jsx";
|
|
||||||
import { VNode } from "preact";
|
|
||||||
import { CommandButton, CustomNoteLauncher, NoteLauncher } from "../launch_bar/GenericButtons.jsx";
|
|
||||||
import date_notes from "../../services/date_notes.js";
|
|
||||||
import { useLegacyWidget, useNoteContext, useNoteRelation, useNoteRelationTarget } from "../react/hooks.jsx";
|
|
||||||
import QuickSearchWidget from "../quick_search.js";
|
|
||||||
import { ParentComponent } from "../react/react_utils.jsx";
|
|
||||||
import { useContext, useEffect, useMemo, useState } from "preact/hooks";
|
|
||||||
import { LaunchBarActionButton, useLauncherIconAndTitle } from "../launch_bar/launch_bar_widgets.jsx";
|
|
||||||
import CalendarWidget from "../launch_bar/CalendarWidget.jsx";
|
|
||||||
import SyncStatus from "../launch_bar/SyncStatus.jsx";
|
|
||||||
|
|
||||||
interface InnerWidget extends BasicWidget {
|
|
||||||
settings?: {
|
|
||||||
titlePlacement: "bottom";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class LauncherWidget extends BasicWidget {
|
|
||||||
private innerWidget!: InnerWidget;
|
|
||||||
private isHorizontalLayout: boolean;
|
|
||||||
|
|
||||||
constructor(isHorizontalLayout: boolean) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.isHorizontalLayout = isHorizontalLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
isEnabled() {
|
|
||||||
return this.innerWidget.isEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
doRender() {
|
|
||||||
this.$widget = this.innerWidget.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
async initLauncher(note: FNote) {
|
|
||||||
if (note.type !== "launcher") {
|
|
||||||
throw new Error(`Note '${note.noteId}' '${note.title}' is not a launcher even though it's in the launcher subtree`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!utils.isDesktop() && note.isLabelTruthy("desktopOnly")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const launcherType = note.getLabelValue("launcherType");
|
|
||||||
|
|
||||||
if (glob.TRILIUM_SAFE_MODE && launcherType === "customWidget") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let widget: BasicWidget | VNode;
|
|
||||||
if (launcherType === "command") {
|
|
||||||
widget = wrapReactWidgets<BasicWidget>([ <CommandButton launcherNote={note} /> ])[0];
|
|
||||||
} else if (launcherType === "note") {
|
|
||||||
widget = wrapReactWidgets<BasicWidget>([ <NoteLauncher launcherNote={note} /> ])[0];
|
|
||||||
} else if (launcherType === "script") {
|
|
||||||
widget = wrapReactWidgets<BasicWidget>([ <ScriptLauncher launcherNote={note} /> ])[0];
|
|
||||||
} else if (launcherType === "customWidget") {
|
|
||||||
widget = wrapReactWidgets<BasicWidget>([ <CustomWidget launcherNote={note} /> ])[0];
|
|
||||||
} else if (launcherType === "builtinWidget") {
|
|
||||||
widget = wrapReactWidgets<BasicWidget>([ this.initBuiltinWidget(note) ])[0];
|
|
||||||
} else {
|
|
||||||
throw new Error(`Unrecognized launcher type '${launcherType}' for launcher '${note.noteId}' title '${note.title}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!widget) {
|
|
||||||
throw new Error(`Unknown initialization error for note '${note.noteId}', title '${note.title}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.child(widget);
|
|
||||||
this.innerWidget = widget as InnerWidget;
|
|
||||||
if (this.isHorizontalLayout && this.innerWidget.settings) {
|
|
||||||
this.innerWidget.settings.titlePlacement = "bottom";
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async initCustomWidget(note: FNote) {
|
|
||||||
const widget = await note.getRelationTarget("widget");
|
|
||||||
|
|
||||||
if (widget) {
|
|
||||||
return await widget.executeScript();
|
|
||||||
} else {
|
|
||||||
throw new Error(`Custom widget of launcher '${note.noteId}' '${note.title}' is not defined.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
initBuiltinWidget(note: FNote) {
|
|
||||||
const builtinWidget = note.getLabelValue("builtinWidget");
|
|
||||||
switch (builtinWidget) {
|
|
||||||
case "calendar":
|
|
||||||
return <CalendarWidget launcherNote={note} />
|
|
||||||
case "spacer":
|
|
||||||
// || has to be inside since 0 is a valid value
|
|
||||||
const baseSize = parseInt(note.getLabelValue("baseSize") || "40");
|
|
||||||
const growthFactor = parseInt(note.getLabelValue("growthFactor") || "100");
|
|
||||||
|
|
||||||
return <SpacerWidget baseSize={baseSize} growthFactor={growthFactor} />;
|
|
||||||
case "bookmarks":
|
|
||||||
return <BookmarkButtons isHorizontalLayout={this.isHorizontalLayout} />;
|
|
||||||
case "protectedSession":
|
|
||||||
return <ProtectedSessionStatusWidget />;
|
|
||||||
case "syncStatus":
|
|
||||||
return <SyncStatus />;
|
|
||||||
case "backInHistoryButton":
|
|
||||||
return <HistoryNavigationButton launcherNote={note} command="backInNoteHistory" />
|
|
||||||
case "forwardInHistoryButton":
|
|
||||||
return <HistoryNavigationButton launcherNote={note} command="forwardInNoteHistory" />
|
|
||||||
case "todayInJournal":
|
|
||||||
return <TodayLauncher launcherNote={note} />
|
|
||||||
case "quickSearch":
|
|
||||||
return <QuickSearchLauncherWidget isHorizontalLayout={this.isHorizontalLayout} />
|
|
||||||
case "aiChatLauncher":
|
|
||||||
return <AiChatButton launcherNote={note} />
|
|
||||||
default:
|
|
||||||
throw new Error(`Unrecognized builtin widget ${builtinWidget} for launcher ${note.noteId} "${note.title}"`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ScriptLauncher({ launcherNote }: { launcherNote: FNote }) {
|
|
||||||
const { icon, title } = useLauncherIconAndTitle(launcherNote);
|
|
||||||
return (
|
|
||||||
<LaunchBarActionButton
|
|
||||||
icon={icon}
|
|
||||||
text={title}
|
|
||||||
onClick={async () => {
|
|
||||||
if (launcherNote.isLabelTruthy("scriptInLauncherContent")) {
|
|
||||||
await launcherNote.executeScript();
|
|
||||||
} else {
|
|
||||||
const script = await launcherNote.getRelationTarget("script");
|
|
||||||
if (script) {
|
|
||||||
await script.executeScript();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function TodayLauncher({ launcherNote }: { launcherNote: FNote }) {
|
|
||||||
return (
|
|
||||||
<CustomNoteLauncher
|
|
||||||
launcherNote={launcherNote}
|
|
||||||
getTargetNoteId={async () => {
|
|
||||||
const todayNote = await date_notes.getTodayNote();
|
|
||||||
return todayNote?.noteId ?? null;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function QuickSearchLauncherWidget({ isHorizontalLayout }: { isHorizontalLayout: boolean }) {
|
|
||||||
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>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
import FlexContainer from "./flex_container.js";
|
|
||||||
import froca from "../../services/froca.js";
|
|
||||||
import appContext, { type EventData } from "../../components/app_context.js";
|
|
||||||
import LauncherWidget from "./launcher.js";
|
|
||||||
import utils from "../../services/utils.js";
|
|
||||||
|
|
||||||
export default class LauncherContainer extends FlexContainer<LauncherWidget> {
|
|
||||||
private isHorizontalLayout: boolean;
|
|
||||||
|
|
||||||
constructor(isHorizontalLayout: boolean) {
|
|
||||||
super(isHorizontalLayout ? "row" : "column");
|
|
||||||
|
|
||||||
this.id("launcher-container");
|
|
||||||
this.filling();
|
|
||||||
this.isHorizontalLayout = isHorizontalLayout;
|
|
||||||
|
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
async load() {
|
|
||||||
await froca.initializedPromise;
|
|
||||||
|
|
||||||
const visibleLaunchersRootId = utils.isMobile() ? "_lbMobileVisibleLaunchers" : "_lbVisibleLaunchers";
|
|
||||||
const visibleLaunchersRoot = await froca.getNote(visibleLaunchersRootId, true);
|
|
||||||
|
|
||||||
if (!visibleLaunchersRoot) {
|
|
||||||
console.log("Visible launchers root note doesn't exist.");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newChildren: LauncherWidget[] = [];
|
|
||||||
|
|
||||||
for (const launcherNote of await visibleLaunchersRoot.getChildNotes()) {
|
|
||||||
try {
|
|
||||||
const launcherWidget = new LauncherWidget(this.isHorizontalLayout);
|
|
||||||
const success = await launcherWidget.initLauncher(launcherNote);
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
newChildren.push(launcherWidget);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.children = [];
|
|
||||||
this.child(...newChildren);
|
|
||||||
|
|
||||||
this.$widget.empty();
|
|
||||||
this.renderChildren();
|
|
||||||
|
|
||||||
await this.handleEventInChildren("initialRenderComplete", {});
|
|
||||||
|
|
||||||
const activeContext = appContext.tabManager.getActiveContext();
|
|
||||||
|
|
||||||
if (activeContext) {
|
|
||||||
await this.handleEvent("setNoteContext", {
|
|
||||||
noteContext: activeContext
|
|
||||||
});
|
|
||||||
|
|
||||||
if (activeContext.notePath) {
|
|
||||||
await this.handleEvent("noteSwitched", {
|
|
||||||
noteContext: activeContext,
|
|
||||||
notePath: activeContext.notePath
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
|
|
||||||
if (loadResults.getBranchRows().find((branch) => branch.parentNoteId && froca.getNoteFromCache(branch.parentNoteId)?.isLaunchBarConfig())) {
|
|
||||||
// changes in note placement require reload of all launchers, all other changes are handled by individual
|
|
||||||
// launchers
|
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
120
apps/client/src/widgets/launch_bar/LauncherContainer.tsx
Normal file
120
apps/client/src/widgets/launch_bar/LauncherContainer.tsx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
import { useLayoutEffect, useState } from "preact/hooks";
|
||||||
|
import FNote from "../../entities/fnote";
|
||||||
|
import froca from "../../services/froca";
|
||||||
|
import { isDesktop, isMobile } from "../../services/utils";
|
||||||
|
import CalendarWidget from "./CalendarWidget";
|
||||||
|
import SpacerWidget from "./SpacerWidget";
|
||||||
|
import BookmarkButtons from "./BookmarkButtons";
|
||||||
|
import ProtectedSessionStatusWidget from "./ProtectedSessionStatusWidget";
|
||||||
|
import SyncStatus from "./SyncStatus";
|
||||||
|
import HistoryNavigationButton from "./HistoryNavigation";
|
||||||
|
import { CustomWidget, QuickSearchLauncherWidget, ScriptLauncher, TodayLauncher } from "./LauncherDefinitions";
|
||||||
|
import AiChatButton from "./AiChatButton";
|
||||||
|
import { CommandButton, NoteLauncher } from "./GenericButtons";
|
||||||
|
import { useTriliumEvent } from "../react/hooks";
|
||||||
|
|
||||||
|
export default function LauncherContainer({ isHorizontalLayout }: { isHorizontalLayout: boolean }) {
|
||||||
|
const childNotes = useLauncherChildNotes();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="launcher-container"
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexGrow: 1,
|
||||||
|
flexDirection: isHorizontalLayout ? "row" : "column"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{childNotes?.map(childNote => {
|
||||||
|
if (childNote.type !== "launcher") {
|
||||||
|
throw new Error(`Note '${childNote.noteId}' '${childNote.title}' is not a launcher even though it's in the launcher subtree`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isDesktop() && childNote.isLabelTruthy("desktopOnly")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Launcher key={childNote.noteId} note={childNote} isHorizontalLayout={isHorizontalLayout} />
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Launcher({ note, isHorizontalLayout }: { note: FNote, isHorizontalLayout: boolean }) {
|
||||||
|
const launcherType = note.getLabelValue("launcherType");
|
||||||
|
if (glob.TRILIUM_SAFE_MODE && launcherType === "customWidget") return;
|
||||||
|
|
||||||
|
switch (launcherType) {
|
||||||
|
case "command":
|
||||||
|
return <CommandButton launcherNote={note} />;
|
||||||
|
case "note":
|
||||||
|
return <NoteLauncher launcherNote={note} />;
|
||||||
|
case "script":
|
||||||
|
return <ScriptLauncher launcherNote={note} />;
|
||||||
|
case "customWidget":
|
||||||
|
return <CustomWidget launcherNote={note} />;
|
||||||
|
case "builtinWidget":
|
||||||
|
return initBuiltinWidget(note, isHorizontalLayout);
|
||||||
|
default:
|
||||||
|
throw new Error(`Unrecognized launcher type '${launcherType}' for launcher '${note.noteId}' title '${note.title}'`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initBuiltinWidget(note: FNote, isHorizontalLayout: boolean) {
|
||||||
|
const builtinWidget = note.getLabelValue("builtinWidget");
|
||||||
|
switch (builtinWidget) {
|
||||||
|
case "calendar":
|
||||||
|
return <CalendarWidget launcherNote={note} />
|
||||||
|
case "spacer":
|
||||||
|
// || has to be inside since 0 is a valid value
|
||||||
|
const baseSize = parseInt(note.getLabelValue("baseSize") || "40");
|
||||||
|
const growthFactor = parseInt(note.getLabelValue("growthFactor") || "100");
|
||||||
|
|
||||||
|
return <SpacerWidget baseSize={baseSize} growthFactor={growthFactor} />;
|
||||||
|
case "bookmarks":
|
||||||
|
return <BookmarkButtons isHorizontalLayout={isHorizontalLayout} />;
|
||||||
|
case "protectedSession":
|
||||||
|
return <ProtectedSessionStatusWidget />;
|
||||||
|
case "syncStatus":
|
||||||
|
return <SyncStatus />;
|
||||||
|
case "backInHistoryButton":
|
||||||
|
return <HistoryNavigationButton launcherNote={note} command="backInNoteHistory" />
|
||||||
|
case "forwardInHistoryButton":
|
||||||
|
return <HistoryNavigationButton launcherNote={note} command="forwardInNoteHistory" />
|
||||||
|
case "todayInJournal":
|
||||||
|
return <TodayLauncher launcherNote={note} />
|
||||||
|
case "quickSearch":
|
||||||
|
return <QuickSearchLauncherWidget isHorizontalLayout={isHorizontalLayout} />
|
||||||
|
case "aiChatLauncher":
|
||||||
|
return <AiChatButton launcherNote={note} />
|
||||||
|
default:
|
||||||
|
throw new Error(`Unrecognized builtin widget ${builtinWidget} for launcher ${note.noteId} "${note.title}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function useLauncherChildNotes() {
|
||||||
|
const [ visibleLaunchersRoot, setVisibleLaunchersRoot ] = useState<FNote | undefined | null>();
|
||||||
|
const [ childNotes, setChildNotes ] = useState<FNote[]>();
|
||||||
|
|
||||||
|
// Load the root note.
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
const visibleLaunchersRootId = isMobile() ? "_lbMobileVisibleLaunchers" : "_lbVisibleLaunchers";
|
||||||
|
froca.getNote(visibleLaunchersRootId, true).then(setVisibleLaunchersRoot);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Load the children.
|
||||||
|
function refresh() {
|
||||||
|
if (!visibleLaunchersRoot) return;
|
||||||
|
visibleLaunchersRoot.getChildNotes().then(setChildNotes);
|
||||||
|
}
|
||||||
|
useLayoutEffect(refresh, [ visibleLaunchersRoot ]);
|
||||||
|
|
||||||
|
// React to position changes.
|
||||||
|
useTriliumEvent("entitiesReloaded", ({loadResults}) => {
|
||||||
|
if (loadResults.getBranchRows().find((branch) => branch.parentNoteId && froca.getNoteFromCache(branch.parentNoteId)?.isLaunchBarConfig())) {
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return childNotes;
|
||||||
|
}
|
||||||
80
apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx
Normal file
80
apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import { useContext, useEffect, useMemo, useState } from "preact/hooks";
|
||||||
|
import { useLegacyWidget, useNoteContext, useNoteRelationTarget } 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 { isMobile } from "../../services/utils";
|
||||||
|
import date_notes from "../../services/date_notes";
|
||||||
|
import { CustomNoteLauncher } from "./GenericButtons";
|
||||||
|
import { LaunchBarActionButton, useLauncherIconAndTitle } from "./launch_bar_widgets";
|
||||||
|
|
||||||
|
export function ScriptLauncher({ launcherNote }: { launcherNote: FNote }) {
|
||||||
|
const { icon, title } = useLauncherIconAndTitle(launcherNote);
|
||||||
|
return (
|
||||||
|
<LaunchBarActionButton
|
||||||
|
icon={icon}
|
||||||
|
text={title}
|
||||||
|
onClick={async () => {
|
||||||
|
if (launcherNote.isLabelTruthy("scriptInLauncherContent")) {
|
||||||
|
await launcherNote.executeScript();
|
||||||
|
} else {
|
||||||
|
const script = await launcherNote.getRelationTarget("script");
|
||||||
|
if (script) {
|
||||||
|
await script.executeScript();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TodayLauncher({ launcherNote }: { launcherNote: FNote }) {
|
||||||
|
return (
|
||||||
|
<CustomNoteLauncher
|
||||||
|
launcherNote={launcherNote}
|
||||||
|
getTargetNoteId={async () => {
|
||||||
|
const todayNote = await date_notes.getTodayNote();
|
||||||
|
return todayNote?.noteId ?? null;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function QuickSearchLauncherWidget({ isHorizontalLayout }: { isHorizontalLayout: boolean }) {
|
||||||
|
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 }: { 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>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function LegacyWidgetRenderer({ widget }: { widget: BasicWidget }) {
|
||||||
|
const { noteContext } = useNoteContext();
|
||||||
|
const [ widgetEl ] = useLegacyWidget(() => widget, {
|
||||||
|
noteContext
|
||||||
|
});
|
||||||
|
return widgetEl;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user