mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-22 03:58:12 +08:00
Refactor persistent data storage code and add button to wipe data on crash (#827)
* Organize persistence.ts * Switch to simpler promise handling * Switch document list storage from localStorage to IndexedDB * Track document auto-save status to avoid re-auto-saving unnecessarily * Add button to clear storage on crash * Bump document version and test file * Switch to IDB-Keyval instead of raw IDB transactions
This commit is contained in:
@@ -2,13 +2,7 @@ import { replaceBlobURLsWithBase64 } from "@/utility-functions/files";
|
||||
|
||||
// Rasterize the string of an SVG document at a given width and height and turn it into the blob data of an image file matching the given MIME type
|
||||
export async function rasterizeSVGCanvas(svg: string, width: number, height: number, backgroundColor?: string): Promise<HTMLCanvasElement> {
|
||||
let promiseResolve: (value: HTMLCanvasElement | PromiseLike<HTMLCanvasElement>) => void | undefined;
|
||||
const promise = new Promise<HTMLCanvasElement>((resolve) => {
|
||||
promiseResolve = resolve;
|
||||
});
|
||||
|
||||
// A canvas to render our svg to in order to get a raster image
|
||||
// https://stackoverflow.com/questions/3975499/convert-svg-to-image-jpeg-png-etc-in-the-browser
|
||||
// A canvas to render our SVG to in order to get a raster image
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
@@ -25,38 +19,35 @@ export async function rasterizeSVGCanvas(svg: string, width: number, height: num
|
||||
const svgWithBase64Images = await replaceBlobURLsWithBase64(svg);
|
||||
|
||||
// Create a blob URL for our SVG
|
||||
const image = new Image();
|
||||
const svgBlob = new Blob([svgWithBase64Images], { type: "image/svg+xml;charset=utf-8" });
|
||||
const url = URL.createObjectURL(svgBlob);
|
||||
image.onload = (): void => {
|
||||
// Draw our SVG to the canvas
|
||||
context?.drawImage(image, 0, 0, width, height);
|
||||
|
||||
// Clean up the SVG blob URL (once the URL is revoked, the SVG blob data itself is garbage collected after `svgBlob` goes out of scope)
|
||||
URL.revokeObjectURL(url);
|
||||
|
||||
promiseResolve(canvas);
|
||||
};
|
||||
const image = new Image();
|
||||
image.src = url;
|
||||
await new Promise<void>((resolve) => {
|
||||
image.onload = (): void => resolve();
|
||||
});
|
||||
|
||||
return promise;
|
||||
// Draw our SVG to the canvas
|
||||
context?.drawImage(image, 0, 0, width, height);
|
||||
|
||||
// Clean up the SVG blob URL (once the URL is revoked, the SVG blob data itself is garbage collected after `svgBlob` goes out of scope)
|
||||
URL.revokeObjectURL(url);
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
export async function rasterizeSVG(svg: string, width: number, height: number, mime: string, backgroundColor?: string): Promise<Blob> {
|
||||
let promiseResolve: (value: Blob | PromiseLike<Blob>) => void | undefined;
|
||||
let promiseReject: () => void | undefined;
|
||||
const promise = new Promise<Blob>((resolve, reject) => {
|
||||
promiseResolve = resolve;
|
||||
promiseReject = reject;
|
||||
});
|
||||
const canvas = await rasterizeSVGCanvas(svg, width, height, backgroundColor);
|
||||
|
||||
rasterizeSVGCanvas(svg, width, height, backgroundColor).then((canvas) => {
|
||||
// Convert the canvas to an image of the correct MIME type
|
||||
// Convert the canvas to an image of the correct MIME type
|
||||
const blob = await new Promise<Blob | undefined>((resolve) => {
|
||||
canvas.toBlob((blob) => {
|
||||
if (blob !== null) promiseResolve(blob);
|
||||
else promiseReject();
|
||||
resolve(blob || undefined);
|
||||
}, mime);
|
||||
});
|
||||
|
||||
return promise;
|
||||
if (!blob) throw new Error("Converting canvas to blob data failed in rasterizeSVG()");
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user