瀏覽代碼

Warn on invalid JSON file (#1159)

* add error dialog

* show error modal on file dnd

* add locales

* Update src/locales/en.json

Co-Authored-By: Lipis <lipiridis@gmail.com>

* Update src/data/blob.ts

* Update src/data/blob.ts

* fix titles, update snapshots

* make modal smaller

* fix dnd wrong file type

* reset errorMessage

Co-authored-by: Faustino Kialungila <faustino.kialungila@gmail.com>
Co-authored-by: Lipis <lipiridis@gmail.com>
Kostas Bariotis 5 年之前
父節點
當前提交
0c9459e9e5

+ 8 - 3
src/actions/actionExport.tsx

@@ -64,11 +64,14 @@ export const actionLoadScene = register({
   perform: (
   perform: (
     elements,
     elements,
     appState,
     appState,
-    { elements: loadedElements, appState: loadedAppState },
+    { elements: loadedElements, appState: loadedAppState, error },
   ) => {
   ) => {
     return {
     return {
       elements: loadedElements,
       elements: loadedElements,
-      appState: loadedAppState,
+      appState: {
+        ...loadedAppState,
+        errorMessage: error,
+      },
       commitToHistory: false,
       commitToHistory: false,
     };
     };
   },
   },
@@ -84,7 +87,9 @@ export const actionLoadScene = register({
           .then(({ elements, appState }) => {
           .then(({ elements, appState }) => {
             updateData({ elements: elements, appState: appState });
             updateData({ elements: elements, appState: appState });
           })
           })
-          .catch((error) => console.error(error));
+          .catch((error) => {
+            updateData({ error: error });
+          });
       }}
       }}
     />
     />
   ),
   ),

+ 2 - 0
src/appState.ts

@@ -6,6 +6,7 @@ export const DEFAULT_FONT = "20px Virgil";
 export function getDefaultAppState(): AppState {
 export function getDefaultAppState(): AppState {
   return {
   return {
     isLoading: false,
     isLoading: false,
+    errorMessage: null,
     draggingElement: null,
     draggingElement: null,
     resizingElement: null,
     resizingElement: null,
     multiElement: null,
     multiElement: null,
@@ -52,6 +53,7 @@ export function clearAppStateForLocalStorage(appState: AppState) {
     collaborators,
     collaborators,
     isCollaborating,
     isCollaborating,
     isLoading,
     isLoading,
+    errorMessage,
     ...exportedState
     ...exportedState
   } = appState;
   } = appState;
   return exportedState;
   return exportedState;

+ 6 - 2
src/components/App.tsx

@@ -247,9 +247,13 @@ export class App extends React.Component<any, AppState> {
                     }),
                     }),
                   )
                   )
                   .catch((error) => {
                   .catch((error) => {
-                    console.error(error);
-                    this.setState({ isLoading: false });
+                    this.setState({ isLoading: false, errorMessage: error });
                   });
                   });
+              } else {
+                this.setState({
+                  isLoading: false,
+                  errorMessage: t("alerts.couldNotLoadInvalidFile"),
+                });
               }
               }
             }}
             }}
           >
           >

+ 36 - 0
src/components/ErrorDialog.tsx

@@ -0,0 +1,36 @@
+import React, { useState } from "react";
+import { t } from "../i18n";
+
+import { Dialog } from "./Dialog";
+
+export function ErrorDialog({
+  message,
+  onClose,
+}: {
+  message: string;
+  onClose?: () => void;
+}) {
+  const [modalIsShown, setModalIsShown] = useState(!!message);
+
+  const handleClose = React.useCallback(() => {
+    setModalIsShown(false);
+
+    if (onClose) {
+      onClose();
+    }
+  }, [onClose]);
+
+  return (
+    <>
+      {modalIsShown && (
+        <Dialog
+          maxWidth={500}
+          onCloseRequest={handleClose}
+          title={t("errorDialog.title")}
+        >
+          <div>{message}</div>
+        </Dialog>
+      )}
+    </>
+  );
+}

+ 7 - 0
src/components/LayerUI.tsx

@@ -22,6 +22,7 @@ import { MobileMenu } from "./MobileMenu";
 import { ZoomActions, SelectedShapeActions, ShapesSwitcher } from "./Actions";
 import { ZoomActions, SelectedShapeActions, ShapesSwitcher } from "./Actions";
 import { Section } from "./Section";
 import { Section } from "./Section";
 import { RoomDialog } from "./RoomDialog";
 import { RoomDialog } from "./RoomDialog";
