feat: resave to png/svg with metadata if you loaded your scene from a png/svg file (#3645)

Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
David Laban 2021-07-15 09:54:26 -04:00 committed by GitHub
parent 9581c45522
commit 685abac81a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 108 additions and 15 deletions

View file

@ -1,3 +1,4 @@
import { FileSystemHandle } from "browser-fs-access";
import { cleanAppStateForExport } from "../appState";
import { EXPORT_DATA_TYPES } from "../constants";
import { clearElementsForExport } from "../element";
@ -80,6 +81,25 @@ export const getMimeType = (blob: Blob | string): string => {
return "";
};
export const getFileHandleType = (handle: FileSystemHandle | null) => {
if (!handle) {
return null;
}
return handle.name.match(/\.(json|excalidraw|png|svg)$/)?.[1] || null;
};
export const isImageFileHandleType = (
type: string | null,
): type is "png" | "svg" => {
return type === "png" || type === "svg";
};
export const isImageFileHandle = (handle: FileSystemHandle | null) => {
const type = getFileHandleType(handle);
return type === "png" || type === "svg";
};
export const loadFromBlob = async (
blob: Blob,
/** @see restore.localAppState */
@ -97,7 +117,7 @@ export const loadFromBlob = async (
elements: clearElementsForExport(data.elements || []),
appState: {
theme: localAppState?.theme,
fileHandle: (!blob.type.startsWith("image/") && blob.handle) || null,
fileHandle: blob.handle || null,
...cleanAppStateForExport(data.appState || {}),
...(localAppState
? calculateScrollCenter(data.elements || [], localAppState, null)

View file

@ -1,4 +1,4 @@
import { fileSave } from "browser-fs-access";
import { fileSave, FileSystemHandle } from "browser-fs-access";
import {
copyBlobToClipboardAsPng,
copyTextToSystemClipboard,
@ -24,11 +24,13 @@ export const exportCanvas = async (
exportPadding = DEFAULT_EXPORT_PADDING,
viewBackgroundColor,
name,
fileHandle = null,
}: {
exportBackground: boolean;
exportPadding?: number;
viewBackgroundColor: string;
name: string;
fileHandle?: FileSystemHandle | null;
},
) => {
if (elements.length === 0) {
@ -44,11 +46,14 @@ export const exportCanvas = async (
exportEmbedScene: appState.exportEmbedScene && type === "svg",
});
if (type === "svg") {
await fileSave(new Blob([tempSvg.outerHTML], { type: "image/svg+xml" }), {
fileName: `${name}.svg`,
extensions: [".svg"],
});
return;
return await fileSave(
new Blob([tempSvg.outerHTML], { type: "image/svg+xml" }),
{
fileName: `${name}.svg`,
extensions: [".svg"],
},
fileHandle,
);
} else if (type === "clipboard-svg") {
await copyTextToSystemClipboard(tempSvg.outerHTML);
return;
@ -76,10 +81,14 @@ export const exportCanvas = async (
});
}
await fileSave(blob, {
fileName,
extensions: [".png"],
});
return await fileSave(
blob,
{
fileName,
extensions: [".png"],
},
fileHandle,
);
} else if (type === "clipboard") {
try {
await copyBlobToClipboardAsPng(blob);

View file

@ -4,7 +4,7 @@ import { EXPORT_DATA_TYPES, EXPORT_SOURCE, MIME_TYPES } from "../constants";
import { clearElementsForExport } from "../element";
import { ExcalidrawElement } from "../element/types";
import { AppState } from "../types";
import { loadFromBlob } from "./blob";
import { isImageFileHandle, loadFromBlob } from "./blob";
import {
ExportedDataState,
@ -44,7 +44,7 @@ export const saveAsJSON = async (
description: "Excalidraw file",
extensions: [".excalidraw"],
},
appState.fileHandle,
isImageFileHandle(appState.fileHandle) ? null : appState.fileHandle,
);
return { fileHandle };
};

38
src/data/resave.ts Normal file
View file

@ -0,0 +1,38 @@
import { ExcalidrawElement } from "../element/types";
import { AppState } from "../types";
import { exportCanvas } from ".";
import { getNonDeletedElements } from "../element";
import { getFileHandleType, isImageFileHandleType } from "./blob";
export const resaveAsImageWithScene = async (
elements: readonly ExcalidrawElement[],
appState: AppState,
) => {
const { exportBackground, viewBackgroundColor, name, fileHandle } = appState;
const fileHandleType = getFileHandleType(fileHandle);
if (!fileHandle || !isImageFileHandleType(fileHandleType)) {
throw new Error(
"fileHandle should exist and should be of type svg or png when resaving",
);
}
appState = {
...appState,
exportEmbedScene: true,
};
await exportCanvas(
fileHandleType,
getNonDeletedElements(elements),
appState,
{
exportBackground,
viewBackgroundColor,
name,
fileHandle,
},
);
return { fileHandle };
};