diff --git a/src/components/ExportDialog.tsx b/src/components/ExportDialog.tsx
index 52ceba1b..72d0218f 100644
--- a/src/components/ExportDialog.tsx
+++ b/src/components/ExportDialog.tsx
@@ -156,7 +156,6 @@ const ExportModal = ({
{actionManager.renderAction("changeExportBackground")}
- {actionManager.renderAction("changeExportEmbedScene")}
{someElementIsSelected && (
)}
+ {actionManager.renderAction("changeExportEmbedScene")}
{actionManager.renderAction("changeShouldAddWatermark")}
diff --git a/src/data/blob.ts b/src/data/blob.ts
index b1ffa847..f2e84fb8 100644
--- a/src/data/blob.ts
+++ b/src/data/blob.ts
@@ -6,24 +6,14 @@ import { LibraryData, ImportedDataState } from "./types";
import { calculateScrollCenter } from "../scene";
import { MIME_TYPES } from "../constants";
import { base64ToString } from "../base64";
-
export const parseFileContents = async (blob: Blob | File) => {
let contents: string;
if (blob.type === "image/png") {
- const { default: decodePng } = await import("png-chunks-extract");
- const { default: tEXt } = await import("png-chunk-text");
- const chunks = decodePng(new Uint8Array(await blob.arrayBuffer()));
-
- const metadataChunk = chunks.find((chunk) => chunk.name === "tEXt");
- if (metadataChunk) {
- const metadata = tEXt.decode(metadataChunk.data);
- if (metadata.keyword === MIME_TYPES.excalidraw) {
- return metadata.text;
- }
- throw new Error(t("alerts.imageDoesNotContainScene"));
- } else {
- throw new Error(t("alerts.imageDoesNotContainScene"));
+ const metadata = await (await import("./png")).getTEXtChunk(blob);
+ if (metadata?.keyword === MIME_TYPES.excalidraw) {
+ return metadata.text;
}
+ throw new Error(t("alerts.imageDoesNotContainScene"));
} else {
if ("text" in Blob) {
contents = await blob.text();
diff --git a/src/data/index.ts b/src/data/index.ts
index a79aa0da..87e61d76 100644
--- a/src/data/index.ts
+++ b/src/data/index.ts
@@ -345,17 +345,10 @@ export const exportCanvas = async (
tempCanvas.toBlob(async (blob) => {
if (blob) {
if (appState.exportEmbedScene) {
- const { default: tEXt } = await import("png-chunk-text");
- const { default: encodePng } = await import("png-chunks-encode");
- const { default: decodePng } = await import("png-chunks-extract");
- const chunks = decodePng(new Uint8Array(await blob.arrayBuffer()));
- const metadata = tEXt.encode(
- MIME_TYPES.excalidraw,
- serializeAsJSON(elements, appState),
- );
- // insert metadata before last chunk (iEND)
- chunks.splice(-1, 0, metadata);
- blob = new Blob([encodePng(chunks)], { type: "image/png" });
+ blob = await (await import("./png")).encodeTEXtChunk(blob, {
+ keyword: MIME_TYPES.excalidraw,
+ text: serializeAsJSON(elements, appState),
+ });
}
await fileSave(blob, {
diff --git a/src/data/png.ts b/src/data/png.ts
new file mode 100644
index 00000000..133ad72e
--- /dev/null
+++ b/src/data/png.ts
@@ -0,0 +1,42 @@
+import decodePng from "png-chunks-extract";
+import tEXt from "png-chunk-text";
+import encodePng from "png-chunks-encode";
+
+const blobToArrayBuffer = (blob: Blob): Promise => {
+ if ("arrayBuffer" in blob) {
+ return blob.arrayBuffer();
+ }
+ // Safari
+ return new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.onload = (event) => {
+ if (!event.target?.result) {
+ return reject(new Error("couldn't convert blob to ArrayBuffer"));
+ }
+ resolve(event.target.result as ArrayBuffer);
+ };
+ reader.readAsArrayBuffer(blob);
+ });
+};
+
+export const getTEXtChunk = async (
+ blob: Blob,
+): Promise<{ keyword: string; text: string } | null> => {
+ const chunks = decodePng(new Uint8Array(await blobToArrayBuffer(blob)));
+ const metadataChunk = chunks.find((chunk) => chunk.name === "tEXt");
+ if (metadataChunk) {
+ return tEXt.decode(metadataChunk.data);
+ }
+ return null;
+};
+
+export const encodeTEXtChunk = async (
+ blob: Blob,
+ chunk: { keyword: string; text: string },
+): Promise => {
+ const chunks = decodePng(new Uint8Array(await blobToArrayBuffer(blob)));
+ const metadata = tEXt.encode(chunk.keyword, chunk.text);
+ // insert metadata before last chunk (iEND)
+ chunks.splice(-1, 0, metadata);
+ return new Blob([encodePng(chunks)], { type: "image/png" });
+};