mirror of
https://github.com/zadam/trilium.git
synced 2025-12-28 10:14:26 +01:00
chore(react/type_widget): set up self-hosted fonts
This commit is contained in:
parent
68bf5b7e68
commit
44b92a024c
@ -1,8 +1,8 @@
|
||||
import { Excalidraw, exportToSvg, getSceneVersion } from "@excalidraw/excalidraw";
|
||||
import { TypeWidgetProps } from "./type_widget";
|
||||
import "@excalidraw/excalidraw/index.css";
|
||||
import { useEditorSpacedUpdate, useNoteBlob } from "../react/hooks";
|
||||
import { useEffect, useMemo, useRef } from "preact/hooks";
|
||||
import { useEditorSpacedUpdate } from "../react/hooks";
|
||||
import { 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";
|
||||
@ -12,6 +12,10 @@ import server from "../../services/server";
|
||||
import { NonDeletedExcalidrawElement } from "@excalidraw/excalidraw/element/types";
|
||||
import { CanvasContent } from "../type_widgets_old/canvas_el";
|
||||
|
||||
// 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 {
|
||||
title: string;
|
||||
attachmentId: string;
|
||||
@ -19,12 +23,12 @@ interface AttachmentMetadata {
|
||||
|
||||
export default function Canvas({ note }: TypeWidgetProps) {
|
||||
const apiRef = useRef<ExcalidrawImperativeAPI>(null);
|
||||
const viewModeEnabled = options.is("databaseReadonly");
|
||||
const isReadOnly = options.is("databaseReadonly");
|
||||
const themeStyle = useMemo(() => {
|
||||
const documentStyle = window.getComputedStyle(document.documentElement);
|
||||
return documentStyle.getPropertyValue("--theme-style")?.trim() as AppState["theme"];
|
||||
}, []);
|
||||
const persistence = usePersistence(note, apiRef, themeStyle);
|
||||
const persistence = usePersistence(note, apiRef, themeStyle, isReadOnly);
|
||||
|
||||
return (
|
||||
<div className="canvas-widget note-detail-canvas note-detail-printable note-detail full-height">
|
||||
@ -33,7 +37,7 @@ export default function Canvas({ note }: TypeWidgetProps) {
|
||||
<Excalidraw
|
||||
excalidrawAPI={api => apiRef.current = api}
|
||||
theme={themeStyle}
|
||||
viewModeEnabled={viewModeEnabled}
|
||||
viewModeEnabled={isReadOnly}
|
||||
zenModeEnabled={false}
|
||||
isCollaborating={false}
|
||||
detectScroll={false}
|
||||
@ -53,7 +57,7 @@ export default function Canvas({ note }: TypeWidgetProps) {
|
||||
)
|
||||
}
|
||||
|
||||
function usePersistence(note: FNote, apiRef: RefObject<ExcalidrawImperativeAPI>, theme: AppState["theme"]): Partial<ExcalidrawProps> {
|
||||
function usePersistence(note: FNote, apiRef: RefObject<ExcalidrawImperativeAPI>, theme: AppState["theme"], isReadOnly: boolean): Partial<ExcalidrawProps> {
|
||||
const libraryChanged = useRef(false);
|
||||
const currentSceneVersion = useRef(0);
|
||||
|
||||
@ -169,7 +173,7 @@ function usePersistence(note: FNote, apiRef: RefObject<ExcalidrawImperativeAPI>,
|
||||
|
||||
return {
|
||||
onChange: () => {
|
||||
if (!apiRef.current) return;
|
||||
if (!apiRef.current || isReadOnly) return;
|
||||
const oldSceneVersion = currentSceneVersion.current;
|
||||
const newSceneVersion = getSceneVersion(apiRef.current.getSceneElements());
|
||||
|
||||
|
||||
@ -113,93 +113,4 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
return this.$widget;
|
||||
}
|
||||
|
||||
async #init() {
|
||||
const renderElement = this.$render.get(0);
|
||||
if (!renderElement) {
|
||||
throw new Error("Unable to find element to render.");
|
||||
}
|
||||
|
||||
const Canvas = (await import("./canvas_el.js")).default;
|
||||
this.canvasInstance = new Canvas({
|
||||
// this makes sure that 1) manual theme switch button is hidden 2) theme stays as it should after opening menu
|
||||
onChange: () => this.onChangeHandler(),
|
||||
onLibraryChange: () => {
|
||||
this.libraryChanged = true;
|
||||
|
||||
this.saveData();
|
||||
},
|
||||
});
|
||||
|
||||
await setupFonts();
|
||||
const canvasEl = renderReactWidget(this, this.canvasInstance.createCanvasElement())[0];
|
||||
renderElement.replaceChildren(canvasEl);
|
||||
}
|
||||
|
||||
/**
|
||||
* called to populate the widget container with the note content
|
||||
*/
|
||||
async doRefresh(note: FNote) {
|
||||
if (!this.canvasInstance) {
|
||||
await this.#init();
|
||||
}
|
||||
|
||||
this.currentNoteId = note.noteId;
|
||||
|
||||
// get note from backend and put into canvas
|
||||
const blob = await note.getBlob();
|
||||
}
|
||||
|
||||
/**
|
||||
* save content to backend
|
||||
*/
|
||||
saveData() {
|
||||
// Since Excalidraw sends an enormous amount of events, wait for them to stop before actually saving.
|
||||
this.spacedUpdate.resetUpdateTimer();
|
||||
this.spacedUpdate.scheduleUpdate();
|
||||
}
|
||||
|
||||
onChangeHandler() {
|
||||
if (options.is("databaseReadonly")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.canvasInstance.isInitialized()) return;
|
||||
|
||||
// changeHandler is called upon any tiny change in excalidraw. button clicked, hover, etc.
|
||||
// make sure only when a new element is added, we actually save something.
|
||||
const isNewSceneVersion = this.canvasInstance.isNewSceneVersion();
|
||||
/**
|
||||
* FIXME: however, we might want to make an exception, if viewport changed, since viewport
|
||||
* is desired to save? (add) and appState background, and some things
|
||||
*/
|
||||
|
||||
// upon updateScene, onchange is called, even though "nothing really changed" that is worth saving
|
||||
const isNotInitialScene = !this.canvasInstance.isInitialScene();
|
||||
const shouldSave = isNewSceneVersion && isNotInitialScene;
|
||||
|
||||
if (shouldSave) {
|
||||
this.canvasInstance.updateSceneVersion();
|
||||
this.saveData();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function setupFonts() {
|
||||
if (window.EXCALIDRAW_ASSET_PATH) {
|
||||
return;
|
||||
}
|
||||
|
||||
// currently required by excalidraw, in order to allows self-hosting fonts locally.
|
||||
// this avoids making excalidraw load the fonts from an external CDN.
|
||||
let path: string;
|
||||
if (!glob.isDev) {
|
||||
path = `${window.location.pathname}/node_modules/@excalidraw/excalidraw/dist/prod`;
|
||||
} else {
|
||||
path = (await import("../../../../../node_modules/@excalidraw/excalidraw/dist/prod/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2?url")).default;
|
||||
let pathComponents = path.split("/");
|
||||
path = pathComponents.slice(0, pathComponents.length - 2).join("/");
|
||||
}
|
||||
|
||||
window.EXCALIDRAW_ASSET_PATH = path;
|
||||
}
|
||||
|
||||
@ -21,17 +21,19 @@ async function register(app: express.Application) {
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
const { createServer: createViteServer } = await import("vite");
|
||||
const clientDir = path.join(srcRoot, "../client");
|
||||
const vite = await createViteServer({
|
||||
server: { middlewareMode: true },
|
||||
appType: "custom",
|
||||
cacheDir: path.join(srcRoot, "../../.cache/vite"),
|
||||
base: `/${assetUrlFragment}/`,
|
||||
root: path.join(srcRoot, "../client")
|
||||
root: clientDir
|
||||
});
|
||||
app.use(`/${assetUrlFragment}/`, (req, res, next) => {
|
||||
req.url = `/${assetUrlFragment}` + req.url;
|
||||
vite.middlewares(req, res, next);
|
||||
});
|
||||
app.use(`/node_modules/@excalidraw/excalidraw/dist/prod`, persistentCacheStatic(path.join(srcRoot, "../../node_modules/@excalidraw/excalidraw/dist/prod")));
|
||||
} else {
|
||||
const publicDir = path.join(resourceDir, "public");
|
||||
if (!existsSync(publicDir)) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user