d6cd8b78f1
* feat: decouple package deps and introduce yarn workspaces * update root directory * fix * fix scripts * fix lint * update path in scripts * remove yarn.lock files from packages * ignore workspace * dummy * dummy * remove comment check * revert workflow changes * ignore ws when installing gh actions * remove log * update path * fix * fix typo
133 lines
3.9 KiB
TypeScript
133 lines
3.9 KiB
TypeScript
import React from "react";
|
|
import { Card } from "../../packages/excalidraw/components/Card";
|
|
import { ToolButton } from "../../packages/excalidraw/components/ToolButton";
|
|
import { serializeAsJSON } from "../../packages/excalidraw/data/json";
|
|
import { loadFirebaseStorage, saveFilesToFirebase } from "../data/firebase";
|
|
import {
|
|
FileId,
|
|
NonDeletedExcalidrawElement,
|
|
} from "../../packages/excalidraw/element/types";
|
|
import {
|
|
AppState,
|
|
BinaryFileData,
|
|
BinaryFiles,
|
|
} from "../../packages/excalidraw/types";
|
|
import { nanoid } from "nanoid";
|
|
import { useI18n } from "../../packages/excalidraw/i18n";
|
|
import {
|
|
encryptData,
|
|
generateEncryptionKey,
|
|
} from "../../packages/excalidraw/data/encryption";
|
|
import { isInitializedImageElement } from "../../packages/excalidraw/element/typeChecks";
|
|
import { FILE_UPLOAD_MAX_BYTES } from "../app_constants";
|
|
import { encodeFilesForUpload } from "../data/FileManager";
|
|
import { MIME_TYPES } from "../../packages/excalidraw/constants";
|
|
import { trackEvent } from "../../packages/excalidraw/analytics";
|
|
import { getFrame } from "../../packages/excalidraw/utils";
|
|
import { ExcalidrawLogo } from "../../packages/excalidraw/components/ExcalidrawLogo";
|
|
|
|
export const exportToExcalidrawPlus = async (
|
|
elements: readonly NonDeletedExcalidrawElement[],
|
|
appState: Partial<AppState>,
|
|
files: BinaryFiles,
|
|
) => {
|
|
const firebase = await loadFirebaseStorage();
|
|
|
|
const id = `${nanoid(12)}`;
|
|
|
|
const encryptionKey = (await generateEncryptionKey())!;
|
|
const encryptedData = await encryptData(
|
|
encryptionKey,
|
|
serializeAsJSON(elements, appState, files, "database"),
|
|
);
|
|
|
|
const blob = new Blob(
|
|
[encryptedData.iv, new Uint8Array(encryptedData.encryptedBuffer)],
|
|
{
|
|
type: MIME_TYPES.binary,
|
|
},
|
|
);
|
|
|
|
await firebase
|
|
.storage()
|
|
.ref(`/migrations/scenes/${id}`)
|
|
.put(blob, {
|
|
customMetadata: {
|
|
data: JSON.stringify({ version: 2, name: appState.name }),
|
|
created: Date.now().toString(),
|
|
},
|
|
});
|
|
|
|
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(
|
|
`${
|
|
import.meta.env.VITE_APP_PLUS_APP
|
|
}/import?excalidraw=${id},${encryptionKey}`,
|
|
);
|
|
};
|
|
|
|
export const ExportToExcalidrawPlus: React.FC<{
|
|
elements: readonly NonDeletedExcalidrawElement[];
|
|
appState: Partial<AppState>;
|
|
files: BinaryFiles;
|
|
onError: (error: Error) => void;
|
|
onSuccess: () => void;
|
|
}> = ({ elements, appState, files, onError, onSuccess }) => {
|
|
const { t } = useI18n();
|
|
return (
|
|
<Card color="primary">
|
|
<div className="Card-icon">
|
|
<ExcalidrawLogo
|
|
style={{
|
|
[`--color-logo-icon` as any]: "#fff",
|
|
width: "2.8rem",
|
|
height: "2.8rem",
|
|
}}
|
|
/>
|
|
</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 {
|
|
trackEvent("export", "eplus", `ui (${getFrame()})`);
|
|
await exportToExcalidrawPlus(elements, appState, files);
|
|
onSuccess();
|
|
} catch (error: any) {
|
|
console.error(error);
|
|
if (error.name !== "AbortError") {
|
|
onError(new Error(t("exportDialog.excalidrawplus_exportError")));
|
|
}
|
|
}
|
|
}}
|
|
/>
|
|
</Card>
|
|
);
|
|
};
|