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,
|
CANVAS_ONLY_ACTIONS,
|
||||||
DEFAULT_VERTICAL_ALIGN,
|
DEFAULT_VERTICAL_ALIGN,
|
||||||
GRID_SIZE,
|
GRID_SIZE,
|
||||||
|
LOCAL_STORAGE_KEY_COLLAB_FORCE_FLAG,
|
||||||
} from "../constants";
|
} from "../constants";
|
||||||
import {
|
import {
|
||||||
INITAL_SCENE_UPDATE_TIMEOUT,
|
INITAL_SCENE_UPDATE_TIMEOUT,
|
||||||
@ -356,6 +357,39 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
this.onSceneUpdated();
|
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 () => {
|
private initializeScene = async () => {
|
||||||
const searchParams = new URLSearchParams(window.location.search);
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
const id = searchParams.get("id");
|
const id = searchParams.get("id");
|
||||||
@ -363,20 +397,28 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
/^#json=([0-9]+),([a-zA-Z0-9_-]+)$/,
|
/^#json=([0-9]+),([a-zA-Z0-9_-]+)$/,
|
||||||
);
|
);
|
||||||
|
|
||||||
const isCollaborationScene = getCollaborationLinkData(window.location.href);
|
let scene = await loadScene(null);
|
||||||
|
|
||||||
if (!isCollaborationScene) {
|
let isCollaborationScene = !!getCollaborationLinkData(window.location.href);
|
||||||
let scene: ResolutionType<typeof loadScene> | undefined;
|
const isExternalScene = !!(id || jsonMatch || isCollaborationScene);
|
||||||
// Backwards compatibility with legacy url format
|
|
||||||
if (id) {
|
if (isExternalScene) {
|
||||||
scene = await loadScene(id);
|
if (
|
||||||
} else if (jsonMatch) {
|
this.shouldForceLoadScene(scene) ||
|
||||||
scene = await loadScene(jsonMatch[1], jsonMatch[2]);
|
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 {
|
} else {
|
||||||
scene = await loadScene(null);
|
isCollaborationScene = false;
|
||||||
}
|
window.history.replaceState({}, "Excalidraw", window.location.origin);
|
||||||
if (scene) {
|
|
||||||
this.syncActionResult(scene);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,9 +426,10 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
this.setState({ isLoading: false });
|
this.setState({ isLoading: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
// run this last else the `isLoading` state
|
|
||||||
if (isCollaborationScene) {
|
if (isCollaborationScene) {
|
||||||
this.initializeSocketClient({ showLoadingState: true });
|
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) => {
|
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 (
|
if (
|
||||||
this.state.isCollaborating &&
|
this.state.isCollaborating &&
|
||||||
globalSceneState.getElements().length > 0
|
globalSceneState.getElements().length > 0
|
||||||
|
@ -77,3 +77,5 @@ export const DEFAULT_VERTICAL_ALIGN = "top";
|
|||||||
export const CANVAS_ONLY_ACTIONS = ["selectAll"];
|
export const CANVAS_ONLY_ACTIONS = ["selectAll"];
|
||||||
|
|
||||||
export const GRID_SIZE = 20; // TODO make it configurable?
|
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
|
// the private key is used to decrypt the content from the server, take
|
||||||
// extra care not to leak it
|
// extra care not to leak it
|
||||||
data = await importFromBackend(id, privateKey);
|
data = await importFromBackend(id, privateKey);
|
||||||
window.history.replaceState({}, "Excalidraw", window.location.origin);
|
|
||||||
} else {
|
} else {
|
||||||
data = restoreFromLocalStorage();
|
data = restoreFromLocalStorage();
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,8 @@
|
|||||||
"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.",
|
||||||
"decryptFailed": "Couldn't decrypt data.",
|
"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": {
|
"toolBar": {
|
||||||
"selection": "Selection",
|
"selection": "Selection",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user