prompt when loading external scene before overriding local one (#1862)
This commit is contained in:
parent
1b9b824c70
commit
d5e7d08586
@ -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,
|
||||
@ -356,6 +357,39 @@ 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");
|
||||
@ -363,20 +397,28 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
/^#json=([0-9]+),([a-zA-Z0-9_-]+)$/,
|
||||
);
|
||||
|
||||
const isCollaborationScene = getCollaborationLinkData(window.location.href);
|
||||
let scene = await loadScene(null);
|
||||
|
||||
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]);
|
||||
let isCollaborationScene = !!getCollaborationLinkData(window.location.href);
|
||||
const isExternalScene = !!(id || jsonMatch || isCollaborationScene);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,9 +426,10 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
this.setState({ isLoading: false });
|
||||
}
|
||||
|
||||
// run this last else the `isLoading` state
|
||||
if (isCollaborationScene) {
|
||||
this.initializeSocketClient({ showLoadingState: true });
|
||||
} else if (scene) {
|
||||
this.syncActionResult(scene);
|
||||
}
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
@ -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";
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user