mirror of
https://github.com/zadam/trilium.git
synced 2025-11-10 15:25:51 +01:00
chore(react/type_widgets): start porting canvas
This commit is contained in:
@@ -33,7 +33,8 @@ const TYPE_MAPPINGS: Record<ExtendedNoteType, () => Promise<{ default: TypeWidge
|
||||
"attachmentList": async () => (await import("./type_widgets/Attachment")).AttachmentList,
|
||||
"attachmentDetail": async () => (await import("./type_widgets/Attachment")).AttachmentDetail,
|
||||
"readOnlyText": () => import("./type_widgets/text/ReadOnlyText"),
|
||||
"render": () => import("./type_widgets/Render")
|
||||
"render": () => import("./type_widgets/Render"),
|
||||
"canvas": () => import("./type_widgets/Canvas")
|
||||
// TODO: finalize the record.
|
||||
};
|
||||
|
||||
|
||||
34
apps/client/src/widgets/type_widgets/Canvas.css
Normal file
34
apps/client/src/widgets/type_widgets/Canvas.css
Normal file
@@ -0,0 +1,34 @@
|
||||
.excalidraw .App-menu_top .buttonList {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Conflict between excalidraw and bootstrap classes keeps the menu hidden */
|
||||
/* https://github.com/zadam/trilium/issues/3780 */
|
||||
/* https://github.com/excalidraw/excalidraw/issues/6567 */
|
||||
.excalidraw .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.excalidraw-wrapper {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:root[dir="ltr"]
|
||||
.excalidraw
|
||||
.layer-ui__wrapper
|
||||
.zen-mode-transition.App-menu_bottom--transition-left {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* collaboration not possible so hide the button */
|
||||
.CollabButton {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.library-button {
|
||||
display: none !important; /* library won't work without extra support which isn't currently implemented */
|
||||
}
|
||||
|
||||
.note-detail-canvas > .canvas-render {
|
||||
height: 100%;
|
||||
}
|
||||
41
apps/client/src/widgets/type_widgets/Canvas.tsx
Normal file
41
apps/client/src/widgets/type_widgets/Canvas.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { Excalidraw } from "@excalidraw/excalidraw";
|
||||
import { TypeWidgetProps } from "./type_widget";
|
||||
import "@excalidraw/excalidraw/index.css";
|
||||
import { useNoteBlob } from "../react/hooks";
|
||||
import { useEffect, useRef } from "preact/hooks";
|
||||
import type { ExcalidrawImperativeAPI, Theme } from "@excalidraw/excalidraw/types";
|
||||
import "./Canvas.css";
|
||||
|
||||
export default function Canvas({ note }: TypeWidgetProps) {
|
||||
const apiRef = useRef<ExcalidrawImperativeAPI>(null);
|
||||
const blob = useNoteBlob(note);
|
||||
|
||||
useEffect(() => {
|
||||
const documentStyle = window.getComputedStyle(document.documentElement);
|
||||
const themeStyle = documentStyle.getPropertyValue("--theme-style")?.trim() as Theme;
|
||||
|
||||
const api = apiRef.current;
|
||||
const content = blob?.content;
|
||||
if (!api) return;
|
||||
if (!content?.trim()) {
|
||||
api.updateScene({
|
||||
elements: [],
|
||||
appState: {
|
||||
theme: themeStyle
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [ blob ]);
|
||||
|
||||
return (
|
||||
<div className="canvas-widget note-detail-canvas note-detail-printable note-detail full-height">
|
||||
<div className="canvas-render">
|
||||
<div className="excalidraw-wrapper">
|
||||
<Excalidraw
|
||||
excalidrawAPI={api => apiRef.current = api}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -3,55 +3,12 @@ import server from "../../services/server.js";
|
||||
import type FNote from "../../entities/fnote.js";
|
||||
import options from "../../services/options.js";
|
||||
import type { LibraryItem } from "@excalidraw/excalidraw/types";
|
||||
import type { Theme } from "@excalidraw/excalidraw/element/types";
|
||||
import type Canvas from "./canvas_el.js";
|
||||
import { CanvasContent } from "./canvas_el.js";
|
||||
import { renderReactWidget } from "../react/react_utils.jsx";
|
||||
import SpacedUpdate from "../../services/spaced_update.js";
|
||||
import protected_session_holder from "../../services/protected_session_holder.js";
|
||||
|
||||
const TPL = /*html*/`
|
||||
<div class="canvas-widget note-detail-canvas note-detail-printable note-detail">
|
||||
<style>
|
||||
.excalidraw .App-menu_top .buttonList {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Conflict between excalidraw and bootstrap classes keeps the menu hidden */
|
||||
/* https://github.com/zadam/trilium/issues/3780 */
|
||||
/* https://github.com/excalidraw/excalidraw/issues/6567 */
|
||||
.excalidraw .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.excalidraw-wrapper {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:root[dir="ltr"]
|
||||
.excalidraw
|
||||
.layer-ui__wrapper
|
||||
.zen-mode-transition.App-menu_bottom--transition-left {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* collaboration not possible so hide the button */
|
||||
.CollabButton {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.library-button {
|
||||
display: none !important; /* library won't work without extra support which isn't currently implemented */
|
||||
}
|
||||
|
||||
</style>
|
||||
<!-- height here necessary. otherwise excalidraw not shown -->
|
||||
<div class="canvas-render" style="height: 100%"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
|
||||
interface AttachmentMetadata {
|
||||
title: string;
|
||||
attachmentId: string;
|
||||
@@ -151,10 +108,6 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
});
|
||||
}
|
||||
|
||||
static getType() {
|
||||
return "canvas";
|
||||
}
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.$widget.bind("mousewheel DOMMouseScroll", (event) => {
|
||||
@@ -165,10 +118,7 @@ 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() as Theme;
|
||||
|
||||
this.#init();
|
||||
|
||||
@@ -229,9 +179,6 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
// get note from backend and put into canvas
|
||||
const blob = await note.getBlob();
|
||||
|
||||
// before we load content into excalidraw, make sure excalidraw has loaded
|
||||
await this.canvasInstance.waitForApiToBecomeAvailable();
|
||||
|
||||
/**
|
||||
* new and empty note - make sure that canvas is empty.
|
||||
* If we do not set it manually, we occasionally get some "bleeding" from another
|
||||
@@ -239,7 +186,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
* newly instantiated?
|
||||
*/
|
||||
if (!blob?.content?.trim()) {
|
||||
this.canvasInstance.resetScene(this.themeStyle);
|
||||
|
||||
} else if (blob.content) {
|
||||
let content: CanvasContent;
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import "@excalidraw/excalidraw/index.css";
|
||||
import { Excalidraw, getSceneVersion, exportToSvg } from "@excalidraw/excalidraw";
|
||||
import { AppState, BinaryFileData, ExcalidrawImperativeAPI, ExcalidrawProps, LibraryItem } from "@excalidraw/excalidraw/types";
|
||||
import { ExcalidrawElement, NonDeletedExcalidrawElement, Theme } from "@excalidraw/excalidraw/element/types";
|
||||
@@ -19,7 +18,6 @@ export default class Canvas {
|
||||
private currentSceneVersion: number;
|
||||
private opts: ExcalidrawProps;
|
||||
private excalidrawApi!: ExcalidrawImperativeAPI;
|
||||
private initializedPromise: JQuery.Deferred<void>;
|
||||
|
||||
constructor(opts: ExcalidrawProps) {
|
||||
this.opts = opts;
|
||||
@@ -27,19 +25,9 @@ export default class Canvas {
|
||||
this.initializedPromise = $.Deferred();
|
||||
}
|
||||
|
||||
async waitForApiToBecomeAvailable() {
|
||||
while (!this.excalidrawApi) {
|
||||
await this.initializedPromise;
|
||||
}
|
||||
}
|
||||
|
||||
createCanvasElement() {
|
||||
return <CanvasElement
|
||||
{...this.opts}
|
||||
excalidrawAPI={api => {
|
||||
this.excalidrawApi = api;
|
||||
this.initializedPromise.resolve();
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -80,15 +68,6 @@ export default class Canvas {
|
||||
return !!this.excalidrawApi;
|
||||
}
|
||||
|
||||
resetScene(theme: Theme) {
|
||||
this.excalidrawApi.updateScene({
|
||||
elements: [],
|
||||
appState: {
|
||||
theme
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadData(content: CanvasContent, theme: Theme) {
|
||||
const { elements, files } = content;
|
||||
const appState: Partial<AppState> = content.appState ?? {};
|
||||
@@ -178,7 +157,6 @@ export default class Canvas {
|
||||
|
||||
function CanvasElement(opts: ExcalidrawProps) {
|
||||
return (
|
||||
<div className="excalidraw-wrapper">
|
||||
<Excalidraw
|
||||
{...opts}
|
||||
onLinkOpen={useCallback((element: NonDeletedExcalidrawElement, event: CustomEvent) => {
|
||||
@@ -196,6 +174,5 @@ function CanvasElement(opts: ExcalidrawProps) {
|
||||
return linkService.goToLinkExt(nativeEvent, link, null);
|
||||
}, [])}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user