fileHandle refactor & fixes (#2252)

This commit is contained in:
David Luzar 2020-10-19 10:53:37 +02:00 committed by GitHub
parent 4a26845395
commit 1484c5a63b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 163 additions and 41 deletions

6
package-lock.json generated
View File

@ -4686,9 +4686,9 @@
"integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
}, },
"browser-nativefs": { "browser-nativefs": {
"version": "0.10.3", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/browser-nativefs/-/browser-nativefs-0.10.3.tgz", "resolved": "https://registry.npmjs.org/browser-nativefs/-/browser-nativefs-0.11.0.tgz",
"integrity": "sha512-WGcoR1aR+bxLlilaJ9fIzVOgSC4MaV+6phCTDGXV1sm+RElFuQFnJXR4BebBf2wEnjCsmGmTDNDTBE5KvVm2UQ==" "integrity": "sha512-JsCiw8DeZ5gB59i81e0O0pFSDK124hRoaYR7teNnuvIFVZRXa7vYJStwZxZAJS1tlmVdu5uuC6eIARskyG/IuQ=="
}, },
"browser-process-hrtime": { "browser-process-hrtime": {
"version": "1.0.0", "version": "1.0.0",

View File

@ -28,7 +28,7 @@
"@types/react": "16.9.52", "@types/react": "16.9.52",
"@types/react-dom": "16.9.8", "@types/react-dom": "16.9.8",
"@types/socket.io-client": "1.4.34", "@types/socket.io-client": "1.4.34",
"browser-nativefs": "0.10.3", "browser-nativefs": "0.11.0",
"firebase": "7.23.0", "firebase": "7.23.0",
"i18next-browser-languagedetector": "6.0.1", "i18next-browser-languagedetector": "6.0.1",
"lodash.throttle": "4.1.1", "lodash.throttle": "4.1.1",

View File

@ -59,8 +59,6 @@ export const actionClearCanvas = register({
showAriaLabel={useIsMobile()} showAriaLabel={useIsMobile()}
onClick={() => { onClick={() => {
if (window.confirm(t("alerts.clearReset"))) { if (window.confirm(t("alerts.clearReset"))) {
// TODO: Make this part of `AppState`.
(window as any).handle = null;
updateData(null); updateData(null);
} }
}} }}

View File

@ -85,12 +85,16 @@ export const actionChangeShouldAddWatermark = register({
export const actionSaveScene = register({ export const actionSaveScene = register({
name: "saveScene", name: "saveScene",
perform: (elements, appState, value) => { perform: async (elements, appState, value) => {
// TODO: Make this part of `AppState`. try {
saveAsJSON(elements, appState, (window as any).handle) const { fileHandle } = await saveAsJSON(elements, appState);
.catch(muteFSAbortError) return { commitToHistory: false, appState: { ...appState, fileHandle } };
.catch((error) => console.error(error)); } catch (error) {
if (error?.name !== "AbortError") {
console.error(error);
}
return { commitToHistory: false }; return { commitToHistory: false };
}
}, },
keyTest: (event) => { keyTest: (event) => {
return event.key === "s" && event[KEYS.CTRL_OR_CMD] && !event.shiftKey; return event.key === "s" && event[KEYS.CTRL_OR_CMD] && !event.shiftKey;
@ -109,11 +113,19 @@ export const actionSaveScene = register({
export const actionSaveAsScene = register({ export const actionSaveAsScene = register({
name: "saveAsScene", name: "saveAsScene",
perform: (elements, appState, value) => { perform: async (elements, appState, value) => {
saveAsJSON(elements, appState, null) try {
.catch(muteFSAbortError) const { fileHandle } = await saveAsJSON(elements, {
.catch((error) => console.error(error)); ...appState,
fileHandle: null,
});
return { commitToHistory: false, appState: { ...appState, fileHandle } };
} catch (error) {
if (error?.name !== "AbortError") {
console.error(error);
}
return { commitToHistory: false }; return { commitToHistory: false };
}
}, },
keyTest: (event) => { keyTest: (event) => {
return event.key === "s" && event.shiftKey && event[KEYS.CTRL_OR_CMD]; return event.key === "s" && event.shiftKey && event[KEYS.CTRL_OR_CMD];

View File

@ -5,6 +5,7 @@ import {
UpdaterFn, UpdaterFn,
ActionFilterFn, ActionFilterFn,
ActionName, ActionName,
ActionResult,
} from "./types"; } from "./types";
import { ExcalidrawElement } from "../element/types"; import { ExcalidrawElement } from "../element/types";
import { AppState } from "../types"; import { AppState } from "../types";
@ -13,7 +14,7 @@ import { t } from "../i18n";
export class ActionManager implements ActionsManagerInterface { export class ActionManager implements ActionsManagerInterface {
actions = {} as ActionsManagerInterface["actions"]; actions = {} as ActionsManagerInterface["actions"];
updater: UpdaterFn; updater: (actionResult: ActionResult | Promise<ActionResult>) => void;
getAppState: () => Readonly<AppState>; getAppState: () => Readonly<AppState>;
@ -24,7 +25,15 @@ export class ActionManager implements ActionsManagerInterface {
getAppState: () => AppState, getAppState: () => AppState,
getElementsIncludingDeleted: () => readonly ExcalidrawElement[], getElementsIncludingDeleted: () => readonly ExcalidrawElement[],
) { ) {
this.updater = updater; this.updater = (actionResult) => {
if (actionResult && "then" in actionResult) {
actionResult.then((actionResult) => {
return updater(actionResult);
});
} else {
return updater(actionResult);
}
};
this.getAppState = getAppState; this.getAppState = getAppState;
this.getElementsIncludingDeleted = getElementsIncludingDeleted; this.getElementsIncludingDeleted = getElementsIncludingDeleted;
} }

View File

@ -16,9 +16,9 @@ type ActionFn = (
elements: readonly ExcalidrawElement[], elements: readonly ExcalidrawElement[],
appState: Readonly<AppState>, appState: Readonly<AppState>,
formData: any, formData: any,
) => ActionResult; ) => ActionResult | Promise<ActionResult>;
export type UpdaterFn = (res: ActionResult, commitToHistory?: boolean) => void; export type UpdaterFn = (res: ActionResult) => void;
export type ActionFilterFn = (action: Action) => void; export type ActionFilterFn = (action: Action) => void;
export type ActionName = export type ActionName =

View File

@ -69,6 +69,7 @@ export const getDefaultAppState = (): Omit<
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
isLibraryOpen: false, isLibraryOpen: false,
fileHandle: null,
}; };
}; };
@ -145,6 +146,7 @@ const APP_STATE_STORAGE_CONF = (<
zoom: { browser: true, export: false }, zoom: { browser: true, export: false },
offsetTop: { browser: false, export: false }, offsetTop: { browser: false, export: false },
offsetLeft: { browser: false, export: false }, offsetLeft: { browser: false, export: false },
fileHandle: { browser: false, export: false },
}); });
const _clearAppStateForStorage = <ExportType extends "export" | "browser">( const _clearAppStateForStorage = <ExportType extends "export" | "browser">(

View File

@ -160,7 +160,7 @@ export const parseClipboard = async (
export const copyCanvasToClipboardAsPng = async (canvas: HTMLCanvasElement) => export const copyCanvasToClipboardAsPng = async (canvas: HTMLCanvasElement) =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
try { try {
canvas.toBlob(async (blob: any) => { canvas.toBlob(async (blob) => {
try { try {
await navigator.clipboard.write([ await navigator.clipboard.write([
new window.ClipboardItem({ "image/png": blob }), new window.ClipboardItem({ "image/png": blob }),

View File

@ -558,7 +558,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
return; return;
} }
const fileHandle = launchParams.files[0]; const fileHandle = launchParams.files[0];
const blob = await fileHandle.getFile(); const blob: Blob = await fileHandle.getFile();
blob.handle = fileHandle; blob.handle = fileHandle;
loadFromBlob(blob, this.state) loadFromBlob(blob, this.state)
.then(({ elements, appState }) => .then(({ elements, appState }) =>
@ -3845,7 +3845,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
// but can be safely ignored on older releases. // but can be safely ignored on older releases.
const item = event.dataTransfer.items[0]; const item = event.dataTransfer.items[0];
// TODO: Make this part of `AppState`. // TODO: Make this part of `AppState`.
(window as any).handle = await (item as any).getAsFileSystemHandle(); (file as any).handle = await (item as any).getAsFileSystemHandle();
} catch (error) { } catch (error) {
console.warn(error.name, error.message); console.warn(error.name, error.message);
} }

View File

@ -4,6 +4,7 @@ import { t } from "../i18n";
import { AppState } from "../types"; import { AppState } from "../types";
import { LibraryData, ImportedDataState } from "./types"; import { LibraryData, ImportedDataState } from "./types";
import { calculateScrollCenter } from "../scene"; import { calculateScrollCenter } from "../scene";
import { MIME_TYPES } from "../constants";
export const parseFileContents = async (blob: Blob | File) => { export const parseFileContents = async (blob: Blob | File) => {
let contents: string; let contents: string;
@ -53,16 +54,22 @@ export const parseFileContents = async (blob: Blob | File) => {
return contents; return contents;
}; };
const getMimeType = (blob: Blob): string => {
if (blob.type) {
return blob.type;
}
const name = blob.name || "";
if (/\.(excalidraw|json)$/.test(name)) {
return "application/json";
}
return "";
};
export const loadFromBlob = async ( export const loadFromBlob = async (
blob: any, blob: Blob,
/** @see restore.localAppState */ /** @see restore.localAppState */
localAppState: AppState | null, localAppState: AppState | null,
) => { ) => {
if (blob.handle) {
// TODO: Make this part of `AppState`.
(window as any).handle = blob.handle;
}
const contents = await parseFileContents(blob); const contents = await parseFileContents(blob);
try { try {
const data: ImportedDataState = JSON.parse(contents); const data: ImportedDataState = JSON.parse(contents);
@ -74,6 +81,13 @@ export const loadFromBlob = async (
elements: data.elements, elements: data.elements,
appState: { appState: {
appearance: localAppState?.appearance, appearance: localAppState?.appearance,
fileHandle:
blob.handle &&
["application/json", MIME_TYPES.excalidraw].includes(
getMimeType(blob),
)
? blob.handle
: null,
...cleanAppStateForExport(data.appState || {}), ...cleanAppStateForExport(data.appState || {}),
...(localAppState ...(localAppState
? calculateScrollCenter(data.elements || [], localAppState, null) ? calculateScrollCenter(data.elements || [], localAppState, null)

View File

@ -66,9 +66,6 @@ export type SocketUpdateDataIncoming =
type: "INVALID_RESPONSE"; type: "INVALID_RESPONSE";
}; };
// TODO: Make this part of `AppState`.
(window as any).handle = null;
const byteToHex = (byte: number): string => `0${byte.toString(16)}`.slice(-2); const byteToHex = (byte: number): string => `0${byte.toString(16)}`.slice(-2);
const generateRandomID = async () => { const generateRandomID = async () => {

View File

@ -27,23 +27,23 @@ export const serializeAsJSON = (
export const saveAsJSON = async ( export const saveAsJSON = async (
elements: readonly ExcalidrawElement[], elements: readonly ExcalidrawElement[],
appState: AppState, appState: AppState,
fileHandle: any,
) => { ) => {
const serialized = serializeAsJSON(elements, appState); const serialized = serializeAsJSON(elements, appState);
const blob = new Blob([serialized], { const blob = new Blob([serialized], {
type: "application/json", type: "application/json",
}); });
const name = `${appState.name}.excalidraw`;
// TODO: Make this part of `AppState`. const fileHandle = await fileSave(
(window as any).handle = await fileSave(
blob, blob,
{ {
fileName: name, fileName: appState.name,
description: "Excalidraw file", description: "Excalidraw file",
extensions: [".excalidraw"], extensions: [".excalidraw"],
}, },
fileHandle || null, appState.fileHandle,
); );
return { fileHandle };
}; };
export const loadFromJSON = async (localAppState: AppState) => { export const loadFromJSON = async (localAppState: AppState) => {

View File

@ -4,7 +4,7 @@ import { loadLibrary, saveLibrary } from "./localStorage";
export class Library { export class Library {
/** imports library (currently merges, removing duplicates) */ /** imports library (currently merges, removing duplicates) */
static async importLibrary(blob: any) { static async importLibrary(blob: Blob) {
const libraryFile = await loadLibraryFromBlob(blob); const libraryFile = await loadLibraryFromBlob(blob);
if (!libraryFile || !libraryFile.library) { if (!libraryFile || !libraryFile.library) {
return; return;

7
src/global.d.ts vendored
View File

@ -76,3 +76,10 @@ type CallableType<T extends (...args: any[]) => any> = (
type ForwardRef<T, P = any> = Parameters< type ForwardRef<T, P = any> = Parameters<
CallableType<React.ForwardRefRenderFunction<T, P>> CallableType<React.ForwardRefRenderFunction<T, P>>
>[1]; >[1];
// --------------------------------------------------------------------------—
interface Blob {
handle?: import("browser-nativefs").FileSystemHandle;
name?: string;
}

View File

@ -1 +0,0 @@
declare module "browser-nativefs";

View File

@ -28,6 +28,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -475,6 +476,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -928,6 +930,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": false, "isBindingEnabled": false,
@ -1690,6 +1693,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -1880,6 +1884,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -2324,6 +2329,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -2563,6 +2569,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -2713,6 +2720,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -3176,6 +3184,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -3470,6 +3479,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -3660,6 +3670,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -3890,6 +3901,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -4128,6 +4140,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -4497,6 +4510,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -4778,6 +4792,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -5071,6 +5086,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -5265,6 +5281,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -5415,6 +5432,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -5854,6 +5872,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -6158,6 +6177,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -8124,6 +8144,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -8472,6 +8493,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -8713,6 +8735,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -8952,6 +8975,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -9253,6 +9277,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -9403,6 +9428,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -9553,6 +9579,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -9703,6 +9730,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -9879,6 +9907,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -10055,6 +10084,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -10231,6 +10261,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -10407,6 +10438,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -10557,6 +10589,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -10707,6 +10740,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -10883,6 +10917,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -11033,6 +11068,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -11209,6 +11245,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -11911,6 +11948,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -12150,6 +12188,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -12238,6 +12277,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -12324,6 +12364,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -13202,6 +13243,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -13639,6 +13681,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -13989,6 +14032,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -14256,6 +14300,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -14444,6 +14489,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -15269,6 +15315,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -15991,6 +16038,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -16614,6 +16662,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -17142,6 +17191,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -17624,6 +17674,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -18017,6 +18068,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -18325,6 +18377,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -18552,6 +18605,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -19430,6 +19484,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -20203,6 +20258,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -20875,6 +20931,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -21450,6 +21507,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -21600,6 +21658,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -21894,6 +21953,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -22188,6 +22248,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -22338,6 +22399,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -22520,6 +22582,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -22755,6 +22818,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -23065,6 +23129,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -23890,6 +23955,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -24184,6 +24250,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -24478,6 +24545,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -24843,6 +24911,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -24996,6 +25065,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -25303,6 +25373,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -25544,6 +25615,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -25857,6 +25929,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -25943,6 +26016,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -26093,6 +26167,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -26900,6 +26975,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -26986,6 +27062,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -27724,6 +27801,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -28115,6 +28193,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -28374,6 +28453,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -28462,6 +28542,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -28940,6 +29021,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
@ -29026,6 +29108,7 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,

View File

@ -96,6 +96,7 @@ export type AppState = {
offsetLeft: number; offsetLeft: number;
isLibraryOpen: boolean; isLibraryOpen: boolean;
fileHandle: import("browser-nativefs").FileSystemHandle | null;
}; };
export type PointerCoords = Readonly<{ export type PointerCoords = Readonly<{