diff --git a/apps/client/src/components/note_context.ts b/apps/client/src/components/note_context.ts index fd33c94ae..c9261f38e 100644 --- a/apps/client/src/components/note_context.ts +++ b/apps/client/src/components/note_context.ts @@ -12,6 +12,7 @@ import server from "../services/server.js"; import treeService from "../services/tree.js"; import utils from "../services/utils.js"; import { ReactWrappedWidget } from "../widgets/basic_widget.js"; +import type { HeadingContext } from "../widgets/sidebar/TableOfContents.js"; import appContext, { type EventData, type EventListener } from "./app_context.js"; import Component from "./component.js"; @@ -22,6 +23,12 @@ export interface SetNoteOpts { export type GetTextEditorCallback = (editor: CKTextEditor) => void; +export interface NoteContextDataMap { + toc: HeadingContext; +} + +type ContextDataKey = keyof NoteContextDataMap; + class NoteContext extends Component implements EventListener<"entitiesReloaded"> { ntxId: string | null; hoistedNoteId: string; @@ -469,8 +476,9 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded"> * @param key - Unique identifier for the data type (e.g., "toc", "pdfPages", "codeOutline") * @param value - The data to store (will be cleared when switching notes) */ - setContextData(key: string, value: T): void { + setContextData(key: K, value: NoteContextDataMap[K]): void { this.contextData.set(key, value); + console.trace("Set context data", key, value); // Trigger event so subscribers can react this.triggerEvent("contextDataChanged", { noteContext: this, @@ -485,21 +493,21 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded"> * @param key - The data key to retrieve * @returns The stored data, or undefined if not found */ - getContextData(key: string): T | undefined { - return this.contextData.get(key) as T | undefined; + getContextData(key: K): NoteContextDataMap[K] | undefined { + return this.contextData.get(key) as NoteContextDataMap[K] | undefined; } /** * Check if context data exists for a given key. */ - hasContextData(key: string): boolean { + hasContextData(key: ContextDataKey): boolean { return this.contextData.has(key); } /** * Clear specific context data. */ - clearContextData(key: string): void { + clearContextData(key: ContextDataKey): void { this.contextData.delete(key); this.triggerEvent("contextDataChanged", { noteContext: this, diff --git a/apps/client/src/widgets/sidebar/TableOfContents.tsx b/apps/client/src/widgets/sidebar/TableOfContents.tsx index 42dc7f781..97bceaab0 100644 --- a/apps/client/src/widgets/sidebar/TableOfContents.tsx +++ b/apps/client/src/widgets/sidebar/TableOfContents.tsx @@ -21,6 +21,11 @@ interface HeadingsWithNesting extends RawHeading { children: HeadingsWithNesting[]; } +export interface HeadingContext { + // scrollToHeading(heading: RawHeading): void; + headings: RawHeading[]; +} + export default function TableOfContents() { const { note, noteContext } = useActiveNoteContext(); const noteType = useNoteProperty(note, "type"); @@ -38,6 +43,7 @@ export default function TableOfContents() { function PdfTableOfContents() { const data = useGetContextData("toc"); + console.log("Rendering with data", data); return (
{JSON.stringify(data, null, 2)}
diff --git a/apps/client/src/widgets/type_widgets/file/Pdf.tsx b/apps/client/src/widgets/type_widgets/file/Pdf.tsx index 7f405b42e..5d68d403f 100644 --- a/apps/client/src/widgets/type_widgets/file/Pdf.tsx +++ b/apps/client/src/widgets/type_widgets/file/Pdf.tsx @@ -39,10 +39,13 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: { if (event.data.type === "pdfjs-viewer-toc") { if (event.data.data) { - noteContext.setContextData("toc", event.data.data); + // Convert PDF outline to HeadingContext format + noteContext.setContextData("toc", { + headings: convertPdfOutlineToHeadings(event.data.data) + }); } else { - // No ToC available, fallback to note title - noteContext.setContextData("toc", note.title); + // No ToC available, use empty headings + noteContext.setContextData("toc", { headings: [] }); } } } @@ -60,8 +63,6 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: { } }, [ blob ]); - // Initial ToC is set to note.title, will be replaced by actual ToC when received - useSetContextData(noteContext, "toc", note.title); return (historyConfig &&