mirror of
https://github.com/zadam/trilium.git
synced 2025-11-11 00:49:00 +01:00
refactor(react/type_widgets): separate persistence from canvas
Some checks failed
Checks / main (push) Has been cancelled
Some checks failed
Checks / main (push) Has been cancelled
This commit is contained in:
parent
0b740bb007
commit
319e28387f
@ -118,7 +118,7 @@ export const TYPE_MAPPINGS: Record<ExtendedNoteType, NoteTypeMapping> = {
|
|||||||
printable: true
|
printable: true
|
||||||
},
|
},
|
||||||
canvas: {
|
canvas: {
|
||||||
view: () => import("./type_widgets/Canvas"),
|
view: () => import("./type_widgets/canvas/Canvas"),
|
||||||
className: "note-detail-canvas",
|
className: "note-detail-canvas",
|
||||||
printable: true,
|
printable: true,
|
||||||
isFullHeight: true
|
isFullHeight: true
|
||||||
|
|||||||
73
apps/client/src/widgets/type_widgets/canvas/Canvas.tsx
Normal file
73
apps/client/src/widgets/type_widgets/canvas/Canvas.tsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { Excalidraw } from "@excalidraw/excalidraw";
|
||||||
|
import { TypeWidgetProps } from "../type_widget";
|
||||||
|
import "@excalidraw/excalidraw/index.css";
|
||||||
|
import { useNoteLabelBoolean } from "../../react/hooks";
|
||||||
|
import { useCallback, useMemo, useRef } from "preact/hooks";
|
||||||
|
import { type ExcalidrawImperativeAPI, type AppState } from "@excalidraw/excalidraw/types";
|
||||||
|
import options from "../../../services/options";
|
||||||
|
import "./Canvas.css";
|
||||||
|
import { NonDeletedExcalidrawElement } from "@excalidraw/excalidraw/element/types";
|
||||||
|
import { goToLinkExt } from "../../../services/link";
|
||||||
|
import useCanvasPersistence from "./persistence";
|
||||||
|
|
||||||
|
// currently required by excalidraw, in order to allows self-hosting fonts locally.
|
||||||
|
// this avoids making excalidraw load the fonts from an external CDN.
|
||||||
|
window.EXCALIDRAW_ASSET_PATH = `${window.location.pathname}/node_modules/@excalidraw/excalidraw/dist/prod`;
|
||||||
|
|
||||||
|
export default function Canvas({ note, noteContext }: TypeWidgetProps) {
|
||||||
|
const apiRef = useRef<ExcalidrawImperativeAPI>(null);
|
||||||
|
const [ isReadOnly ] = useNoteLabelBoolean(note, "readOnly");
|
||||||
|
const themeStyle = useMemo(() => {
|
||||||
|
const documentStyle = window.getComputedStyle(document.documentElement);
|
||||||
|
return documentStyle.getPropertyValue("--theme-style")?.trim() as AppState["theme"];
|
||||||
|
}, []);
|
||||||
|
const persistence = useCanvasPersistence(note, noteContext, apiRef, themeStyle, isReadOnly);
|
||||||
|
|
||||||
|
/** Use excalidraw's native zoom instead of the global zoom. */
|
||||||
|
const onWheel = useCallback((e: MouseEvent) => {
|
||||||
|
if (e.ctrlKey) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onLinkOpen = useCallback((element: NonDeletedExcalidrawElement, event: CustomEvent) => {
|
||||||
|
let link = element.link;
|
||||||
|
if (!link) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (link.startsWith("root/")) {
|
||||||
|
link = "#" + link;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { nativeEvent } = event.detail;
|
||||||
|
event.preventDefault();
|
||||||
|
return goToLinkExt(nativeEvent, link, null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="canvas-render" onWheel={onWheel}>
|
||||||
|
<div className="excalidraw-wrapper">
|
||||||
|
<Excalidraw
|
||||||
|
excalidrawAPI={api => apiRef.current = api}
|
||||||
|
theme={themeStyle}
|
||||||
|
viewModeEnabled={isReadOnly || options.is("databaseReadonly")}
|
||||||
|
zenModeEnabled={false}
|
||||||
|
isCollaborating={false}
|
||||||
|
detectScroll={false}
|
||||||
|
handleKeyboardGlobally={false}
|
||||||
|
autoFocus={false}
|
||||||
|
UIOptions={{
|
||||||
|
canvasActions: {
|
||||||
|
saveToActiveFile: false,
|
||||||
|
export: false
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onLinkOpen={onLinkOpen}
|
||||||
|
{...persistence}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,92 +1,25 @@
|
|||||||
import { Excalidraw, exportToSvg, getSceneVersion } from "@excalidraw/excalidraw";
|
|
||||||
import { TypeWidgetProps } from "./type_widget";
|
|
||||||
import "@excalidraw/excalidraw/index.css";
|
|
||||||
import { useEditorSpacedUpdate, useNoteLabelBoolean } from "../react/hooks";
|
|
||||||
import { useCallback, useMemo, useRef } from "preact/hooks";
|
|
||||||
import { type ExcalidrawImperativeAPI, type AppState, type BinaryFileData, LibraryItem, ExcalidrawProps } from "@excalidraw/excalidraw/types";
|
|
||||||
import options from "../../services/options";
|
|
||||||
import "./Canvas.css";
|
|
||||||
import FNote from "../../entities/fnote";
|
|
||||||
import { RefObject } from "preact";
|
import { RefObject } from "preact";
|
||||||
import server from "../../services/server";
|
import NoteContext from "../../../components/note_context";
|
||||||
|
import FNote from "../../../entities/fnote";
|
||||||
|
import { AppState, BinaryFileData, ExcalidrawImperativeAPI, ExcalidrawProps, LibraryItem } from "@excalidraw/excalidraw/types";
|
||||||
|
import { useRef } from "preact/hooks";
|
||||||
|
import { useEditorSpacedUpdate } from "../../react/hooks";
|
||||||
import { ExcalidrawElement, NonDeletedExcalidrawElement } from "@excalidraw/excalidraw/element/types";
|
import { ExcalidrawElement, NonDeletedExcalidrawElement } from "@excalidraw/excalidraw/element/types";
|
||||||
import { goToLinkExt } from "../../services/link";
|
import { exportToSvg, getSceneVersion } from "@excalidraw/excalidraw";
|
||||||
import NoteContext from "../../components/note_context";
|
import server from "../../../services/server";
|
||||||
|
|
||||||
// currently required by excalidraw, in order to allows self-hosting fonts locally.
|
|
||||||
// this avoids making excalidraw load the fonts from an external CDN.
|
|
||||||
window.EXCALIDRAW_ASSET_PATH = `${window.location.pathname}/node_modules/@excalidraw/excalidraw/dist/prod`;
|
|
||||||
|
|
||||||
interface AttachmentMetadata {
|
interface AttachmentMetadata {
|
||||||
title: string;
|
title: string;
|
||||||
attachmentId: string;
|
attachmentId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CanvasContent {
|
export interface CanvasContent {
|
||||||
elements: ExcalidrawElement[];
|
elements: ExcalidrawElement[];
|
||||||
files: BinaryFileData[];
|
files: BinaryFileData[];
|
||||||
appState: Partial<AppState>;
|
appState: Partial<AppState>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Canvas({ note, noteContext }: TypeWidgetProps) {
|
export default function useCanvasPersistence(note: FNote, noteContext: NoteContext | null | undefined, apiRef: RefObject<ExcalidrawImperativeAPI>, theme: AppState["theme"], isReadOnly: boolean): Partial<ExcalidrawProps> {
|
||||||
const apiRef = useRef<ExcalidrawImperativeAPI>(null);
|
|
||||||
const [ isReadOnly ] = useNoteLabelBoolean(note, "readOnly");
|
|
||||||
const themeStyle = useMemo(() => {
|
|
||||||
const documentStyle = window.getComputedStyle(document.documentElement);
|
|
||||||
return documentStyle.getPropertyValue("--theme-style")?.trim() as AppState["theme"];
|
|
||||||
}, []);
|
|
||||||
const persistence = usePersistence(note, noteContext, apiRef, themeStyle, isReadOnly);
|
|
||||||
|
|
||||||
/** Use excalidraw's native zoom instead of the global zoom. */
|
|
||||||
const onWheel = useCallback((e: MouseEvent) => {
|
|
||||||
if (e.ctrlKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onLinkOpen = useCallback((element: NonDeletedExcalidrawElement, event: CustomEvent) => {
|
|
||||||
let link = element.link;
|
|
||||||
if (!link) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (link.startsWith("root/")) {
|
|
||||||
link = "#" + link;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { nativeEvent } = event.detail;
|
|
||||||
event.preventDefault();
|
|
||||||
return goToLinkExt(nativeEvent, link, null);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="canvas-render" onWheel={onWheel}>
|
|
||||||
<div className="excalidraw-wrapper">
|
|
||||||
<Excalidraw
|
|
||||||
excalidrawAPI={api => apiRef.current = api}
|
|
||||||
theme={themeStyle}
|
|
||||||
viewModeEnabled={isReadOnly || options.is("databaseReadonly")}
|
|
||||||
zenModeEnabled={false}
|
|
||||||
isCollaborating={false}
|
|
||||||
detectScroll={false}
|
|
||||||
handleKeyboardGlobally={false}
|
|
||||||
autoFocus={false}
|
|
||||||
UIOptions={{
|
|
||||||
canvasActions: {
|
|
||||||
saveToActiveFile: false,
|
|
||||||
export: false
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onLinkOpen={onLinkOpen}
|
|
||||||
{...persistence}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function usePersistence(note: FNote, noteContext: NoteContext | null | undefined, apiRef: RefObject<ExcalidrawImperativeAPI>, theme: AppState["theme"], isReadOnly: boolean): Partial<ExcalidrawProps> {
|
|
||||||
const libraryChanged = useRef(false);
|
const libraryChanged = useRef(false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Loading…
x
Reference in New Issue
Block a user