Skip to content

Commit

Permalink
prompt when loading external scene before overriding local one (excal…
Browse files Browse the repository at this point in the history
  • Loading branch information
dwelle authored Jul 8, 2020
1 parent 1b9b824 commit d5e7d08
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 15 deletions.
78 changes: 65 additions & 13 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ import {
CANVAS_ONLY_ACTIONS,
DEFAULT_VERTICAL_ALIGN,
GRID_SIZE,
LOCAL_STORAGE_KEY_COLLAB_FORCE_FLAG,
} from "../constants";
import {
INITAL_SCENE_UPDATE_TIMEOUT,
Expand Down Expand Up @@ -356,37 +357,79 @@ class App extends React.Component<ExcalidrawProps, AppState> {
this.onSceneUpdated();
};

private shouldForceLoadScene(
scene: ResolutionType<typeof loadScene>,
): boolean {
if (!scene.elements.length) {
return true;
}

const roomMatch = getCollaborationLinkData(window.location.href);

if (!roomMatch) {
return false;
}
const collabForceLoadFlag = localStorage.getItem(
LOCAL_STORAGE_KEY_COLLAB_FORCE_FLAG,
);
if (collabForceLoadFlag) {
try {
const {
room: previousRoom,
timestamp,
}: { room: string; timestamp: number } = JSON.parse(
collabForceLoadFlag,
);
// if loading same room as the one previously unloaded within 15sec
// force reload without prompting
if (previousRoom === roomMatch[1] && Date.now() - timestamp < 15000) {
return true;
}
} catch {}
}
return false;
}

private initializeScene = async () => {
const searchParams = new URLSearchParams(window.location.search);
const id = searchParams.get("id");
const jsonMatch = window.location.hash.match(
/^#json=([0-9]+),([a-zA-Z0-9_-]+)$/,
);

const isCollaborationScene = getCollaborationLinkData(window.location.href);
let scene = await loadScene(null);

let isCollaborationScene = !!getCollaborationLinkData(window.location.href);
const isExternalScene = !!(id || jsonMatch || isCollaborationScene);

if (!isCollaborationScene) {
let scene: ResolutionType<typeof loadScene> | undefined;
// Backwards compatibility with legacy url format
if (id) {
scene = await loadScene(id);
} else if (jsonMatch) {
scene = await loadScene(jsonMatch[1], jsonMatch[2]);
if (isExternalScene) {
if (
this.shouldForceLoadScene(scene) ||
window.confirm(t("alerts.loadSceneOverridePrompt"))
) {
// Backwards compatibility with legacy url format
if (id) {
scene = await loadScene(id);
} else if (jsonMatch) {
scene = await loadScene(jsonMatch[1], jsonMatch[2]);
}
if (!isCollaborationScene) {
window.history.replaceState({}, "Excalidraw", window.location.origin);
}
} else {
scene = await loadScene(null);
}
if (scene) {
this.syncActionResult(scene);
isCollaborationScene = false;
window.history.replaceState({}, "Excalidraw", window.location.origin);
}
}

if (this.state.isLoading) {
this.setState({ isLoading: false });
}

// run this last else the `isLoading` state
if (isCollaborationScene) {
this.initializeSocketClient({ showLoadingState: true });
} else if (scene) {
this.syncActionResult(scene);
}
};

Expand Down Expand Up @@ -515,6 +558,15 @@ class App extends React.Component<ExcalidrawProps, AppState> {
}

private beforeUnload = withBatchedUpdates((event: BeforeUnloadEvent) => {
if (this.state.isCollaborating && this.portal.roomID) {
localStorage.setItem(
LOCAL_STORAGE_KEY_COLLAB_FORCE_FLAG,
JSON.stringify({
timestamp: Date.now(),
room: this.portal.roomID,
}),
);
}
if (
this.state.isCollaborating &&
globalSceneState.getElements().length > 0
Expand Down
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,5 @@ export const DEFAULT_VERTICAL_ALIGN = "top";
export const CANVAS_ONLY_ACTIONS = ["selectAll"];

export const GRID_SIZE = 20; // TODO make it configurable?

export const LOCAL_STORAGE_KEY_COLLAB_FORCE_FLAG = "collabLinkForceLoadFlag";
1 change: 0 additions & 1 deletion src/data/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,6 @@ export const loadScene = async (id: string | null, privateKey?: string) => {
// the private key is used to decrypt the content from the server, take
// extra care not to leak it
data = await importFromBackend(id, privateKey);
window.history.replaceState({}, "Excalidraw", window.location.origin);
} else {
data = restoreFromLocalStorage();
}
Expand Down
3 changes: 2 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@
"cannotExportEmptyCanvas": "Cannot export empty canvas.",
"couldNotCopyToClipboard": "Couldn't copy to clipboard. Try using Chrome browser.",
"decryptFailed": "Couldn't decrypt data.",
"uploadedSecurly": "The upload has been secured with end-to-end encryption, which means that Excalidraw server and third parties can't read the content."
"uploadedSecurly": "The upload has been secured with end-to-end encryption, which means that Excalidraw server and third parties can't read the content.",
"loadSceneOverridePrompt": "Loading external drawing will replace your existing content. Do you wish to continue?"
},
"toolBar": {
"selection": "Selection",
Expand Down

0 comments on commit d5e7d08

Please sign in to comment.