diff --git a/apps/client/src/widgets/type_widgets/code/Code.tsx b/apps/client/src/widgets/type_widgets/code/Code.tsx index 3121f36ee..e78d86948 100644 --- a/apps/client/src/widgets/type_widgets/code/Code.tsx +++ b/apps/client/src/widgets/type_widgets/code/Code.tsx @@ -1,15 +1,16 @@ import { useEffect, useRef, useState } from "preact/hooks"; -import { default as VanillaCodeMirror } from "@triliumnext/codemirror"; +import { getThemeById, default as VanillaCodeMirror } from "@triliumnext/codemirror"; import { TypeWidgetProps } from "../type_widget"; import "./code.css"; import CodeMirror, { CodeMirrorProps } from "./CodeMirror"; import utils from "../../../services/utils"; -import { useEditorSpacedUpdate, useNoteBlob, useSyncedRef, useTriliumOptionBool } from "../../react/hooks"; +import { useEditorSpacedUpdate, useNoteBlob, useSyncedRef, useTriliumEvent, useTriliumOption, useTriliumOptionBool } from "../../react/hooks"; import { t } from "../../../services/i18n"; import appContext from "../../../components/app_context"; import TouchBar, { TouchBarButton } from "../../react/TouchBar"; import keyboard_actions from "../../../services/keyboard_actions"; import { refToJQuerySelector } from "../../react/react_utils"; +import { CODE_THEME_DEFAULT_PREFIX as DEFAULT_PREFIX } from "../constants"; export function ReadOnlyCode({ note, viewScope, ntxId, parentComponent }: TypeWidgetProps) { const [ content, setContent ] = useState(""); @@ -24,12 +25,11 @@ export function ReadOnlyCode({ note, viewScope, ntxId, parentComponent }: TypeWi return (
) @@ -63,10 +63,9 @@ export function EditableCode({ note, ntxId, debounceUpdate, parentComponent }: T return (
& Pick) { +function CodeEditor({ note, parentComponent, ntxId, containerRef: externalContainerRef, editorRef: externalEditorRef, ...editorProps }: Omit & Pick) { + const codeEditorRef = useRef(null); const containerRef = useSyncedRef(externalContainerRef); + const initialized = useRef($.Deferred()); + const [ codeLineWrapEnabled ] = useTriliumOptionBool("codeLineWrapEnabled"); + const [ codeNoteTheme ] = useTriliumOption("codeNoteTheme"); // React to background color. const [ backgroundColor, setBackgroundColor ] = useState(); @@ -100,14 +103,47 @@ function CodeEditor({ note, parentComponent, containerRef: externalContainerRef, }; }, [ backgroundColor ]); + // React to theme changes. + useEffect(() => { + if (codeEditorRef.current && codeNoteTheme.startsWith(DEFAULT_PREFIX)) { + const theme = getThemeById(codeNoteTheme.substring(DEFAULT_PREFIX.length)); + if (theme) { + codeEditorRef.current.setTheme(theme).then(() => { + if (note?.mime === "text/x-sqlite;schema=trilium") return; + const editor = containerRef.current?.querySelector(".cm-editor"); + if (!editor) return; + const style = window.getComputedStyle(editor); + setBackgroundColor(style.backgroundColor); + }); + } + } + }, [ codeEditorRef, codeNoteTheme ]); + + useTriliumEvent("executeWithCodeEditor", async ({ resolve, ntxId: eventNtxId }) => { + if (eventNtxId !== ntxId) return; + await initialized.current.promise(); + resolve(codeEditorRef.current!); + }); + + useTriliumEvent("executeWithContentElement", async ({ resolve, ntxId: eventNtxId}) => { + if (eventNtxId !== ntxId) return; + await initialized.current.promise(); + resolve(refToJQuerySelector(containerRef)); + }); + return { - const editor = containerRef.current?.querySelector(".cm-editor"); - if (!editor) return; - const style = window.getComputedStyle(editor); - setBackgroundColor(style.backgroundColor); - } : undefined} + lineWrapping={codeLineWrapEnabled} + onInitialized={() => { + if (externalContainerRef && containerRef.current) { + externalContainerRef.current = containerRef.current; + } + if (externalEditorRef && codeEditorRef.current) { + externalEditorRef.current = codeEditorRef.current; + } + initialized.current.resolve(); + }} /> } diff --git a/apps/client/src/widgets/type_widgets/code/CodeMirror.tsx b/apps/client/src/widgets/type_widgets/code/CodeMirror.tsx index 9f6097fd3..f1b94a887 100644 --- a/apps/client/src/widgets/type_widgets/code/CodeMirror.tsx +++ b/apps/client/src/widgets/type_widgets/code/CodeMirror.tsx @@ -1,39 +1,20 @@ import { useEffect, useRef } from "preact/hooks"; -import { EditorConfig, getThemeById, default as VanillaCodeMirror } from "@triliumnext/codemirror"; -import { useSyncedRef, useTriliumEvent, useTriliumOption, useTriliumOptionBool } from "../../react/hooks"; -import { refToJQuerySelector } from "../../react/react_utils"; +import { EditorConfig, default as VanillaCodeMirror } from "@triliumnext/codemirror"; +import { useSyncedRef } from "../../react/hooks"; import { RefObject } from "preact"; -import { CODE_THEME_DEFAULT_PREFIX as DEFAULT_PREFIX } from "../constants"; export interface CodeMirrorProps extends Omit { content: string; mime: string; className?: string; - ntxId: string | null | undefined; editorRef?: RefObject; containerRef?: RefObject; - onThemeChange?: () => void; + onInitialized?: () => void; } -export default function CodeMirror({ className, content, mime, ntxId, editorRef: externalEditorRef, containerRef: externalContainerRef, onThemeChange, ...extraOpts }: CodeMirrorProps) { +export default function CodeMirror({ className, content, mime, editorRef: externalEditorRef, containerRef: externalContainerRef, onInitialized, ...extraOpts }: CodeMirrorProps) { const parentRef = useSyncedRef(externalContainerRef); const codeEditorRef = useRef(); - const [ codeLineWrapEnabled ] = useTriliumOptionBool("codeLineWrapEnabled"); - const [ codeNoteTheme ] = useTriliumOption("codeNoteTheme"); - const initialized = $.Deferred(); - - // Integration within Trilium's event system. - useTriliumEvent("executeWithCodeEditor", async ({ resolve, ntxId: eventNtxId }) => { - if (eventNtxId !== ntxId) return; - await initialized.promise(); - resolve(codeEditorRef.current!); - }); - - useTriliumEvent("executeWithContentElement", async ({ resolve, ntxId: eventNtxId}) => { - if (eventNtxId !== ntxId) return; - await initialized.promise(); - resolve(refToJQuerySelector(parentRef)); - }); // Create CodeMirror instance. useEffect(() => { @@ -41,30 +22,17 @@ export default function CodeMirror({ className, content, mime, ntxId, editorRef: const codeEditor = new VanillaCodeMirror({ parent: parentRef.current, - lineWrapping: codeLineWrapEnabled, ...extraOpts }); codeEditorRef.current = codeEditor; if (externalEditorRef) { externalEditorRef.current = codeEditor; } - initialized.resolve(); + onInitialized?.(); return () => codeEditor.destroy(); }, []); - // React to theme changes. - useEffect(() => { - if (codeEditorRef.current && codeNoteTheme.startsWith(DEFAULT_PREFIX)) { - const theme = getThemeById(codeNoteTheme.substring(DEFAULT_PREFIX.length)); - if (theme) { - codeEditorRef.current.setTheme(theme).then(() => { - onThemeChange?.(); - }); - } - } - }, [ codeEditorRef, codeNoteTheme ]); - // React to text changes. useEffect(() => { const codeEditor = codeEditorRef.current;