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:
Keavon Chambers
2022-11-03 03:05:41 -07:00
parent d6c2d73f45
commit 7522af9fc7
16 changed files with 182 additions and 186 deletions
+19 -28
View File
@@ -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;
}