Skip to content

Commit b68b74c

Browse files
authored
Patch flash when loading (#186)
* Wrapped exportAsync in a proxy method that allows us to also message the UI when you call it so that it can display a loading message. * Added comment for clarity
1 parent e4036d3 commit b68b74c

File tree

4 files changed

+50
-14
lines changed

4 files changed

+50
-14
lines changed

packages/backend/src/altNodes/altNodeUtils.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { AltNode } from "types";
22
import { curry } from "../common/curry";
3+
import { exportAsyncProxy } from "../common/exportAsyncProxy";
34

45
export const overrideReadonlyProperty = curry(
56
<T, K extends keyof T>(prop: K, value: any, obj: T): T =>
@@ -48,7 +49,9 @@ export const isSVGNode = (node: SceneNode) => {
4849
};
4950

5051
export const renderNodeAsSVG = async (node: SceneNode) =>
51-
await node.exportAsync({ format: "SVG_STRING" });
52+
await exportAsyncProxy<string>(node, {
53+
format: "SVG_STRING",
54+
});
5255

5356
export const renderAndAttachSVG = async (node: SceneNode) => {
5457
const altNode = node as AltNode<typeof node>;
@@ -60,7 +63,7 @@ export const renderAndAttachSVG = async (node: SceneNode) => {
6063
return altNode;
6164
}
6265
// console.log(`${nodeName} can be flattened!`);
63-
const svg = await renderNodeAsSVG(altNode.originalNode);
66+
const svg = (await renderNodeAsSVG(altNode.originalNode)) as string;
6467
// console.log(`${svg}`);
6568
altNode.svg = svg;
6669
}

packages/backend/src/code.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ export const run = async (settings: PluginSettings) => {
2929
);
3030
}
3131

32-
postConversionStart();
33-
// force postMessage to run right now.
34-
await new Promise((resolve) => setTimeout(resolve, 30));
35-
3632
const convertedSelection = convertNodesToAltNodes(selection, null);
3733

3834
// ignore when nothing was selected
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { postConversionStart } from "../messaging";
2+
3+
let isRunning = false;
4+
5+
/*
6+
* This is a wrapper for exportAsync() This allows us to pass a message to the UI every time
7+
* this rather costly operation gets run so that it can display a loading message. This avoids
8+
* showing a loading message every time anything in the UI changes and only showing it when
9+
* exportAsync() is called.
10+
*/
11+
export const exportAsyncProxy = async <
12+
T extends string | Uint8Array = Uint8Array /* | Object */,
13+
>(
14+
node: SceneNode,
15+
settings: ExportSettings | ExportSettingsSVGString /*| ExportSettingsREST*/,
16+
): Promise<T> => {
17+
if (node.exportAsync === undefined) {
18+
// console.log(node);
19+
throw new TypeError(
20+
"Something went wrong. This node doesn't have an exportAsync() function. Maybe check the type before calling this function.",
21+
);
22+
}
23+
24+
if (isRunning === false) {
25+
isRunning = true;
26+
postConversionStart();
27+
// force postMessage to run right now.
28+
await new Promise((resolve) => setTimeout(resolve, 30));
29+
}
30+
31+
// The following is necessary for typescript to not lose its mind.
32+
let result;
33+
if (settings.format === "SVG_STRING") {
34+
result = await node.exportAsync(settings as ExportSettingsSVGString);
35+
// } else if (settings.format === "JSON_REST_V1") {
36+
// result = await node.exportAsync(settings as ExportSettingsREST);
37+
} else {
38+
result = await node.exportAsync(settings as ExportSettings);
39+
}
40+
41+
isRunning = false;
42+
return result as T;
43+
};

packages/backend/src/common/images.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { AltNode, ExportableNode } from "types";
22
import { btoa } from "js-base64";
33
import { addWarning } from "./commonConversionWarnings";
4+
import { exportAsyncProxy } from "./exportAsyncProxy";
45

56
export const PLACEHOLDER_IMAGE_DOMAIN = "https://placehold.co";
67

@@ -49,13 +50,6 @@ export const exportNodeAsBase64PNG = async <T extends ExportableNode>(
4950

5051
const n: ExportableNode = node.originalNode;
5152

52-
if (n.exportAsync === undefined) {
53-
console.log(n);
54-
throw new TypeError(
55-
"Something went wrong. This node doesn't have an exportAsync function. Maybe check the type before calling this function.",
56-
);
57-
}
58-
5953
const temporarilyHideChildren =
6054
excludeChildren && "children" in n && n.children.length > 0;
6155
const parent = n as ChildrenMixin;
@@ -77,7 +71,7 @@ export const exportNodeAsBase64PNG = async <T extends ExportableNode>(
7771
format: "PNG",
7872
constraint: { type: "SCALE", value: 1 },
7973
};
80-
const bytes = await n.exportAsync(exportSettings);
74+
const bytes = await exportAsyncProxy(n, exportSettings);
8175

8276
if (temporarilyHideChildren) {
8377
// After export, restore visibility

0 commit comments

Comments
 (0)