feat: Implement the Web Share Target API (#3230)

* Use the web share target API

* Make requested changes

* Remove line

* Add application/json back

* Add application/vnd.excalidraw+json

* Add 'POST' check back

* Make requested changes

* Update src/appState.ts

Co-authored-by: Thomas Steiner <tomac@google.com>

* Update test

* Override initializeScene

* Use Excalidraw MIME type

* Minor fixes

* More MIME type tweaks

* More permissive file open

* Be overpermissive in file open

Co-authored-by: Thomas Steiner <tomac@google.com>
Co-authored-by: tomayac <steiner.thomas@gmail.com>
This commit is contained in:
Arun 2021-03-14 03:12:54 +05:30 committed by GitHub
parent f1daff2437
commit b9e70ec666
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 11846 additions and 11397 deletions

View file

@ -737,11 +737,16 @@ class App extends React.Component<ExcalidrawProps, AppState> {
this.scene.addCallback(this.onSceneUpdated);
this.addEventListeners();
// optim to avoid extra render on init
if (
const searchParams = new URLSearchParams(window.location.search.slice(1));
if (searchParams.has("web-share-target")) {
// Obtain a file that was shared via the Web Share Target API.
this.restoreFileFromShare();
} else if (
typeof this.props.offsetLeft === "number" &&
typeof this.props.offsetTop === "number"
) {
// Optimization to avoid extra render on init.
this.initializeScene();
} else {
this.setState(this.getCanvasOffsets(this.props), () => {
@ -1278,6 +1283,22 @@ class App extends React.Component<ExcalidrawProps, AppState> {
this.setState({ toastMessage: null });
};
restoreFileFromShare = async () => {
try {
const webShareTargetCache = await caches.open("web-share-target");
const file = await webShareTargetCache.match("shared-file");
if (file) {
const blob = await file.blob();
this.loadFileToCanvas(blob);
await webShareTargetCache.delete("shared-file");
window.history.replaceState(null, APP_NAME, window.location.pathname);
}
} catch (error) {
this.setState({ errorMessage: error.message });
}
};
public updateScene = withBatchedUpdates((sceneData: SceneData) => {
if (sceneData.commitToHistory) {
history.resumeRecording();
@ -3576,20 +3597,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
console.warn(error.name, error.message);
}
}
loadFromBlob(file, this.state)
.then(({ elements, appState }) =>
this.syncActionResult({
elements,
appState: {
...(appState || this.state),
isLoading: false,
},
commitToHistory: true,
}),
)
.catch((error) => {
this.setState({ isLoading: false, errorMessage: error.message });
});
this.loadFileToCanvas(file);
} else if (
file?.type === MIME_TYPES.excalidrawlib ||
file?.name.endsWith(".excalidrawlib")
@ -3609,6 +3617,23 @@ class App extends React.Component<ExcalidrawProps, AppState> {
}
};
loadFileToCanvas = (file: Blob) => {
loadFromBlob(file, this.state)
.then(({ elements, appState }) =>
this.syncActionResult({
elements,
appState: {
...(appState || this.state),
isLoading: false,
},
commitToHistory: true,
}),
)
.catch((error) => {
this.setState({ isLoading: false, errorMessage: error.message });
});
};
private handleCanvasContextMenu = (
event: React.PointerEvent<HTMLCanvasElement>,
) => {