feat(right_pane): render title bar

This commit is contained in:
Elian Doran 2025-12-20 10:33:28 +02:00
parent 8f1614f603
commit aac4316fb8
No known key found for this signature in database
3 changed files with 51 additions and 16 deletions

View File

@ -605,10 +605,11 @@ export function useNoteBlob(note: FNote | null | undefined, componentId?: string
return blob;
}
export function useLegacyWidget<T extends BasicWidget>(widgetFactory: () => T, { noteContext, containerClassName, containerStyle }: {
export function useLegacyWidget<T extends BasicWidget>(widgetFactory: () => T, { noteContext, containerClassName, containerStyle, noAttach }: {
noteContext?: NoteContext;
containerClassName?: string;
containerStyle?: CSSProperties;
noAttach?: boolean;
} = {}): [VNode, T] {
const ref = useRef<HTMLDivElement>(null);
const parentComponent = useContext(ParentComponent);
@ -627,22 +628,24 @@ export function useLegacyWidget<T extends BasicWidget>(widgetFactory: () => T, {
const renderedWidget = widget.render();
return [ widget, renderedWidget ];
}, []);
}, [ noteContext, parentComponent, widgetFactory]);
// Attach the widget to the parent.
useEffect(() => {
if (ref.current) {
ref.current.innerHTML = "";
renderedWidget.appendTo(ref.current);
if (noAttach) return;
const parentContainer = ref.current;
if (parentContainer) {
parentContainer.replaceChildren();
renderedWidget.appendTo(parentContainer);
}
}, [ renderedWidget ]);
}, [ renderedWidget, noAttach ]);
// Inject the note context.
useEffect(() => {
if (noteContext && widget instanceof NoteContextAwareWidget) {
widget.activeContextChangedEvent({ noteContext });
}
}, [ noteContext ]);
}, [ noteContext, widget ]);
useDebugValue(widget);

View File

@ -2,7 +2,7 @@
import "./RightPanelContainer.css";
import Split from "@triliumnext/split.js";
import { useEffect } from "preact/hooks";
import { useEffect, useRef } from "preact/hooks";
import { t } from "../../services/i18n";
import options from "../../services/options";
@ -11,7 +11,9 @@ import BasicWidget from "../basic_widget";
import Button from "../react/Button";
import { useActiveNoteContext, useLegacyWidget, useNoteProperty, useTriliumOptionBool, useTriliumOptionJson } from "../react/hooks";
import Icon from "../react/Icon";
import LegacyRightPanelWidget from "../right_panel_widget";
import HighlightsList from "./HighlightsList";
import RightPanelWidget from "./RightPanelWidget";
import TableOfContents from "./TableOfContents";
const MIN_WIDTH_PERCENT = 5;
@ -67,7 +69,36 @@ function useSplit(visible: boolean) {
}, [ visible ]);
}
function CustomWidget({ originalWidget }: { originalWidget: BasicWidget }) {
const [ el ] = useLegacyWidget(() => originalWidget);
return <>{el}</>;
function CustomWidget({ originalWidget }: { originalWidget: LegacyRightPanelWidget }) {
const containerRef = useRef<HTMLDivElement>(null);
const [ el ] = useLegacyWidget(() => {
// Monkey-patch the original widget by replacing the default initialization logic.
originalWidget.doRender = function doRender(this: LegacyRightPanelWidget) {
if (!containerRef.current) {
this.$widget = $("<div>");
return;
};
this.$widget = $(containerRef.current);
this.$body = this.$widget.find(".card-body");
const renderResult = this.doRenderBody();
if (typeof renderResult === "object" && "catch" in renderResult) {
this.initialized = renderResult.catch((e) => {
this.logRenderingError(e);
});
} else {
this.initialized = Promise.resolve();
}
};
return originalWidget;
}, {
noAttach: true
});
return (
<RightPanelWidget
id={originalWidget._noteId}
title={originalWidget.widgetTitle}
containerRef={containerRef}
>{el}</RightPanelWidget>
);
}

View File

@ -1,8 +1,8 @@
import clsx from "clsx";
import { ComponentChildren } from "preact";
import { useContext, useRef, useState } from "preact/hooks";
import { ComponentChildren, RefObject } from "preact";
import { useContext, useState } from "preact/hooks";
import { useTriliumOptionJson } from "../react/hooks";
import { useSyncedRef, useTriliumOptionJson } from "../react/hooks";
import Icon from "../react/Icon";
import { ParentComponent } from "../react/react_utils";
@ -11,12 +11,13 @@ interface RightPanelWidgetProps {
title: string;
children: ComponentChildren;
buttons?: ComponentChildren;
containerRef?: RefObject<HTMLDivElement>;
}
export default function RightPanelWidget({ id, title, buttons, children }: RightPanelWidgetProps) {
export default function RightPanelWidget({ id, title, buttons, children, containerRef: externalContainerRef }: RightPanelWidgetProps) {
const [ rightPaneCollapsedItems, setRightPaneCollapsedItems ] = useTriliumOptionJson<string[]>("rightPaneCollapsedItems");
const [ expanded, setExpanded ] = useState(!rightPaneCollapsedItems.includes(id));
const containerRef = useRef<HTMLDivElement>(null);
const containerRef = useSyncedRef<HTMLDivElement>(externalContainerRef, null);
const parentComponent = useContext(ParentComponent);
if (parentComponent) {