+import { ErrorDialog } from "./ErrorDialog";
 import { LoadingMessage } from "./LoadingMessage";
 import { LoadingMessage } from "./LoadingMessage";
 
 
 interface LayerUIProps {
 interface LayerUIProps {
@@ -105,6 +106,12 @@ export const LayerUI = React.memo(
     ) : (
     ) : (
       <>
       <>
         {appState.isLoading && <LoadingMessage />}
         {appState.isLoading && <LoadingMessage />}
+        {appState.errorMessage && (
+          <ErrorDialog
+            message={appState.errorMessage}
+            onClose={() => setAppState({ errorMessage: null })}
+          />
+        )}
         <FixedSideContainer side="top">
         <FixedSideContainer side="top">
           <HintViewer appState={appState} elements={elements} />
           <HintViewer appState={appState} elements={elements} />
           <div className="App-menu App-menu_top">
           <div className="App-menu App-menu_top">

+ 3 - 2
src/data/blob.ts

@@ -1,6 +1,7 @@
 import { getDefaultAppState } from "../appState";
 import { getDefaultAppState } from "../appState";
 import { DataState } from "./types";
 import { DataState } from "./types";
 import { restore } from "./restore";
 import { restore } from "./restore";
+import { t } from "../i18n";
 
 
 export async function loadFromBlob(blob: any) {
 export async function loadFromBlob(blob: any) {
   const updateAppState = (contents: string) => {
   const updateAppState = (contents: string) => {
@@ -10,7 +11,7 @@ export async function loadFromBlob(blob: any) {
     try {
     try {
       const data = JSON.parse(contents);
       const data = JSON.parse(contents);
       if (data.type !== "excalidraw") {
       if (data.type !== "excalidraw") {
-        throw new Error("Cannot load invalid json");
+        throw new Error(t("alerts.couldNotLoadInvalidFile"));
       }
       }
       elements = data.elements || [];
       elements = data.elements || [];
       appState = { ...defaultAppState, ...data.appState };
       appState = { ...defaultAppState, ...data.appState };
@@ -39,7 +40,7 @@ export async function loadFromBlob(blob: any) {
   }
   }
   const { elements, appState } = updateAppState(contents);
   const { elements, appState } = updateAppState(contents);
   if (!elements.length) {
   if (!elements.length) {
-    return Promise.reject("Cannot load invalid json");
+    return Promise.reject(t("alerts.couldNotLoadInvalidFile"));
   }
   }
   return new Promise<DataState>((resolve) => {
   return new Promise<DataState>((resolve) => {
     resolve(restore(elements, appState, { scrollToContent: true }));
     resolve(restore(elements, appState, { scrollToContent: true }));

+ 4 - 0
src/locales/en.json

@@ -74,6 +74,7 @@
   "alerts": {
   "alerts": {
     "clearReset": "This will clear the whole canvas. Are you sure?",
     "clearReset": "This will clear the whole canvas. Are you sure?",
     "couldNotCreateShareableLink": "Couldn't create shareable link.",
     "couldNotCreateShareableLink": "Couldn't create shareable link.",
+    "couldNotLoadInvalidFile": "Couldn't load invalid file",
     "importBackendFailed": "Importing from backend failed.",
     "importBackendFailed": "Importing from backend failed.",
     "cannotExportEmptyCanvas": "Cannot export empty canvas.",
     "cannotExportEmptyCanvas": "Cannot export empty canvas.",
     "couldNotCopyToClipboard": "Couldn't copy to clipboard. Try using Chrome browser.",
     "couldNotCopyToClipboard": "Couldn't copy to clipboard. Try using Chrome browser.",
@@ -123,5 +124,8 @@
     "desc_persistenceWarning": "Note that the scene data is shared across collaborators in a P2P fashion, and not persisted to our server. Thus, if all of you disconnect, you will loose the data unless you export it to a file or a shareable link.",
     "desc_persistenceWarning": "Note that the scene data is shared across collaborators in a P2P fashion, and not persisted to our server. Thus, if all of you disconnect, you will loose the data unless you export it to a file or a shareable link.",
     "desc_shareLink": "Share this link with anyone you want to collaborate with:",
     "desc_shareLink": "Share this link with anyone you want to collaborate with:",
     "desc_exitSession": "Stopping the session will disconnect your from the room, but you'll be able to continue working with the scene, locally. Note that this won't affect other people, and they'll still be able to collaborate on their version."
     "desc_exitSession": "Stopping the session will disconnect your from the room, but you'll be able to continue working with the scene, locally. Note that this won't affect other people, and they'll still be able to collaborate on their version."
+  },
+  "errorDialog": {
+    "title": "Error"
   }
   }
 }
 }

+ 41 - 0
src/tests/__snapshots__/regressionTests.test.tsx.snap

@@ -16,6 +16,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -202,6 +203,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -311,6 +313,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -560,6 +563,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -705,6 +709,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -886,6 +891,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -1072,6 +1078,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -1354,6 +1361,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -1949,6 +1957,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -2058,6 +2067,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -2167,6 +2177,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -2276,6 +2287,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -2407,6 +2419,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -2538,6 +2551,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -2669,6 +2683,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -2778,6 +2793,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -2887,6 +2903,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -3018,6 +3035,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -3127,6 +3145,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -3178,6 +3197,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -3863,6 +3883,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -4224,6 +4245,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -4513,6 +4535,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -4730,6 +4753,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -4875,6 +4899,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -5524,6 +5549,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -6101,6 +6127,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -6606,6 +6633,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -7039,6 +7067,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -7436,6 +7465,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -7761,6 +7791,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -8014,6 +8045,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -8195,6 +8227,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -8880,6 +8913,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -9493,6 +9527,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -10034,6 +10069,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -10503,6 +10539,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -10746,6 +10783,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -10795,6 +10833,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -10846,6 +10885,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,
@@ -11127,6 +11167,7 @@ Object {
   "editingElement": null,
   "editingElement": null,
   "elementLocked": false,
   "elementLocked": false,
   "elementType": "selection",
   "elementType": "selection",
+  "errorMessage": null,
   "exportBackground": true,
   "exportBackground": true,
   "isCollaborating": false,
   "isCollaborating": false,
   "isLoading": false,
   "isLoading": false,

+ 1 - 0
src/types.ts

@@ -11,6 +11,7 @@ export type Point = Readonly<RoughPoint>;
 
 
 export type AppState = {
 export type AppState = {
   isLoading: boolean;
   isLoading: boolean;
+  errorMessage: string | null;
   draggingElement: ExcalidrawElement | null;
   draggingElement: ExcalidrawElement | null;
   resizingElement: ExcalidrawElement | null;
   resizingElement: ExcalidrawElement | null;
   multiElement: ExcalidrawLinearElement | null;
   multiElement: ExcalidrawLinearElement | null;