mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-22 07:38:12 +08:00
Split apart the frontend Editor type into SubscriptionsRouter and EditorHandle (#3923)
* Remove the unused Editor.raw/wasmMemory/wasmImport * Split out Editor.subscriptions * Replace editor.handle.* with editor.* (1 of 2) * Replace editor.handle.* with editor.* (2 of 2) * Replace Editor typedef with EditorHandle import * Pluralize subscription-router and rename subscriptionsRef->subscriptionsRouter and editorRef->editorHandle * Remove editor.ts * Update the readme * Fix demo art loading bug
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import type { EditorHandle } from "@graphite/../wasm/pkg/graphite_wasm";
|
||||
import { extractPixelData } from "@graphite/utility-functions/rasterization";
|
||||
import { stripIndents } from "@graphite/utility-functions/strip-indents";
|
||||
|
||||
@@ -83,7 +83,7 @@ export function insertAtCaret(text: string) {
|
||||
element.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
}
|
||||
|
||||
export async function triggerClipboardRead(editor: Editor) {
|
||||
export async function triggerClipboardRead(editor: EditorHandle) {
|
||||
// In the try block, attempt to read from the Clipboard API, which may not have permission and may not be supported in all browsers
|
||||
// In the catch block, explain to the user why the paste failed and how to fix or work around the problem
|
||||
try {
|
||||
@@ -105,7 +105,7 @@ export async function triggerClipboardRead(editor: Editor) {
|
||||
const blob = await item.getType("text/plain");
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
if (typeof reader.result === "string") editor.handle.pasteText(reader.result);
|
||||
if (typeof reader.result === "string") editor.pasteText(reader.result);
|
||||
};
|
||||
reader.readAsText(blob);
|
||||
return true;
|
||||
@@ -119,7 +119,7 @@ export async function triggerClipboardRead(editor: Editor) {
|
||||
const blob = await item.getType("text/plain");
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
if (typeof reader.result === "string") editor.handle.pasteSvg(undefined, reader.result);
|
||||
if (typeof reader.result === "string") editor.pasteSvg(undefined, reader.result);
|
||||
};
|
||||
reader.readAsText(blob);
|
||||
return true;
|
||||
@@ -132,7 +132,7 @@ export async function triggerClipboardRead(editor: Editor) {
|
||||
reader.onload = async () => {
|
||||
if (reader.result instanceof ArrayBuffer) {
|
||||
const imageData = await extractPixelData(new Blob([reader.result], { type: imageType }));
|
||||
editor.handle.pasteImage(undefined, new Uint8Array(imageData.data), imageData.width, imageData.height);
|
||||
editor.pasteImage(undefined, new Uint8Array(imageData.data), imageData.width, imageData.height);
|
||||
}
|
||||
};
|
||||
reader.readAsArrayBuffer(blob);
|
||||
@@ -170,6 +170,6 @@ export async function triggerClipboardRead(editor: Editor) {
|
||||
};
|
||||
const message = Object.entries(matchMessage).find(([key]) => String(err).includes(key))?.[1] || String(err);
|
||||
|
||||
editor.handle.errorDialog("Cannot access clipboard", message);
|
||||
editor.errorDialog("Cannot access clipboard", message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import type { EditorHandle } from "@graphite/../wasm/pkg/graphite_wasm";
|
||||
import { extractPixelData } from "@graphite/utility-functions/rasterization";
|
||||
|
||||
export function downloadFileURL(filename: string, url: string) {
|
||||
@@ -66,18 +66,18 @@ export async function upload(accept: string, textOrData: "text" | "data" | "both
|
||||
}
|
||||
export type UploadResult<T> = { filename: string; type: string; content: T };
|
||||
|
||||
export async function pasteFile(item: DataTransferItem, editor: Editor, mouse?: [number, number], insertParentId?: bigint, insertIndex?: number) {
|
||||
export async function pasteFile(item: DataTransferItem, editor: EditorHandle, mouse?: [number, number], insertParentId?: bigint, insertIndex?: number) {
|
||||
const file = item.getAsFile();
|
||||
if (!file) return;
|
||||
|
||||
if (file.type.startsWith("image/svg")) {
|
||||
const svg = await file.text();
|
||||
editor.handle.pasteSvg(file.name, svg, mouse?.[0], mouse?.[1], insertParentId, insertIndex);
|
||||
editor.pasteSvg(file.name, svg, mouse?.[0], mouse?.[1], insertParentId, insertIndex);
|
||||
} else if (file.type.startsWith("image/")) {
|
||||
const imageData = await extractPixelData(file);
|
||||
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height, mouse?.[0], mouse?.[1], insertParentId, insertIndex);
|
||||
} else if (file.name.endsWith("." + editor.handle.fileExtension())) {
|
||||
editor.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height, mouse?.[0], mouse?.[1], insertParentId, insertIndex);
|
||||
} else if (file.name.endsWith("." + editor.fileExtension())) {
|
||||
// TODO: When we eventually have sub-documents, this should be changed to import the document as a node instead of opening it in a separate tab
|
||||
editor.handle.openFile(file.name, await file.bytes());
|
||||
editor.openFile(file.name, await file.bytes());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { get } from "svelte/store";
|
||||
|
||||
import { isPlatformNative } from "@graphite/../wasm/pkg/graphite_wasm";
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import type { EditorHandle } from "@graphite/../wasm/pkg/graphite_wasm";
|
||||
import type { DialogStore } from "@graphite/stores/dialog";
|
||||
import type { DocumentStore } from "@graphite/stores/document";
|
||||
import { toggleFullscreen } from "@graphite/stores/fullscreen";
|
||||
@@ -79,7 +79,7 @@ export async function shouldRedirectKeyboardEventToBackend(e: KeyboardEvent, dia
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function onKeyDown(e: KeyboardEvent, editor: Editor, dialogStore: DialogStore) {
|
||||
export async function onKeyDown(e: KeyboardEvent, editor: EditorHandle, dialogStore: DialogStore) {
|
||||
const key = await getLocalizedScanCode(e);
|
||||
|
||||
const NO_KEY_REPEAT_MODIFIER_KEYS = ["ControlLeft", "ControlRight", "ShiftLeft", "ShiftRight", "MetaLeft", "MetaRight", "AltLeft", "AltRight", "AltGraph", "CapsLock", "Fn", "FnLock"];
|
||||
@@ -88,29 +88,29 @@ export async function onKeyDown(e: KeyboardEvent, editor: Editor, dialogStore: D
|
||||
if (await shouldRedirectKeyboardEventToBackend(e, dialogStore)) {
|
||||
e.preventDefault();
|
||||
const modifiers = makeKeyboardModifiersBitfield(e);
|
||||
editor.handle.onKeyDown(key, modifiers, e.repeat);
|
||||
editor.onKeyDown(key, modifiers, e.repeat);
|
||||
return;
|
||||
}
|
||||
|
||||
if (get(dialogStore).visible && key === "Escape") {
|
||||
editor.handle.onDialogDismiss();
|
||||
editor.onDialogDismiss();
|
||||
}
|
||||
}
|
||||
|
||||
export async function onKeyUp(e: KeyboardEvent, editor: Editor, dialogStore: DialogStore) {
|
||||
export async function onKeyUp(e: KeyboardEvent, editor: EditorHandle, dialogStore: DialogStore) {
|
||||
const key = await getLocalizedScanCode(e);
|
||||
|
||||
if (await shouldRedirectKeyboardEventToBackend(e, dialogStore)) {
|
||||
e.preventDefault();
|
||||
const modifiers = makeKeyboardModifiersBitfield(e);
|
||||
editor.handle.onKeyUp(key, modifiers, e.repeat);
|
||||
editor.onKeyUp(key, modifiers, e.repeat);
|
||||
}
|
||||
}
|
||||
|
||||
// Pointer events
|
||||
|
||||
// While any pointer button is already down, additional button down events are not reported, but they are sent as `pointermove` events and these are handled in the backend
|
||||
export function onPointerMove(e: PointerEvent, editor: Editor, documentStore: DocumentStore) {
|
||||
export function onPointerMove(e: PointerEvent, editor: EditorHandle, documentStore: DocumentStore) {
|
||||
potentiallyRestoreCanvasFocus(e);
|
||||
|
||||
if (!e.buttons) viewportPointerInteractionOngoing = false;
|
||||
@@ -124,11 +124,11 @@ export function onPointerMove(e: PointerEvent, editor: Editor, documentStore: Do
|
||||
if (!viewportPointerInteractionOngoing && (inFloatingMenu || inGraphOverlay)) return;
|
||||
|
||||
const modifiers = makeKeyboardModifiersBitfield(e);
|
||||
if (detectShake(e)) editor.handle.onMouseShake(e.clientX, e.clientY, e.buttons, modifiers);
|
||||
editor.handle.onMouseMove(e.clientX, e.clientY, e.buttons, modifiers);
|
||||
if (detectShake(e)) editor.onMouseShake(e.clientX, e.clientY, e.buttons, modifiers);
|
||||
editor.onMouseMove(e.clientX, e.clientY, e.buttons, modifiers);
|
||||
}
|
||||
|
||||
export function onPointerDown(e: PointerEvent, editor: Editor, dialogStore: DialogStore) {
|
||||
export function onPointerDown(e: PointerEvent, editor: EditorHandle, dialogStore: DialogStore) {
|
||||
potentiallyRestoreCanvasFocus(e);
|
||||
|
||||
const inFloatingMenu = e.target instanceof Element && e.target.closest("[data-floating-menu-content]");
|
||||
@@ -138,7 +138,7 @@ export function onPointerDown(e: PointerEvent, editor: Editor, dialogStore: Dial
|
||||
const inTextInput = e.target === textToolInteractiveInputElement;
|
||||
|
||||
if (get(dialogStore).visible && !inDialog) {
|
||||
editor.handle.onDialogDismiss();
|
||||
editor.onDialogDismiss();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
@@ -146,7 +146,7 @@ export function onPointerDown(e: PointerEvent, editor: Editor, dialogStore: Dial
|
||||
if (!inTextInput && !inContextMenu) {
|
||||
if (textToolInteractiveInputElement) {
|
||||
const isLeftOrRightClick = e.button === BUTTON_RIGHT || e.button === BUTTON_LEFT;
|
||||
editor.handle.onChangeText(textInputCleanup(textToolInteractiveInputElement.innerText), isLeftOrRightClick);
|
||||
editor.onChangeText(textInputCleanup(textToolInteractiveInputElement.innerText), isLeftOrRightClick);
|
||||
} else {
|
||||
viewportPointerInteractionOngoing = isTargetingCanvas instanceof Element;
|
||||
}
|
||||
@@ -154,11 +154,11 @@ export function onPointerDown(e: PointerEvent, editor: Editor, dialogStore: Dial
|
||||
|
||||
if (viewportPointerInteractionOngoing && isTargetingCanvas instanceof Element) {
|
||||
const modifiers = makeKeyboardModifiersBitfield(e);
|
||||
editor.handle.onMouseDown(e.clientX, e.clientY, e.buttons, modifiers);
|
||||
editor.onMouseDown(e.clientX, e.clientY, e.buttons, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
export function onPointerUp(e: PointerEvent, editor: Editor) {
|
||||
export function onPointerUp(e: PointerEvent, editor: EditorHandle) {
|
||||
potentiallyRestoreCanvasFocus(e);
|
||||
|
||||
// Don't let the browser navigate back or forward when using the buttons on some mice
|
||||
@@ -172,12 +172,12 @@ export function onPointerUp(e: PointerEvent, editor: Editor) {
|
||||
if (textToolInteractiveInputElement) return;
|
||||
|
||||
const modifiers = makeKeyboardModifiersBitfield(e);
|
||||
editor.handle.onMouseUp(e.clientX, e.clientY, e.buttons, modifiers);
|
||||
editor.onMouseUp(e.clientX, e.clientY, e.buttons, modifiers);
|
||||
}
|
||||
|
||||
// Mouse events
|
||||
|
||||
export function onPotentialDoubleClick(e: MouseEvent, editor: Editor) {
|
||||
export function onPotentialDoubleClick(e: MouseEvent, editor: EditorHandle) {
|
||||
if (textToolInteractiveInputElement || inPointerLock) return;
|
||||
|
||||
// Allow only events within the viewport or node graph boundaries
|
||||
@@ -196,7 +196,7 @@ export function onPotentialDoubleClick(e: MouseEvent, editor: Editor) {
|
||||
if (e.button === BUTTON_FORWARD) buttons = 16; // Forward
|
||||
|
||||
const modifiers = makeKeyboardModifiersBitfield(e);
|
||||
editor.handle.onDoubleClick(e.clientX, e.clientY, buttons, modifiers);
|
||||
editor.onDoubleClick(e.clientX, e.clientY, buttons, modifiers);
|
||||
}
|
||||
|
||||
export function onMouseDown(e: MouseEvent) {
|
||||
@@ -216,7 +216,7 @@ export function onPointerLockChange() {
|
||||
|
||||
// Wheel events
|
||||
|
||||
export function onWheelScroll(e: WheelEvent, editor: Editor) {
|
||||
export function onWheelScroll(e: WheelEvent, editor: EditorHandle) {
|
||||
const isTargetingCanvas = e.target instanceof Element && e.target.closest("[data-viewport], [data-viewport-container], [data-node-graph]");
|
||||
|
||||
// Prevent zooming the entire page when using Ctrl + scroll wheel outside of the viewport
|
||||
@@ -235,7 +235,7 @@ export function onWheelScroll(e: WheelEvent, editor: Editor) {
|
||||
if (isTargetingCanvas) {
|
||||
e.preventDefault();
|
||||
const modifiers = makeKeyboardModifiersBitfield(e);
|
||||
editor.handle.onWheelScroll(e.clientX, e.clientY, e.buttons, e.deltaX, e.deltaY, e.deltaZ, modifiers);
|
||||
editor.onWheelScroll(e.clientX, e.clientY, e.buttons, e.deltaX, e.deltaY, e.deltaZ, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,15 +247,15 @@ export function onModifyInputField(e: CustomEvent) {
|
||||
|
||||
// Window events
|
||||
|
||||
export async function onBeforeUnload(e: BeforeUnloadEvent, editor: Editor, portfolioStore: PortfolioStore) {
|
||||
export async function onBeforeUnload(e: BeforeUnloadEvent, editor: EditorHandle, portfolioStore: PortfolioStore) {
|
||||
const activeDocument = get(portfolioStore).documents[get(portfolioStore).activeDocumentIndex];
|
||||
if (activeDocument && !activeDocument.details.isAutoSaved) editor.handle.triggerAutoSave(activeDocument.id);
|
||||
if (activeDocument && !activeDocument.details.isAutoSaved) editor.triggerAutoSave(activeDocument.id);
|
||||
|
||||
// Skip the message if the editor crashed, since work is already lost
|
||||
if (await editor.handle.hasCrashed()) return;
|
||||
if (await editor.hasCrashed()) return;
|
||||
|
||||
// Skip the message during development, since it's annoying when testing
|
||||
if (await editor.handle.inDevelopmentMode()) return;
|
||||
if (await editor.inDevelopmentMode()) return;
|
||||
|
||||
const allDocumentsSaved = get(portfolioStore).documents.reduce((acc, doc) => acc && doc.details.isSaved, true);
|
||||
if (!allDocumentsSaved) {
|
||||
@@ -264,13 +264,13 @@ export async function onBeforeUnload(e: BeforeUnloadEvent, editor: Editor, portf
|
||||
}
|
||||
}
|
||||
|
||||
export function onPaste(e: ClipboardEvent, editor: Editor) {
|
||||
export function onPaste(e: ClipboardEvent, editor: EditorHandle) {
|
||||
const dataTransfer = e.clipboardData;
|
||||
if (!dataTransfer || targetIsTextField(e.target || undefined)) return;
|
||||
e.preventDefault();
|
||||
|
||||
Array.from(dataTransfer.items).forEach(async (item) => {
|
||||
if (item.type === "text/plain") item.getAsString((text) => editor.handle.pasteText(text));
|
||||
if (item.type === "text/plain") item.getAsString((text) => editor.pasteText(text));
|
||||
await pasteFile(item, editor);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { EditorHandle } from "@graphite/../wasm/pkg/graphite_wasm";
|
||||
|
||||
export type RequestResult = { body: string; status: number };
|
||||
|
||||
// Special implementation using the legacy XMLHttpRequest API that provides callbacks to get:
|
||||
@@ -31,3 +33,23 @@ export function requestWithUploadDownloadProgress(
|
||||
|
||||
return [promise, xhrValue];
|
||||
}
|
||||
|
||||
// If the URL hash fragment contains a demo artwork path (e.g. #demo/isometric-light), fetch and open it
|
||||
export async function loadDemoArtwork(editor: EditorHandle) {
|
||||
const demoArtwork = window.location.hash.trim().match(/#demo\/(.*)/)?.[1];
|
||||
if (!demoArtwork) return;
|
||||
|
||||
try {
|
||||
const url = new URL(`/demo-artwork/${demoArtwork}.${editor.fileExtension()}`, document.location.href);
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error();
|
||||
|
||||
const filename = url.pathname.split("/").pop() || `Untitled.${editor.fileExtension()}`;
|
||||
const content = await response.bytes();
|
||||
editor.openFile(filename, content);
|
||||
|
||||
history.replaceState("", "", `${window.location.pathname}${window.location.search}`);
|
||||
} catch {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as idb from "idb-keyval";
|
||||
import { get } from "svelte/store";
|
||||
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import type { EditorHandle } from "@graphite/../wasm/pkg/graphite_wasm";
|
||||
import type { PortfolioStore } from "@graphite/stores/portfolio";
|
||||
import type { MessageBody } from "@graphite/subscription-router";
|
||||
import type { MessageBody } from "/src/subscriptions-router";
|
||||
|
||||
export async function storeCurrentDocumentId(documentId: string) {
|
||||
const indexedDbStorage = idb.createStore("graphite", "store");
|
||||
@@ -65,7 +65,7 @@ export async function removeDocument(id: string, portfolio: PortfolioStore) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadFirstDocument(editor: Editor) {
|
||||
export async function loadFirstDocument(editor: EditorHandle) {
|
||||
const indexedDbStorage = idb.createStore("graphite", "store");
|
||||
|
||||
const previouslySavedDocuments = await idb.get<Record<string, MessageBody<"TriggerPersistenceWriteDocument">>>("documents", indexedDbStorage);
|
||||
@@ -87,19 +87,19 @@ export async function loadFirstDocument(editor: Editor) {
|
||||
|
||||
if (currentDocumentId !== undefined && String(currentDocumentId) in previouslySavedDocuments) {
|
||||
const doc = previouslySavedDocuments[String(currentDocumentId)];
|
||||
editor.handle.openAutoSavedDocument(doc.documentId, doc.details.name, doc.details.isSaved, doc.document, false);
|
||||
editor.handle.selectDocument(currentDocumentId);
|
||||
editor.openAutoSavedDocument(doc.documentId, doc.details.name, doc.details.isSaved, doc.document, false);
|
||||
editor.selectDocument(currentDocumentId);
|
||||
} else {
|
||||
const len = orderedSavedDocuments.length;
|
||||
if (len > 0) {
|
||||
const doc = orderedSavedDocuments[len - 1];
|
||||
editor.handle.openAutoSavedDocument(doc.documentId, doc.details.name, doc.details.isSaved, doc.document, false);
|
||||
editor.handle.selectDocument(doc.documentId);
|
||||
editor.openAutoSavedDocument(doc.documentId, doc.details.name, doc.details.isSaved, doc.document, false);
|
||||
editor.selectDocument(doc.documentId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadRestDocuments(editor: Editor) {
|
||||
export async function loadRestDocuments(editor: EditorHandle) {
|
||||
const indexedDbStorage = idb.createStore("graphite", "store");
|
||||
|
||||
const previouslySavedDocuments = await idb.get<Record<string, MessageBody<"TriggerPersistenceWriteDocument">>>("documents", indexedDbStorage);
|
||||
@@ -126,15 +126,15 @@ export async function loadRestDocuments(editor: Editor) {
|
||||
for (let i = currentIndex - 1; i >= 0; i--) {
|
||||
const { documentId, document, details } = orderedSavedDocuments[i];
|
||||
const { name, isSaved } = details;
|
||||
editor.handle.openAutoSavedDocument(documentId, name, isSaved, document, true);
|
||||
editor.openAutoSavedDocument(documentId, name, isSaved, document, true);
|
||||
}
|
||||
for (let i = currentIndex + 1; i < orderedSavedDocuments.length; i++) {
|
||||
const { documentId, document, details } = orderedSavedDocuments[i];
|
||||
const { name, isSaved } = details;
|
||||
editor.handle.openAutoSavedDocument(documentId, name, isSaved, document, false);
|
||||
editor.openAutoSavedDocument(documentId, name, isSaved, document, false);
|
||||
}
|
||||
|
||||
editor.handle.selectDocument(currentDocumentId);
|
||||
editor.selectDocument(currentDocumentId);
|
||||
}
|
||||
// No valid current document: open all remaining documents and select the last one
|
||||
else {
|
||||
@@ -143,10 +143,10 @@ export async function loadRestDocuments(editor: Editor) {
|
||||
for (let i = length - 2; i >= 0; i--) {
|
||||
const { documentId, document, details } = orderedSavedDocuments[i];
|
||||
const { name, isSaved } = details;
|
||||
editor.handle.openAutoSavedDocument(documentId, name, isSaved, document, true);
|
||||
editor.openAutoSavedDocument(documentId, name, isSaved, document, true);
|
||||
}
|
||||
|
||||
if (length > 0) editor.handle.selectDocument(orderedSavedDocuments[length - 1].documentId);
|
||||
if (length > 0) editor.selectDocument(orderedSavedDocuments[length - 1].documentId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,11 +177,11 @@ export async function saveEditorPreferences(preferences: unknown) {
|
||||
await idb.set("preferences", preferences, indexedDbStorage);
|
||||
}
|
||||
|
||||
export async function loadEditorPreferences(editor: Editor) {
|
||||
export async function loadEditorPreferences(editor: EditorHandle) {
|
||||
const indexedDbStorage = idb.createStore("graphite", "store");
|
||||
|
||||
const preferences = await idb.get<Record<string, unknown>>("preferences", indexedDbStorage);
|
||||
editor.handle.loadPreferences(preferences ? JSON.stringify(preferences) : undefined);
|
||||
editor.loadPreferences(preferences ? JSON.stringify(preferences) : undefined);
|
||||
}
|
||||
|
||||
export async function wipeDocuments() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import type { EditorHandle } from "@graphite/../wasm/pkg/graphite_wasm";
|
||||
|
||||
export function setupViewportResizeObserver(editor: Editor): () => void {
|
||||
export function setupViewportResizeObserver(editor: EditorHandle): () => void {
|
||||
const viewports = Array.from(window.document.querySelectorAll("[data-viewport-container]"));
|
||||
if (viewports.length <= 0) return () => {};
|
||||
|
||||
@@ -40,7 +40,7 @@ export function setupViewportResizeObserver(editor: Editor): () => void {
|
||||
continue;
|
||||
}
|
||||
|
||||
editor.handle.updateViewport(bounds.x, bounds.y, logicalWidth, logicalHeight, scale);
|
||||
editor.updateViewport(bounds.x, bounds.y, logicalWidth, logicalHeight, scale);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user