mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-29 02:52:27 +08:00
refactor(deps): use webpack import for canvas
This commit is contained in:
parent
ab65913e52
commit
7d3f506efb
@ -73,7 +73,6 @@ const copy = async () => {
|
||||
}
|
||||
|
||||
const nodeModulesFolder = [
|
||||
"node_modules/@excalidraw/excalidraw/dist/",
|
||||
"node_modules/katex/dist/",
|
||||
"node_modules/dayjs/",
|
||||
"node_modules/boxicons/css/",
|
||||
|
@ -49,7 +49,6 @@ cp "$script_dir/../build/electron-main.js" "$DIR"
|
||||
if [[ -d "$DIR"/node_modules ]]; then
|
||||
# cleanup of useless files in dependencies
|
||||
for d in 'image-q/demo' \
|
||||
'@excalidraw/excalidraw/dist/excalidraw-assets-dev' '@excalidraw/excalidraw/dist/excalidraw.development.js' '@excalidraw/excalidraw/dist/excalidraw-with-preact.development.js' \
|
||||
'mermaid/dist/mermaid.js' \
|
||||
'boxicons/svg' 'boxicons/node_modules/react'/* \
|
||||
'@jimp/plugin-print/fonts' 'jimp/browser' 'jimp/fonts'; do
|
||||
|
33
package-lock.json
generated
33
package-lock.json
generated
@ -16,6 +16,7 @@
|
||||
"@mermaid-js/layout-elk": "0.1.7",
|
||||
"@mind-elixir/node-menu": "1.0.3",
|
||||
"@triliumnext/express-partial-content": "1.0.1",
|
||||
"@types/react-dom": "18.3.1",
|
||||
"archiver": "7.0.1",
|
||||
"async-mutex": "0.5.0",
|
||||
"autocomplete.js": "0.38.1",
|
||||
@ -133,6 +134,7 @@
|
||||
"@types/mime-types": "2.1.4",
|
||||
"@types/multer": "1.4.12",
|
||||
"@types/node": "22.10.7",
|
||||
"@types/react": "18.3.1",
|
||||
"@types/safe-compare": "1.1.2",
|
||||
"@types/sanitize-html": "2.13.0",
|
||||
"@types/sax": "1.2.7",
|
||||
@ -3912,6 +3914,12 @@
|
||||
"undici-types": "~6.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz",
|
||||
"integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/qs": {
|
||||
"version": "6.9.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz",
|
||||
@ -3926,6 +3934,25 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.1.tgz",
|
||||
"integrity": "sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-dom": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
|
||||
"integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/readdir-glob": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.5.tgz",
|
||||
@ -6652,6 +6679,12 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cytoscape": {
|
||||
"version": "3.30.4",
|
||||
"resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.30.4.tgz",
|
||||
|
@ -61,6 +61,7 @@
|
||||
"@mermaid-js/layout-elk": "0.1.7",
|
||||
"@mind-elixir/node-menu": "1.0.3",
|
||||
"@triliumnext/express-partial-content": "1.0.1",
|
||||
"@types/react-dom": "18.3.1",
|
||||
"archiver": "7.0.1",
|
||||
"async-mutex": "0.5.0",
|
||||
"autocomplete.js": "0.38.1",
|
||||
@ -175,6 +176,7 @@
|
||||
"@types/mime-types": "2.1.4",
|
||||
"@types/multer": "1.4.12",
|
||||
"@types/node": "22.10.7",
|
||||
"@types/react": "18.3.1",
|
||||
"@types/safe-compare": "1.1.2",
|
||||
"@types/sanitize-html": "2.13.0",
|
||||
"@types/sax": "1.2.7",
|
||||
|
@ -72,10 +72,6 @@ const MERMAID: Library = {
|
||||
js: ["node_modules/mermaid/dist/mermaid.min.js"]
|
||||
};
|
||||
|
||||
const EXCALIDRAW: Library = {
|
||||
js: ["node_modules/react/umd/react.production.min.js", "node_modules/react-dom/umd/react-dom.production.min.js", "node_modules/@excalidraw/excalidraw/dist/excalidraw.production.min.js"]
|
||||
};
|
||||
|
||||
const MARKJS: Library = {
|
||||
js: ["node_modules/mark.js/dist/jquery.mark.es6.min.js"]
|
||||
};
|
||||
@ -198,7 +194,6 @@ export default {
|
||||
KATEX,
|
||||
WHEEL_ZOOM,
|
||||
MERMAID,
|
||||
EXCALIDRAW,
|
||||
MARKJS,
|
||||
I18NEXT,
|
||||
HIGHLIGHT_JS
|
||||
|
@ -234,7 +234,7 @@ function goToLink(evt: MouseEvent | JQuery.ClickEvent) {
|
||||
return goToLinkExt(evt, hrefLink, $link);
|
||||
}
|
||||
|
||||
function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent, hrefLink: string | undefined, $link: JQuery<HTMLElement> | null) {
|
||||
function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | React.PointerEvent<HTMLCanvasElement>, hrefLink: string | undefined, $link: JQuery<HTMLElement> | null) {
|
||||
if (hrefLink?.startsWith("data:")) {
|
||||
return true;
|
||||
}
|
||||
@ -249,13 +249,10 @@ function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent, hrefLink: string | und
|
||||
const { notePath, viewScope } = parseNavigationStateFromUrl(hrefLink);
|
||||
|
||||
const ctrlKey = utils.isCtrlKey(evt);
|
||||
const isLeftClick = evt.which === 1;
|
||||
const isMiddleClick = evt.which === 2;
|
||||
const isLeftClick = ("which" in evt && evt.which === 1);
|
||||
const isMiddleClick = ("which" in evt && evt.which === 2);
|
||||
const openInNewTab = (isLeftClick && ctrlKey) || isMiddleClick;
|
||||
|
||||
const leftClick = evt.which === 1;
|
||||
const middleClick = evt.which === 2;
|
||||
|
||||
if (notePath) {
|
||||
if (openInNewTab) {
|
||||
appContext.tabManager.openTabWithNoteWithHoisting(notePath, { viewScope });
|
||||
@ -276,7 +273,7 @@ function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent, hrefLink: string | und
|
||||
const withinEditLink = $link?.hasClass("ck-link-actions__preview");
|
||||
const outsideOfCKEditor = !$link || $link.closest("[contenteditable]").length === 0;
|
||||
|
||||
if (openInNewTab || (withinEditLink && (leftClick || middleClick)) || (outsideOfCKEditor && (leftClick || middleClick))) {
|
||||
if (openInNewTab || (withinEditLink && (isLeftClick || isMiddleClick)) || (outsideOfCKEditor && (isLeftClick || isMiddleClick))) {
|
||||
if (hrefLink.toLowerCase().startsWith("http") || hrefLink.startsWith("api/")) {
|
||||
window.open(hrefLink, "_blank");
|
||||
} else if ((hrefLink.toLowerCase().startsWith("file:") || hrefLink.toLowerCase().startsWith("geo:")) && utils.isElectron()) {
|
||||
|
@ -97,7 +97,7 @@ function isMac() {
|
||||
return navigator.platform.indexOf("Mac") > -1;
|
||||
}
|
||||
|
||||
function isCtrlKey(evt: KeyboardEvent | MouseEvent | JQuery.ClickEvent | JQuery.ContextMenuEvent | JQuery.TriggeredEvent) {
|
||||
function isCtrlKey(evt: KeyboardEvent | MouseEvent | JQuery.ClickEvent | JQuery.ContextMenuEvent | JQuery.TriggeredEvent | React.PointerEvent<HTMLCanvasElement>) {
|
||||
return (!isMac() && evt.ctrlKey) || (isMac() && evt.metaKey);
|
||||
}
|
||||
|
||||
|
66
src/public/app/types.d.ts
vendored
66
src/public/app/types.d.ts
vendored
@ -54,72 +54,6 @@ declare global {
|
||||
|
||||
process?: ElectronProcess;
|
||||
glob?: CustomGlobals;
|
||||
React: {
|
||||
createElement(any, any?, any?);
|
||||
Fragment: any;
|
||||
useState({
|
||||
width: undefined,
|
||||
height: undefined
|
||||
});
|
||||
useRef(ref: null);
|
||||
useEffect(cb: () => void, args: unknown[]);
|
||||
useCallback(cb: (el, ev) => void, args: unknown[]);
|
||||
};
|
||||
ReactDOM: {
|
||||
unmountComponentAtNode(el: HTMLElement);
|
||||
createRoot(el: HTMLElement);
|
||||
}
|
||||
ExcalidrawLib: {
|
||||
getSceneVersion(el: unknown[]): number;
|
||||
exportToSvg(opts: {
|
||||
elements: ExcalidrawElement[],
|
||||
appState: ExcalidrawAppState,
|
||||
exportPadding: number,
|
||||
metadata: string,
|
||||
files: ExcalidrawElement[]
|
||||
}): Promise<HTMLElement>;
|
||||
updateScene,
|
||||
Excalidraw: unknown
|
||||
}
|
||||
EXCALIDRAW_ASSET_PATH: string;
|
||||
}
|
||||
|
||||
interface ExcalidrawApi {
|
||||
getSceneElements(): ExcalidrawElement[];
|
||||
getAppState(): ExcalidrawAppState;
|
||||
getFiles(): ExcalidrawElement[];
|
||||
updateScene(scene: ExcalidrawScene);
|
||||
updateLibrary(opts: { libraryItems?: ExcalidrawLibrary[], merge: boolean }): Promise<ExcalidrawLibrary[]>;
|
||||
addFiles(files: ExcalidrawElement[]);
|
||||
history: {
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
interface ExcalidrawElement {
|
||||
fileId: number;
|
||||
}
|
||||
|
||||
interface ExcalidrawLibrary {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface ExcalidrawScene {
|
||||
elements: unknown[];
|
||||
appState: ExcalidrawAppState;
|
||||
collaborators: unknown[];
|
||||
}
|
||||
|
||||
interface ExcalidrawAppState {
|
||||
scrollX?: number;
|
||||
scrollY?: number;
|
||||
zoom?: number;
|
||||
theme?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
offsetLeft?: number;
|
||||
offsetTop?: number;
|
||||
}
|
||||
|
||||
interface AutoCompleteConfig {
|
||||
|
@ -1,9 +1,14 @@
|
||||
import libraryLoader from "../../services/library_loader.js";
|
||||
import TypeWidget from "./type_widget.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import linkService from "../../services/link.js";
|
||||
import server from "../../services/server.js";
|
||||
import type FNote from "../../entities/fnote.js";
|
||||
import type { default as ExcalidrawLib } from "@excalidraw/excalidraw";
|
||||
import type { ExcalidrawElement, Theme } from "@excalidraw/excalidraw/types/element/types.js";
|
||||
import type { AppState, BinaryFileData, ExcalidrawImperativeAPI, ExcalidrawProps, LibraryItem, SceneData } from "@excalidraw/excalidraw/types/types.js";
|
||||
import type { JSX } from "react";
|
||||
import type React from "react";
|
||||
|
||||
const TPL = `
|
||||
<div class="canvas-widget note-detail-canvas note-detail-printable note-detail">
|
||||
<style>
|
||||
@ -54,8 +59,8 @@ const TPL = `
|
||||
|
||||
interface CanvasContent {
|
||||
elements: ExcalidrawElement[],
|
||||
files: ExcalidrawElement[],
|
||||
appState: ExcalidrawAppState
|
||||
files: BinaryFileData[],
|
||||
appState: Partial<AppState>
|
||||
}
|
||||
|
||||
interface AttachmentMetadata {
|
||||
@ -114,13 +119,12 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
private currentNoteId: string;
|
||||
private currentSceneVersion: number;
|
||||
private libraryChanged: boolean;
|
||||
private librarycache: ExcalidrawLibrary[];
|
||||
private librarycache: LibraryItem[];
|
||||
private attachmentMetadata: AttachmentMetadata[];
|
||||
private themeStyle!: string;
|
||||
private excalidrawApi!: ExcalidrawApi;
|
||||
private excalidrawWrapperRef!: {
|
||||
current: HTMLElement
|
||||
};
|
||||
private themeStyle!: Theme;
|
||||
private excalidrawLib!: typeof ExcalidrawLib;
|
||||
private excalidrawApi!: ExcalidrawImperativeAPI;
|
||||
private excalidrawWrapperRef!: React.RefObject<HTMLElement | null>;
|
||||
|
||||
private $render!: JQuery<HTMLElement>;
|
||||
private reactHandlers!: JQuery<HTMLElement>;
|
||||
@ -133,7 +137,8 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
this.SCENE_VERSION_ERROR = -2; // -2 indicates error
|
||||
|
||||
// ensure that assets are loaded from trilium
|
||||
window.EXCALIDRAW_ASSET_PATH = `${window.location.origin}/node_modules/@excalidraw/excalidraw/dist/`;
|
||||
// TODO:
|
||||
(window as any).EXCALIDRAW_ASSET_PATH = `${window.location.origin}/node_modules/@excalidraw/excalidraw/dist/`;
|
||||
|
||||
// temporary vars
|
||||
this.currentNoteId = "";
|
||||
@ -169,24 +174,39 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
this.$widget.toggleClass("full-height", true);
|
||||
this.$render = this.$widget.find(".canvas-render");
|
||||
const documentStyle = window.getComputedStyle(document.documentElement);
|
||||
this.themeStyle = documentStyle.getPropertyValue("--theme-style")?.trim();
|
||||
this.themeStyle = documentStyle.getPropertyValue("--theme-style")?.trim() as Theme;
|
||||
|
||||
libraryLoader.requireLibrary(libraryLoader.EXCALIDRAW).then(() => {
|
||||
const React = window.React;
|
||||
const ReactDOM = window.ReactDOM;
|
||||
const renderElement = this.$render.get(0);
|
||||
if (!renderElement) {
|
||||
throw new Error("Unable to find element to render.");
|
||||
}
|
||||
|
||||
ReactDOM.unmountComponentAtNode(renderElement);
|
||||
const root = ReactDOM.createRoot(renderElement);
|
||||
root.render(React.createElement(() => this.createExcalidrawReactApp()));
|
||||
});
|
||||
this.#init();
|
||||
|
||||
return this.$widget;
|
||||
}
|
||||
|
||||
async #init() {
|
||||
const renderElement = this.$render.get(0);
|
||||
if (!renderElement) {
|
||||
throw new Error("Unable to find element to render.");
|
||||
}
|
||||
|
||||
// See https://github.com/excalidraw/excalidraw/issues/7899.
|
||||
if (!window.process) {
|
||||
(window.process as any) = {};
|
||||
}
|
||||
if (!window.process.env) {
|
||||
window.process.env = {};
|
||||
}
|
||||
(window.process.env as any).PREACT = false;
|
||||
|
||||
const excalidraw = (await import("@excalidraw/excalidraw"));
|
||||
this.excalidrawLib = excalidraw;
|
||||
|
||||
const { unmountComponentAtNode } = await import("react-dom");
|
||||
const { createRoot } = await import("react-dom/client");
|
||||
const React = (await import("react")).default;
|
||||
unmountComponentAtNode(renderElement);
|
||||
const root = createRoot(renderElement);
|
||||
root.render(React.createElement(() => this.createExcalidrawReactApp(React, excalidraw.Excalidraw)));
|
||||
}
|
||||
|
||||
/**
|
||||
* called to populate the widget container with the note content
|
||||
*/
|
||||
@ -215,15 +235,15 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
* newly instantiated?
|
||||
*/
|
||||
if (!blob?.content?.trim()) {
|
||||
const sceneData = {
|
||||
const sceneData: SceneData = {
|
||||
elements: [],
|
||||
appState: {
|
||||
theme: this.themeStyle
|
||||
},
|
||||
collaborators: []
|
||||
}
|
||||
};
|
||||
|
||||
this.excalidrawApi.updateScene(sceneData);
|
||||
// TODO: Props mismatch.
|
||||
this.excalidrawApi.updateScene(sceneData as any);
|
||||
} else if (blob.content) {
|
||||
let content: CanvasContent;
|
||||
|
||||
@ -240,26 +260,28 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
};
|
||||
}
|
||||
|
||||
const { elements, files, appState = {} } = content;
|
||||
const { elements, files } = content;
|
||||
const appState: Partial<AppState> = content.appState ?? {};
|
||||
|
||||
appState.theme = this.themeStyle;
|
||||
|
||||
const boundingClientRect = this.excalidrawWrapperRef.current.getBoundingClientRect();
|
||||
appState.width = boundingClientRect.width;
|
||||
appState.height = boundingClientRect.height;
|
||||
appState.offsetLeft = boundingClientRect.left;
|
||||
appState.offsetTop = boundingClientRect.top;
|
||||
if (this.excalidrawWrapperRef.current) {
|
||||
const boundingClientRect = this.excalidrawWrapperRef.current.getBoundingClientRect();
|
||||
appState.width = boundingClientRect.width;
|
||||
appState.height = boundingClientRect.height;
|
||||
appState.offsetLeft = boundingClientRect.left;
|
||||
appState.offsetTop = boundingClientRect.top;
|
||||
}
|
||||
|
||||
const sceneData: ExcalidrawScene = {
|
||||
const sceneData: SceneData = {
|
||||
elements,
|
||||
appState,
|
||||
collaborators: []
|
||||
appState
|
||||
};
|
||||
|
||||
// files are expected in an array when loading. they are stored as a key-index object
|
||||
// see example for loading here:
|
||||
// https://github.com/excalidraw/excalidraw/blob/c5a7723185f6ca05e0ceb0b0d45c4e3fbcb81b2a/src/packages/excalidraw/example/App.js#L68
|
||||
const fileArray = [];
|
||||
const fileArray: BinaryFileData[] = [];
|
||||
for (const fileId in files) {
|
||||
const file = files[fileId];
|
||||
// TODO: dataURL is replaceable with a trilium image url
|
||||
@ -288,7 +310,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
}
|
||||
|
||||
// Extract libraryItems from the blobs
|
||||
const libraryItems = results.map((result) => result?.blob?.getJsonContentSafely()).filter((item) => !!item) as ExcalidrawLibrary[];
|
||||
const libraryItems = results.map((result) => result?.blob?.getJsonContentSafely()).filter((item) => !!item) as LibraryItem[];
|
||||
|
||||
// Extract metadata for each attachment
|
||||
const metadata = results.map((result) => result.metadata);
|
||||
@ -302,7 +324,8 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
});
|
||||
|
||||
// Update the scene
|
||||
this.excalidrawApi.updateScene(sceneData);
|
||||
// TODO: Fix type of sceneData
|
||||
this.excalidrawApi.updateScene(sceneData as any);
|
||||
this.excalidrawApi.addFiles(fileArray);
|
||||
this.excalidrawApi.history.clear();
|
||||
}
|
||||
@ -328,18 +351,17 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
const files = this.excalidrawApi.getFiles();
|
||||
|
||||
// parallel svg export to combat bitrot and enable rendering image for note inclusion, preview, and share
|
||||
const svg = await window.ExcalidrawLib.exportToSvg({
|
||||
const svg = await this.excalidrawLib.exportToSvg({
|
||||
elements,
|
||||
appState,
|
||||
exportPadding: 5, // 5 px padding
|
||||
metadata: "trilium-export",
|
||||
files
|
||||
});
|
||||
const svgString = svg.outerHTML;
|
||||
|
||||
const activeFiles: Record<string, ExcalidrawElement> = {};
|
||||
const activeFiles: Record<string, BinaryFileData> = {};
|
||||
elements.forEach((element) => {
|
||||
if (element.fileId) {
|
||||
if ("fileId" in element && element.fileId) {
|
||||
activeFiles[element.fileId] = files[element.fileId];
|
||||
}
|
||||
});
|
||||
@ -362,7 +384,12 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
// this.libraryChanged is unset in dataSaved()
|
||||
|
||||
// there's no separate method to get library items, so have to abuse this one
|
||||
const libraryItems = await this.excalidrawApi.updateLibrary({ merge: true });
|
||||
const libraryItems = await this.excalidrawApi.updateLibrary({
|
||||
libraryItems(currentLibraryItems) {
|
||||
return [];
|
||||
},
|
||||
merge: true
|
||||
});
|
||||
|
||||
// excalidraw saves the library as a own state. the items are saved to libraryItems. then we compare the library right now with a libraryitemcache. The cache is filled when we first load the Library into the note.
|
||||
//We need the cache to delete old attachments later in the server.
|
||||
@ -445,33 +472,35 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
}
|
||||
}
|
||||
|
||||
createExcalidrawReactApp() {
|
||||
const React = window.React;
|
||||
const { Excalidraw } = window.ExcalidrawLib;
|
||||
const excalidrawWrapperRef = React.useRef(null);
|
||||
createExcalidrawReactApp(react: typeof React, excalidrawComponent: React.MemoExoticComponent<(props: ExcalidrawProps) => JSX.Element>) {
|
||||
const excalidrawWrapperRef = react.useRef<HTMLElement>(null);
|
||||
this.excalidrawWrapperRef = excalidrawWrapperRef;
|
||||
const [dimensions, setDimensions] = React.useState({
|
||||
const [dimensions, setDimensions] = react.useState<{ width?: number, height?: number}>({
|
||||
width: undefined,
|
||||
height: undefined
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
const dimensions = {
|
||||
width: excalidrawWrapperRef.current.getBoundingClientRect().width,
|
||||
height: excalidrawWrapperRef.current.getBoundingClientRect().height
|
||||
};
|
||||
setDimensions(dimensions);
|
||||
react.useEffect(() => {
|
||||
if (excalidrawWrapperRef.current) {
|
||||
const dimensions = {
|
||||
width: excalidrawWrapperRef.current.getBoundingClientRect().width,
|
||||
height: excalidrawWrapperRef.current.getBoundingClientRect().height
|
||||
};
|
||||
setDimensions(dimensions);
|
||||
}
|
||||
|
||||
const onResize = () => {
|
||||
if (this.note?.type !== "canvas") {
|
||||
return;
|
||||
}
|
||||
|
||||
const dimensions = {
|
||||
width: excalidrawWrapperRef.current.getBoundingClientRect().width,
|
||||
height: excalidrawWrapperRef.current.getBoundingClientRect().height
|
||||
};
|
||||
setDimensions(dimensions);
|
||||
if (excalidrawWrapperRef.current) {
|
||||
const dimensions = {
|
||||
width: excalidrawWrapperRef.current.getBoundingClientRect().width,
|
||||
height: excalidrawWrapperRef.current.getBoundingClientRect().height
|
||||
};
|
||||
setDimensions(dimensions);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("resize", onResize);
|
||||
@ -479,8 +508,11 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
return () => window.removeEventListener("resize", onResize);
|
||||
}, [excalidrawWrapperRef]);
|
||||
|
||||
const onLinkOpen = React.useCallback((element, event) => {
|
||||
const onLinkOpen = react.useCallback<NonNullable<ExcalidrawProps["onLinkOpen"]>>((element, event) => {
|
||||
let link = element.link;
|
||||
if (!link) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (link.startsWith("root/")) {
|
||||
link = "#" + link;
|
||||
@ -493,25 +525,24 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
return linkService.goToLinkExt(nativeEvent, link, null);
|
||||
}, []);
|
||||
|
||||
return React.createElement(
|
||||
React.Fragment,
|
||||
return react.createElement(
|
||||
react.Fragment,
|
||||
null,
|
||||
React.createElement(
|
||||
react.createElement(
|
||||
"div",
|
||||
{
|
||||
className: "excalidraw-wrapper",
|
||||
ref: excalidrawWrapperRef
|
||||
},
|
||||
React.createElement(Excalidraw, {
|
||||
react.createElement(excalidrawComponent, {
|
||||
// this makes sure that 1) manual theme switch button is hidden 2) theme stays as it should after opening menu
|
||||
theme: this.themeStyle,
|
||||
excalidrawAPI: (api: ExcalidrawApi) => {
|
||||
excalidrawAPI: (api: ExcalidrawImperativeAPI) => {
|
||||
this.excalidrawApi = api;
|
||||
},
|
||||
width: dimensions.width,
|
||||
height: dimensions.height,
|
||||
onPaste: (data: unknown, event: unknown) => {
|
||||
console.log("Verbose: excalidraw internal paste. No trilium action implemented.", data, event);
|
||||
return false;
|
||||
},
|
||||
onLibraryChange: () => {
|
||||
this.libraryChanged = true;
|
||||
@ -528,8 +559,10 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
autoFocus: false,
|
||||
onLinkOpen,
|
||||
UIOptions: {
|
||||
saveToActiveFile: false,
|
||||
saveAsImage: false
|
||||
canvasActions: {
|
||||
saveToActiveFile: false,
|
||||
saveAsImage: false
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
@ -555,7 +588,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
getSceneVersion() {
|
||||
if (this.excalidrawApi) {
|
||||
const elements = this.excalidrawApi.getSceneElements();
|
||||
return window.ExcalidrawLib.getSceneVersion(elements);
|
||||
return this.excalidrawLib.getSceneVersion(elements);
|
||||
} else {
|
||||
return this.SCENE_VERSION_ERROR;
|
||||
}
|
||||
|
@ -44,13 +44,6 @@ async function register(app: express.Application) {
|
||||
app.use(`/assets/vX/stylesheets`, express.static(path.join(srcRoot, "public/stylesheets")));
|
||||
app.use(`/${assetPath}/libraries`, persistentCacheStatic(path.join(srcRoot, "..", "libraries")));
|
||||
app.use(`/assets/vX/libraries`, express.static(path.join(srcRoot, "..", "libraries")));
|
||||
|
||||
// excalidraw-view mode in shared notes
|
||||
app.use(`/${assetPath}/node_modules/react/umd/react.production.min.js`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/react/umd/react.production.min.js")));
|
||||
app.use(`/${assetPath}/node_modules/react/umd/react.development.js`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/react/umd/react.development.js")));
|
||||
app.use(`/${assetPath}/node_modules/react-dom/umd/react-dom.production.min.js`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/react-dom/umd/react-dom.production.min.js")));
|
||||
app.use(`/${assetPath}/node_modules/react-dom/umd/react-dom.development.js`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/react-dom/umd/react-dom.development.js")));
|
||||
// expose the whole dist folder since complete assets are needed in edit and share
|
||||
app.use(`/node_modules/@excalidraw/excalidraw/dist/`, express.static(path.join(srcRoot, "..", "node_modules/@excalidraw/excalidraw/dist/")));
|
||||
app.use(`/${assetPath}/node_modules/@excalidraw/excalidraw/dist/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/@excalidraw/excalidraw/dist/")));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user