123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- import { cleanAppStateForExport } from "../appState";
- import { EXPORT_DATA_TYPES } from "../constants";
- import { clearElementsForExport } from "../element";
- import { ExcalidrawElement } from "../element/types";
- import { CanvasError } from "../errors";
- import { t } from "../i18n";
- import { calculateScrollCenter } from "../scene";
- import { AppState } from "../types";
- import { isValidExcalidrawData } from "./json";
- import { restore } from "./restore";
- import { ImportedLibraryData } from "./types";
- const parseFileContents = async (blob: Blob | File) => {
- let contents: string;
- if (blob.type === "image/png") {
- try {
- return await (
- await import(/* webpackChunkName: "image" */ "./image")
- ).decodePngMetadata(blob);
- } catch (error) {
- if (error.message === "INVALID") {
- throw new Error(t("alerts.imageDoesNotContainScene"));
- } else {
- throw new Error(t("alerts.cannotRestoreFromImage"));
- }
- }
- } else {
- if ("text" in Blob) {
- contents = await blob.text();
- } else {
- contents = await new Promise((resolve) => {
- const reader = new FileReader();
- reader.readAsText(blob, "utf8");
- reader.onloadend = () => {
- if (reader.readyState === FileReader.DONE) {
- resolve(reader.result as string);
- }
- };
- });
- }
- if (blob.type === "image/svg+xml") {
- try {
- return await (
- await import(/* webpackChunkName: "image" */ "./image")
- ).decodeSvgMetadata({
- svg: contents,
- });
- } catch (error) {
- if (error.message === "INVALID") {
- throw new Error(t("alerts.imageDoesNotContainScene"));
- } else {
- throw new Error(t("alerts.cannotRestoreFromImage"));
- }
- }
- }
- }
- return contents;
- };
- export const getMimeType = (blob: Blob | string): string => {
- let name: string;
- if (typeof blob === "string") {
- name = blob;
- } else {
- if (blob.type) {
- return blob.type;
- }
- name = blob.name || "";
- }
- if (/\.(excalidraw|json)$/.test(name)) {
- return "application/json";
- } else if (/\.png$/.test(name)) {
- return "image/png";
- } else if (/\.jpe?g$/.test(name)) {
- return "image/jpeg";
- } else if (/\.svg$/.test(name)) {
- return "image/svg+xml";
- }
- return "";
- };
- export const loadFromBlob = async (
- blob: Blob,
- /** @see restore.localAppState */
- localAppState: AppState | null,
- localElements: readonly ExcalidrawElement[] | null,
- ) => {
- const contents = await parseFileContents(blob);
- try {
- const data = JSON.parse(contents);
- if (!isValidExcalidrawData(data)) {
- throw new Error(t("alerts.couldNotLoadInvalidFile"));
- }
- const result = restore(
- {
- elements: clearElementsForExport(data.elements || []),
- appState: {
- theme: localAppState?.theme,
- fileHandle: (!blob.type.startsWith("image/") && blob.handle) || null,
- ...cleanAppStateForExport(data.appState || {}),
- ...(localAppState
- ? calculateScrollCenter(data.elements || [], localAppState, null)
- : {}),
- },
- },
- localAppState,
- localElements,
- );
- return result;
- } catch (error) {
- console.error(error.message);
- throw new Error(t("alerts.couldNotLoadInvalidFile"));
- }
- };
- export const loadLibraryFromBlob = async (blob: Blob) => {
- const contents = await parseFileContents(blob);
- const data: ImportedLibraryData = JSON.parse(contents);
- if (data.type !== EXPORT_DATA_TYPES.excalidrawLibrary) {
- throw new Error(t("alerts.couldNotLoadInvalidFile"));
- }
- return data;
- };
- export const canvasToBlob = async (
- canvas: HTMLCanvasElement,
- ): Promise<Blob> => {
- return new Promise((resolve, reject) => {
- try {
- canvas.toBlob((blob) => {
- if (!blob) {
- return reject(
- new CanvasError(
- t("canvasError.canvasTooBig"),
- "CANVAS_POSSIBLY_TOO_BIG",
- ),
- );
- }
- resolve(blob);
- });
- } catch (error) {
- reject(error);
- }
- });
- };
|