Skip to content

Commit

Permalink
Warn on invalid JSON file (excalidraw#1159)
Browse files Browse the repository at this point in the history
* add error dialog

* show error modal on file dnd

* add locales

* Update src/locales/en.json

Co-Authored-By: Lipis <[email protected]>

* 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 <[email protected]>
Co-authored-by: Lipis <[email protected]>
  • Loading branch information
3 people authored Apr 3, 2020
1 parent 2be34ef commit 0c9459e
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 7 deletions.
11 changes: 8 additions & 3 deletions src/actions/actionExport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,14 @@ export const actionLoadScene = register({
perform: (
elements,
appState,
{ elements: loadedElements, appState: loadedAppState },
{ elements: loadedElements, appState: loadedAppState, error },
) => {
return {
elements: loadedElements,
appState: loadedAppState,
appState: {
...loadedAppState,
errorMessage: error,
},
commitToHistory: false,
};
},
Expand All @@ -84,7 +87,9 @@ export const actionLoadScene = register({
.then(({ elements, appState }) => {
updateData({ elements: elements, appState: appState });
})
.catch((error) => console.error(error));
.catch((error) => {
updateData({ error: error });
});
}}
/>
),
Expand Down
2 changes: 2 additions & 0 deletions src/appState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const DEFAULT_FONT = "20px Virgil";
export function getDefaultAppState(): AppState {
return {
isLoading: false,
errorMessage: null,
draggingElement: null,
resizingElement: null,
multiElement: null,
Expand Down Expand Up @@ -52,6 +53,7 @@ export function clearAppStateForLocalStorage(appState: AppState) {
collaborators,
isCollaborating,
isLoading,
errorMessage,
...exportedState
} = appState;
return exportedState;
Expand Down
8 changes: 6 additions & 2 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,13 @@ export class App extends React.Component<any, AppState> {
}),
)
.catch((error) => {
console.error(error);
this.setState({ isLoading: false });
this.setState({ isLoading: false, errorMessage: error });
});
} else {
this.setState({
isLoading: false,
errorMessage: t("alerts.couldNotLoadInvalidFile"),
});
}
}}
>
Expand Down
36 changes: 36 additions & 0 deletions src/components/ErrorDialog.tsx
Original file line number Diff line number Diff line change
@@ -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 changes: 7 additions & 0 deletions src/components/LayerUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { MobileMenu } from "./MobileMenu";
import { ZoomActions, SelectedShapeActions, ShapesSwitcher } from "./Actions";
import { Section } from "./Section";
import { RoomDialog } from "./RoomDialog";
import { ErrorDialog } from "./ErrorDialog";
import { LoadingMessage } from "./LoadingMessage";

interface LayerUIProps {
Expand Down Expand Up @@ -105,6 +106,12 @@ export const LayerUI = React.memo(
) : (
<>
{appState.isLoading && <LoadingMessage />}
{appState.errorMessage && (
<ErrorDialog
message={appState.errorMessage}
onClose={() => setAppState({ errorMessage: null })}
/>
)}
<FixedSideContainer side="top">
<HintViewer appState={appState} elements={elements} />
<div className="App-menu App-menu_top">
Expand Down
5 changes: 3 additions & 2 deletions src/data/blob.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getDefaultAppState } from "../appState";
import { DataState } from "./types";
import { restore } from "./restore";
import { t } from "../i18n";

export async function loadFromBlob(blob: any) {
const updateAppState = (contents: string) => {
Expand All @@ -10,7 +11,7 @@ export async function loadFromBlob(blob: any) {
try {
const data = JSON.parse(contents);
if (data.type !== "excalidraw") {
throw new Error("Cannot load invalid json");
throw new Error(t("alerts.couldNotLoadInvalidFile"));
}
elements = data.elements || [];
appState = { ...defaultAppState, ...data.appState };
Expand Down Expand Up @@ -39,7 +40,7 @@ export async function loadFromBlob(blob: any) {
}
const { elements, appState } = updateAppState(contents);
if (!elements.length) {
return Promise.reject("Cannot load invalid json");
return Promise.reject(t("alerts.couldNotLoadInvalidFile"));
}
return new Promise<DataState>((resolve) => {
resolve(restore(elements, appState, { scrollToContent: true }));
Expand Down
4 changes: 4 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"alerts": {
"clearReset": "This will clear the whole canvas. Are you sure?",
"couldNotCreateShareableLink": "Couldn't create shareable link.",
"couldNotLoadInvalidFile": "Couldn't load invalid file",
"importBackendFailed": "Importing from backend failed.",
"cannotExportEmptyCanvas": "Cannot export empty canvas.",
"couldNotCopyToClipboard": "Couldn't copy to clipboard. Try using Chrome browser.",
Expand Down Expand Up @@ -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_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."
},
"errorDialog": {
"title": "Error"
}
}
Loading

0 comments on commit 0c9459e

Please sign in to comment.