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, 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(); 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; files: BinaryFiles; onError: (error: Error) => void; onSuccess: () => void; }> = ({ elements, appState, files, onError, onSuccess }) => { const { t } = useI18n(); return (

Excalidraw+

{t("exportDialog.excalidrawplus_description")}
{ 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"))); } } }} />
); };