mirror of
https://github.com/zadam/trilium.git
synced 2025-12-20 22:34:23 +01:00
feat(toc): basic support for docs
This commit is contained in:
parent
b93c80fe7b
commit
704dcd011e
@ -1,40 +1,41 @@
|
|||||||
import froca from "../services/froca.js";
|
|
||||||
import RootCommandExecutor from "./root_command_executor.js";
|
|
||||||
import Entrypoints from "./entrypoints.js";
|
|
||||||
import options from "../services/options.js";
|
|
||||||
import utils, { hasTouchBar } from "../services/utils.js";
|
|
||||||
import zoomComponent from "./zoom.js";
|
|
||||||
import TabManager from "./tab_manager.js";
|
|
||||||
import Component from "./component.js";
|
|
||||||
import keyboardActionsService from "../services/keyboard_actions.js";
|
|
||||||
import linkService, { type ViewScope } from "../services/link.js";
|
|
||||||
import MobileScreenSwitcherExecutor, { type Screen } from "./mobile_screen_switcher.js";
|
|
||||||
import MainTreeExecutors from "./main_tree_executors.js";
|
|
||||||
import toast from "../services/toast.js";
|
|
||||||
import ShortcutComponent from "./shortcut_component.js";
|
|
||||||
import { t, initLocale } from "../services/i18n.js";
|
|
||||||
import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js";
|
|
||||||
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
|
|
||||||
import type { ConfirmWithMessageOptions, ConfirmWithTitleOptions } from "../widgets/dialogs/confirm.js";
|
|
||||||
import type LoadResults from "../services/load_results.js";
|
|
||||||
import type { Attribute } from "../services/attribute_parser.js";
|
|
||||||
import type NoteTreeWidget from "../widgets/note_tree.js";
|
|
||||||
import type { default as NoteContext, GetTextEditorCallback } from "./note_context.js";
|
|
||||||
import type { NativeImage, TouchBar } from "electron";
|
|
||||||
import TouchBarComponent from "./touch_bar.js";
|
|
||||||
import type { CKTextEditor } from "@triliumnext/ckeditor5";
|
import type { CKTextEditor } from "@triliumnext/ckeditor5";
|
||||||
import type CodeMirror from "@triliumnext/codemirror";
|
import type CodeMirror from "@triliumnext/codemirror";
|
||||||
import { StartupChecks } from "./startup_checks.js";
|
|
||||||
import type { CreateNoteOpts } from "../services/note_create.js";
|
|
||||||
import { ColumnComponent } from "tabulator-tables";
|
|
||||||
import { ChooseNoteTypeCallback } from "../widgets/dialogs/note_type_chooser.jsx";
|
|
||||||
import type RootContainer from "../widgets/containers/root_container.js";
|
|
||||||
import { SqlExecuteResults } from "@triliumnext/commons";
|
import { SqlExecuteResults } from "@triliumnext/commons";
|
||||||
import { AddLinkOpts } from "../widgets/dialogs/add_link.jsx";
|
import type { NativeImage, TouchBar } from "electron";
|
||||||
import { IncludeNoteOpts } from "../widgets/dialogs/include_note.jsx";
|
import { ColumnComponent } from "tabulator-tables";
|
||||||
|
|
||||||
|
import type { Attribute } from "../services/attribute_parser.js";
|
||||||
|
import froca from "../services/froca.js";
|
||||||
|
import { initLocale,t } from "../services/i18n.js";
|
||||||
|
import keyboardActionsService from "../services/keyboard_actions.js";
|
||||||
|
import linkService, { type ViewScope } from "../services/link.js";
|
||||||
|
import type LoadResults from "../services/load_results.js";
|
||||||
|
import type { CreateNoteOpts } from "../services/note_create.js";
|
||||||
|
import options from "../services/options.js";
|
||||||
|
import toast from "../services/toast.js";
|
||||||
|
import utils, { hasTouchBar } from "../services/utils.js";
|
||||||
import { ReactWrappedWidget } from "../widgets/basic_widget.js";
|
import { ReactWrappedWidget } from "../widgets/basic_widget.js";
|
||||||
import type { MarkdownImportOpts } from "../widgets/dialogs/markdown_import.jsx";
|
import type RootContainer from "../widgets/containers/root_container.js";
|
||||||
|
import { AddLinkOpts } from "../widgets/dialogs/add_link.jsx";
|
||||||
|
import type { ConfirmWithMessageOptions, ConfirmWithTitleOptions } from "../widgets/dialogs/confirm.js";
|
||||||
|
import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js";
|
||||||
|
import { IncludeNoteOpts } from "../widgets/dialogs/include_note.jsx";
|
||||||
import type { InfoProps } from "../widgets/dialogs/info.jsx";
|
import type { InfoProps } from "../widgets/dialogs/info.jsx";
|
||||||
|
import type { MarkdownImportOpts } from "../widgets/dialogs/markdown_import.jsx";
|
||||||
|
import { ChooseNoteTypeCallback } from "../widgets/dialogs/note_type_chooser.jsx";
|
||||||
|
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
|
||||||
|
import type NoteTreeWidget from "../widgets/note_tree.js";
|
||||||
|
import Component from "./component.js";
|
||||||
|
import Entrypoints from "./entrypoints.js";
|
||||||
|
import MainTreeExecutors from "./main_tree_executors.js";
|
||||||
|
import MobileScreenSwitcherExecutor, { type Screen } from "./mobile_screen_switcher.js";
|
||||||
|
import type { default as NoteContext, GetTextEditorCallback } from "./note_context.js";
|
||||||
|
import RootCommandExecutor from "./root_command_executor.js";
|
||||||
|
import ShortcutComponent from "./shortcut_component.js";
|
||||||
|
import { StartupChecks } from "./startup_checks.js";
|
||||||
|
import TabManager from "./tab_manager.js";
|
||||||
|
import TouchBarComponent from "./touch_bar.js";
|
||||||
|
import zoomComponent from "./zoom.js";
|
||||||
|
|
||||||
interface Layout {
|
interface Layout {
|
||||||
getRootWidget: (appContext: AppContext) => RootContainer;
|
getRootWidget: (appContext: AppContext) => RootContainer;
|
||||||
@ -447,6 +448,7 @@ type EventMappings = {
|
|||||||
};
|
};
|
||||||
searchRefreshed: { ntxId?: string | null };
|
searchRefreshed: { ntxId?: string | null };
|
||||||
textEditorRefreshed: { ntxId?: string | null, editor: CKTextEditor };
|
textEditorRefreshed: { ntxId?: string | null, editor: CKTextEditor };
|
||||||
|
contentElRefreshed: { ntxId?: string | null, contentEl: HTMLElement };
|
||||||
hoistedNoteChanged: {
|
hoistedNoteChanged: {
|
||||||
noteId: string;
|
noteId: string;
|
||||||
ntxId: string | null;
|
ntxId: string | null;
|
||||||
@ -695,10 +697,8 @@ $(window).on("beforeunload", () => {
|
|||||||
console.log(`Component ${component.componentId} is not finished saving its state.`);
|
console.log(`Component ${component.componentId} is not finished saving its state.`);
|
||||||
allSaved = false;
|
allSaved = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!listener()) {
|
||||||
if (!listener()) {
|
allSaved = false;
|
||||||
allSaved = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,7 +708,7 @@ $(window).on("beforeunload", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(window).on("hashchange", function () {
|
$(window).on("hashchange", () => {
|
||||||
const { notePath, ntxId, viewScope, searchString } = linkService.parseNavigationStateFromUrl(window.location.href);
|
const { notePath, ntxId, viewScope, searchString } = linkService.parseNavigationStateFromUrl(window.location.href);
|
||||||
|
|
||||||
if (notePath || ntxId) {
|
if (notePath || ntxId) {
|
||||||
|
|||||||
@ -1119,6 +1119,7 @@ export function useTextEditor(noteContext: NoteContext | null | undefined) {
|
|||||||
export function useContentElement(noteContext: NoteContext | null | undefined) {
|
export function useContentElement(noteContext: NoteContext | null | undefined) {
|
||||||
const [ contentElement, setContentElement ] = useState<HTMLElement | null>(null);
|
const [ contentElement, setContentElement ] = useState<HTMLElement | null>(null);
|
||||||
const requestIdRef = useRef(0);
|
const requestIdRef = useRef(0);
|
||||||
|
const [, forceUpdate] = useState(0);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const requestId = ++requestIdRef.current;
|
const requestId = ++requestIdRef.current;
|
||||||
@ -1126,8 +1127,16 @@ export function useContentElement(noteContext: NoteContext | null | undefined) {
|
|||||||
// Prevent stale async.
|
// Prevent stale async.
|
||||||
if (requestId !== requestIdRef.current) return;
|
if (requestId !== requestIdRef.current) return;
|
||||||
setContentElement(contentElement?.[0] ?? null);
|
setContentElement(contentElement?.[0] ?? null);
|
||||||
|
forceUpdate(v => v + 1);
|
||||||
});
|
});
|
||||||
}, [ noteContext ]);
|
}, [ noteContext ]);
|
||||||
|
|
||||||
|
// React to content changes initializing.
|
||||||
|
useTriliumEvent("contentElRefreshed", ({ ntxId: eventNtxId, contentEl }) => {
|
||||||
|
if (eventNtxId !== noteContext?.ntxId) return;
|
||||||
|
setContentElement(contentEl);
|
||||||
|
forceUpdate(v => v + 1);
|
||||||
|
});
|
||||||
|
|
||||||
return contentElement;
|
return contentElement;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,9 +27,8 @@ export default function TableOfContents() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RightPanelWidget title={t("toc.table_of_contents")}>
|
<RightPanelWidget title={t("toc.table_of_contents")}>
|
||||||
{noteType === "text" && (
|
{((noteType === "text" && isReadOnly) || (noteType === "doc")) && <ReadOnlyTextTableOfContents />}
|
||||||
isReadOnly ? <ReadOnlyTextTableOfContents /> : <EditableTextTableOfContents />
|
{noteType === "text" && !isReadOnly && <EditableTextTableOfContents />}
|
||||||
)}
|
|
||||||
</RightPanelWidget>
|
</RightPanelWidget>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import { useEffect, useRef, useState } from "preact/hooks";
|
|
||||||
import { RawHtmlBlock } from "../react/RawHtml";
|
|
||||||
import renderDoc from "../../services/doc_renderer";
|
|
||||||
import "./Doc.css";
|
import "./Doc.css";
|
||||||
import { TypeWidgetProps } from "./type_widget";
|
|
||||||
|
import { useEffect, useRef } from "preact/hooks";
|
||||||
|
|
||||||
|
import appContext from "../../components/app_context";
|
||||||
|
import renderDoc from "../../services/doc_renderer";
|
||||||
import { useTriliumEvent } from "../react/hooks";
|
import { useTriliumEvent } from "../react/hooks";
|
||||||
import { refToJQuerySelector } from "../react/react_utils";
|
import { refToJQuerySelector } from "../react/react_utils";
|
||||||
|
import { TypeWidgetProps } from "./type_widget";
|
||||||
|
|
||||||
export default function Doc({ note, viewScope, ntxId }: TypeWidgetProps) {
|
export default function Doc({ note, viewScope, ntxId }: TypeWidgetProps) {
|
||||||
const initialized = useRef<Promise<void> | null>(null);
|
const initialized = useRef<Promise<void> | null>(null);
|
||||||
@ -14,9 +16,11 @@ export default function Doc({ note, viewScope, ntxId }: TypeWidgetProps) {
|
|||||||
if (!note) return;
|
if (!note) return;
|
||||||
|
|
||||||
initialized.current = renderDoc(note).then($content => {
|
initialized.current = renderDoc(note).then($content => {
|
||||||
containerRef.current?.replaceChildren(...$content);
|
if (!containerRef.current) return;
|
||||||
|
containerRef.current.replaceChildren(...$content);
|
||||||
|
appContext.triggerEvent("contentElRefreshed", { ntxId, contentEl: containerRef.current });
|
||||||
});
|
});
|
||||||
}, [ note ]);
|
}, [ note, ntxId ]);
|
||||||
|
|
||||||
useTriliumEvent("executeWithContentElement", async ({ resolve, ntxId: eventNtxId}) => {
|
useTriliumEvent("executeWithContentElement", async ({ resolve, ntxId: eventNtxId}) => {
|
||||||
if (eventNtxId !== ntxId) return;
|
if (eventNtxId !== ntxId) return;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user