2021-06-01 14:05:09 +02:00
|
|
|
import React from "react";
|
|
|
|
import { Card } from "../../components/Card";
|
|
|
|
import { ToolButton } from "../../components/ToolButton";
|
|
|
|
import { serializeAsJSON } from "../../data/json";
|
2021-10-21 22:05:48 +02:00
|
|
|
import { loadFirebaseStorage, saveFilesToFirebase } from "../data/firebase";
|
|
|
|
import { FileId, NonDeletedExcalidrawElement } from "../../element/types";
|
|
|
|
import { AppState, BinaryFileData, BinaryFiles } from "../../types";
|
2021-06-01 14:05:09 +02:00
|
|
|
import { nanoid } from "nanoid";
|
|
|
|
import { t } from "../../i18n";
|
|
|
|
import { excalidrawPlusIcon } from "./icons";
|
2021-10-21 22:05:48 +02:00
|
|
|
import { encryptData, generateEncryptionKey } from "../../data/encryption";
|
|
|
|
import { isInitializedImageElement } from "../../element/typeChecks";
|
|
|
|
import { FILE_UPLOAD_MAX_BYTES } from "../app_constants";
|
|
|
|
import { encodeFilesForUpload } from "../data/FileManager";
|
|
|
|
import { MIME_TYPES } from "../../constants";
|
2021-06-01 14:05:09 +02:00
|
|
|
|
|
|
|
const exportToExcalidrawPlus = async (
|
|
|
|
elements: readonly NonDeletedExcalidrawElement[],
|
|
|
|
appState: AppState,
|
2021-10-21 22:05:48 +02:00
|
|
|
files: BinaryFiles,
|
2021-06-01 14:05:09 +02:00
|
|
|
) => {
|
|
|
|
const firebase = await loadFirebaseStorage();
|
|
|
|
|
|
|
|
const id = `${nanoid(12)}`;
|
|
|
|
|
2021-10-21 22:05:48 +02:00
|
|
|
const encryptionKey = (await generateEncryptionKey())!;
|
2021-06-01 14:05:09 +02:00
|
|
|
const encryptedData = await encryptData(
|
2021-10-21 22:05:48 +02:00
|
|
|
encryptionKey,
|
|
|
|
serializeAsJSON(elements, appState, files, "database"),
|
2021-06-01 14:05:09 +02:00
|
|
|
);
|
|
|
|
|
2021-10-21 22:05:48 +02:00
|
|
|
const blob = new Blob(
|
|
|
|
[encryptedData.iv, new Uint8Array(encryptedData.encryptedBuffer)],
|
|
|
|
{
|
|
|
|
type: MIME_TYPES.binary,
|
|
|
|
},
|
|
|
|
);
|
2021-06-01 14:05:09 +02:00
|
|
|
|
|
|
|
await firebase
|
|
|
|
.storage()
|
|
|
|
.ref(`/migrations/scenes/${id}`)
|
|
|
|
.put(blob, {
|
|
|
|
customMetadata: {
|
2021-10-21 22:05:48 +02:00
|
|
|
data: JSON.stringify({ version: 2, name: appState.name }),
|
2021-06-01 14:05:09 +02:00
|
|
|
created: Date.now().toString(),
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2021-10-21 22:05:48 +02:00
|
|
|
const filesMap = new Map<FileId, BinaryFileData>();
|
|
|
|
for (const element of elements) {
|
|
|
|
if (isInitializedImageElement(element) && files[element.fileId]) {
|
|
|
|
filesMap.set(element.fileId, files[element.fileId]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (filesMap.size) {
|
|
|
|
const filesToUpload = await encodeFilesForUpload({
|
|
|
|
files: filesMap,
|
|
|
|
encryptionKey,
|
|
|
|
maxBytes: FILE_UPLOAD_MAX_BYTES,
|
|
|
|
});
|
|
|
|
|
|
|
|
await saveFilesToFirebase({
|
|
|
|
prefix: `/migrations/files/scenes/${id}`,
|
|
|
|
files: filesToUpload,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
window.open(
|
|
|
|
`https://plus.excalidraw.com/import?excalidraw=${id},${encryptionKey}`,
|
|
|
|
);
|
2021-06-01 14:05:09 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
export const ExportToExcalidrawPlus: React.FC<{
|
|
|
|
elements: readonly NonDeletedExcalidrawElement[];
|
|
|
|
appState: AppState;
|
2021-10-21 22:05:48 +02:00
|
|
|
files: BinaryFiles;
|
2021-06-01 14:05:09 +02:00
|
|
|
onError: (error: Error) => void;
|
2021-10-21 22:05:48 +02:00
|
|
|
}> = ({ elements, appState, files, onError }) => {
|
2021-06-01 14:05:09 +02:00
|
|
|
return (
|
|
|
|
<Card color="indigo">
|
|
|
|
<div className="Card-icon">{excalidrawPlusIcon}</div>
|
|
|
|
<h2>Excalidraw+</h2>
|
|
|
|
<div className="Card-details">
|
|
|
|
{t("exportDialog.excalidrawplus_description")}
|
|
|
|
</div>
|
|
|
|
<ToolButton
|
|
|
|
className="Card-button"
|
|
|
|
type="button"
|
|
|
|
title={t("exportDialog.excalidrawplus_button")}
|
|
|
|
aria-label={t("exportDialog.excalidrawplus_button")}
|
|
|
|
showAriaLabel={true}
|
|
|
|
onClick={async () => {
|
|
|
|
try {
|
2021-10-21 22:05:48 +02:00
|
|
|
await exportToExcalidrawPlus(elements, appState, files);
|
2021-11-02 14:24:16 +02:00
|
|
|
} catch (error: any) {
|
2021-06-01 14:05:09 +02:00
|
|
|
console.error(error);
|
2021-10-30 23:40:35 +02:00
|
|
|
if (error.name !== "AbortError") {
|
|
|
|
onError(new Error(t("exportDialog.excalidrawplus_exportError")));
|
|
|
|
}
|
2021-06-01 14:05:09 +02:00
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</Card>
|
|
|
|
);
|
|
|
|
};
|