fix export preview flicker (#2335)

This commit is contained in:
David Luzar 2020-11-04 18:50:53 +01:00 committed by GitHub
parent 566e6a5ede
commit 455badb23e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,6 +1,7 @@
import "./ExportDialog.scss"; import "./ExportDialog.scss";
import React, { useState, useEffect, useRef } from "react"; import React, { useState, useEffect, useRef } from "react";
import { render, unmountComponentAtNode } from "react-dom";
import { ToolButton } from "./ToolButton"; import { ToolButton } from "./ToolButton";
import { clipboard, exportFile, link } from "./icons"; import { clipboard, exportFile, link } from "./icons";
@ -33,6 +34,19 @@ export const ErrorCanvasPreview = () => {
); );
}; };
const renderPreview = (
content: HTMLCanvasElement | Error,
previewNode: HTMLDivElement,
) => {
unmountComponentAtNode(previewNode);
previewNode.innerHTML = "";
if (content instanceof HTMLCanvasElement) {
previewNode.appendChild(content);
} else {
render(<ErrorCanvasPreview />, previewNode);
}
};
export type ExportCB = ( export type ExportCB = (
elements: readonly NonDeletedExcalidrawElement[], elements: readonly NonDeletedExcalidrawElement[],
scale?: number, scale?: number,
@ -61,7 +75,6 @@ const ExportModal = ({
const someElementIsSelected = isSomeElementSelected(elements, appState); const someElementIsSelected = isSomeElementSelected(elements, appState);
const [scale, setScale] = useState(defaultScale); const [scale, setScale] = useState(defaultScale);
const [exportSelected, setExportSelected] = useState(someElementIsSelected); const [exportSelected, setExportSelected] = useState(someElementIsSelected);
const [previewError, setPreviewError] = useState<Error | null>(null);
const previewRef = useRef<HTMLDivElement>(null); const previewRef = useRef<HTMLDivElement>(null);
const { const {
exportBackground, exportBackground,
@ -91,29 +104,19 @@ const ExportModal = ({
shouldAddWatermark, shouldAddWatermark,
}); });
let isRemoved = false;
// if converting to blob fails, there's some problem that will // if converting to blob fails, there's some problem that will
// likely prevent preview and export (e.g. canvas too big) // likely prevent preview and export (e.g. canvas too big)
canvasToBlob(canvas) canvasToBlob(canvas)
.then(() => { .then(() => {
if (isRemoved) { renderPreview(canvas, previewNode);
return;
}
setPreviewError(null);
previewNode.appendChild(canvas);
}) })
.catch((error) => { .catch((error) => {
console.error(error); console.error(error);
setPreviewError(new CanvasError()); renderPreview(new CanvasError(), previewNode);
}); });
return () => {
isRemoved = true;
canvas.remove();
};
} catch (error) { } catch (error) {
console.error(error); console.error(error);
setPreviewError(new CanvasError()); renderPreview(new CanvasError(), previewNode);
} }
}, [ }, [
appState, appState,
@ -127,9 +130,7 @@ const ExportModal = ({
return ( return (
<div className="ExportDialog"> <div className="ExportDialog">
<div className="ExportDialog__preview" ref={previewRef}> <div className="ExportDialog__preview" ref={previewRef} />
{previewError && <ErrorCanvasPreview />}
</div>
<Stack.Col gap={2} align="center"> <Stack.Col gap={2} align="center">
<div className="ExportDialog__actions"> <div className="ExportDialog__actions">
<Stack.Row gap={2}> <Stack.Row gap={2}>