chore(client/right_pane): inject title into PDF toc sidebar

This commit is contained in:
Elian Doran 2025-12-29 21:28:17 +02:00
parent 9098bfb63a
commit 257f6c5994
No known key found for this signature in database
4 changed files with 23 additions and 6 deletions

View File

@ -57,13 +57,16 @@ export default function RightPanelContainer({ widgetsByParent }: { widgetsByPare
function useItems(rightPaneVisible: boolean, widgetsByParent: WidgetsByParent) { function useItems(rightPaneVisible: boolean, widgetsByParent: WidgetsByParent) {
const { note } = useActiveNoteContext(); const { note } = useActiveNoteContext();
const noteType = useNoteProperty(note, "type"); const noteType = useNoteProperty(note, "type");
const noteMime = useNoteProperty(note, "mime");
const [ highlightsList ] = useTriliumOptionJson<string[]>("highlightsList"); const [ highlightsList ] = useTriliumOptionJson<string[]>("highlightsList");
if (!rightPaneVisible) return []; if (!rightPaneVisible) return [];
const definitions: RightPanelWidgetDefinition[] = [ const definitions: RightPanelWidgetDefinition[] = [
{ {
el: <TableOfContents />, el: <TableOfContents />,
enabled: (noteType === "text" || noteType === "doc"), enabled: (noteType === "text"
|| noteType === "doc"
|| (noteType === "file" && noteMime === "application/pdf")),
}, },
{ {
el: <HighlightsList />, el: <HighlightsList />,

View File

@ -6,7 +6,7 @@ import { useCallback, useEffect, useState } from "preact/hooks";
import { t } from "../../services/i18n"; import { t } from "../../services/i18n";
import { randomString } from "../../services/utils"; import { randomString } from "../../services/utils";
import { useActiveNoteContext, useContentElement, useIsNoteReadOnly, useNoteProperty, useTextEditor } from "../react/hooks"; import { useActiveNoteContext, useContentElement, useGetContextData, useIsNoteReadOnly, useNoteProperty, useTextEditor } from "../react/hooks";
import Icon from "../react/Icon"; import Icon from "../react/Icon";
import RightPanelWidget from "./RightPanelWidget"; import RightPanelWidget from "./RightPanelWidget";
@ -24,16 +24,26 @@ interface HeadingsWithNesting extends RawHeading {
export default function TableOfContents() { export default function TableOfContents() {
const { note, noteContext } = useActiveNoteContext(); const { note, noteContext } = useActiveNoteContext();
const noteType = useNoteProperty(note, "type"); const noteType = useNoteProperty(note, "type");
const noteMime = useNoteProperty(note, "mime");
const { isReadOnly } = useIsNoteReadOnly(note, noteContext); const { isReadOnly } = useIsNoteReadOnly(note, noteContext);
return ( return (
<RightPanelWidget id="toc" title={t("toc.table_of_contents")} grow> <RightPanelWidget id="toc" title={t("toc.table_of_contents")} grow>
{((noteType === "text" && isReadOnly) || (noteType === "doc")) && <ReadOnlyTextTableOfContents />} {((noteType === "text" && isReadOnly) || (noteType === "doc")) && <ReadOnlyTextTableOfContents />}
{noteType === "text" && !isReadOnly && <EditableTextTableOfContents />} {noteType === "text" && !isReadOnly && <EditableTextTableOfContents />}
{noteType === "file" && noteMime === "application/pdf" && <PdfTableOfContents />}
</RightPanelWidget> </RightPanelWidget>
); );
} }
function PdfTableOfContents() {
const data = useGetContextData("toc");
return (
<pre>{JSON.stringify(data, null, 2)}</pre>
);
}
function AbstractTableOfContents<T extends RawHeading>({ headings, scrollToHeading }: { function AbstractTableOfContents<T extends RawHeading>({ headings, scrollToHeading }: {
headings: T[]; headings: T[];
scrollToHeading(heading: T): void; scrollToHeading(heading: T): void;

View File

@ -10,13 +10,13 @@ import { TypeWidgetProps } from "./type_widget";
const TEXT_MAX_NUM_CHARS = 5000; const TEXT_MAX_NUM_CHARS = 5000;
export default function FileTypeWidget({ note, parentComponent }: TypeWidgetProps) { export default function FileTypeWidget({ note, parentComponent, noteContext }: TypeWidgetProps) {
const blob = useNoteBlob(note, parentComponent?.componentId); const blob = useNoteBlob(note, parentComponent?.componentId);
if (blob?.content) { if (blob?.content) {
return <TextPreview content={blob.content} />; return <TextPreview content={blob.content} />;
} else if (note.mime === "application/pdf") { } else if (note.mime === "application/pdf") {
return <PdfPreview blob={blob} note={note} componentId={parentComponent?.componentId} />; return <PdfPreview blob={blob} note={note} componentId={parentComponent?.componentId} noteContext={noteContext} />;
} else if (note.mime.startsWith("video/")) { } else if (note.mime.startsWith("video/")) {
return <VideoPreview note={note} />; return <VideoPreview note={note} />;
} else if (note.mime.startsWith("audio/")) { } else if (note.mime.startsWith("audio/")) {

View File

@ -1,11 +1,12 @@
import { RefObject } from "preact"; import { RefObject } from "preact";
import { useCallback, useEffect, useRef } from "preact/hooks"; import { useCallback, useEffect, useRef } from "preact/hooks";
import type NoteContext from "../../../components/note_context";
import FBlob from "../../../entities/fblob"; import FBlob from "../../../entities/fblob";
import FNote from "../../../entities/fnote"; import FNote from "../../../entities/fnote";
import server from "../../../services/server"; import server from "../../../services/server";
import { useViewModeConfig } from "../../collections/NoteList"; import { useViewModeConfig } from "../../collections/NoteList";
import { useTriliumOption } from "../../react/hooks"; import { useSetContextData, useTriliumOption } from "../../react/hooks";
const VARIABLE_WHITELIST = new Set([ const VARIABLE_WHITELIST = new Set([
"root-background", "root-background",
@ -14,8 +15,9 @@ const VARIABLE_WHITELIST = new Set([
"main-text-color" "main-text-color"
]); ]);
export default function PdfPreview({ note, blob, componentId }: { export default function PdfPreview({ note, blob, componentId, noteContext }: {
note: FNote, note: FNote,
noteContext: NoteContext
blob: FBlob | null | undefined, blob: FBlob | null | undefined,
componentId: string | undefined; componentId: string | undefined;
}) { }) {
@ -49,6 +51,8 @@ export default function PdfPreview({ note, blob, componentId }: {
} }
}, [ blob ]); }, [ blob ]);
useSetContextData(noteContext, "toc", note.title);
return (historyConfig && return (historyConfig &&
<iframe <iframe
ref={iframeRef} ref={iframeRef}