Skip to content

Commit ba4b9c3

Browse files
authored
Big fat Christmas refactoring (#148)
* WIP * Fix type error * Fixed outstanding ts errors * fixed all ts errors * Added tsconfig to root which enables errors in VS Code for the project * Removed unused files * tsc no longer checks node_modules * removed unused code & description component * added messaging module * refactoring messaging * Reworked messaging on the frontend * Renamed preferences to settings for consistency * split types for conversion
1 parent e784c5a commit ba4b9c3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+578
-1266
lines changed

apps/debug/next-env.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
/// <reference types="next/image-types/global" />
33

44
// NOTE: This file should not be edited
5-
// see https://nextjs.org/docs/basic-features/typescript for more information.
5+
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.

apps/debug/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"postcss": "^8.4.49",
2626
"tailwindcss": "3.4.6",
2727
"tsconfig": "workspace:*",
28+
"types": "workspace:*",
2829
"typescript": "^5.7.2"
2930
}
3031
}

apps/debug/pages/index.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { FrameworkTypes, PluginUI } from "plugin-ui";
1+
import { FrameworkTypes } from "types";
22
import * as React from "react";
3+
import { PluginUI } from "plugin-ui";
34

45
export default function Web() {
56
const [selectedFramework, setSelectedFramework] =
@@ -22,8 +23,8 @@ export default function Web() {
2223
selectedFramework={selectedFramework}
2324
setSelectedFramework={setSelectedFramework}
2425
htmlPreview={null}
25-
preferences={undefined}
26-
onPreferenceChange={() => {}}
26+
settings={undefined}
27+
onPreferenceChanged={() => {}}
2728
colors={[]}
2829
gradients={[]}
2930
/>
@@ -39,8 +40,8 @@ export default function Web() {
3940
setSelectedFramework={setSelectedFramework}
4041
emptySelection={false}
4142
htmlPreview={null}
42-
preferences={undefined}
43-
onPreferenceChange={() => {}}
43+
settings={undefined}
44+
onPreferenceChanged={() => {}}
4445
colors={[]}
4546
gradients={[]}
4647
/>

apps/plugin/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"tailwindcss": "3.4.6",
3535
"tsconfig": "workspace:*",
3636
"typescript": "^5.7.2",
37+
"types": "workspace:*",
3738
"vite": "^5.4.11",
3839
"vite-plugin-singlefile": "^2.1.0"
3940
}

apps/plugin/plugin-src/code.ts

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ import {
66
swiftuiMain,
77
convertIntoNodes,
88
htmlMain,
9-
PluginSettings,
9+
postSettingsChanged,
1010
} from "backend";
1111
import { retrieveGenericSolidUIColors } from "backend/src/common/retrieveUI/retrieveColors";
1212
import { flutterCodeGenTextStyles } from "backend/src/flutter/flutterMain";
1313
import { htmlCodeGenTextStyles } from "backend/src/html/htmlMain";
1414
import { swiftUICodeGenTextStyles } from "backend/src/swiftui/swiftuiMain";
15+
import { PluginSettings, SettingWillChangeMessage } from "types";
1516

1617
let userPluginSettings: PluginSettings;
1718

@@ -58,11 +59,7 @@ const getUserSettings = async () => {
5859

5960
const initSettings = async () => {
6061
await getUserSettings();
61-
figma.ui.postMessage({
62-
type: "pluginSettingChanged",
63-
data: userPluginSettings,
64-
});
65-
62+
postSettingsChanged(userPluginSettings);
6663
safeRun(userPluginSettings);
6764
};
6865

@@ -71,19 +68,17 @@ const safeRun = (settings: PluginSettings) => {
7168
run(settings);
7269
} catch (e) {
7370
if (e && typeof e === "object" && "message" in e) {
74-
console.log("error: ", (e as any).stack);
75-
figma.ui.postMessage({
76-
type: "error",
77-
data: e.message,
78-
});
71+
const error = e as Error;
72+
console.log("error: ", error.stack);
73+
figma.ui.postMessage({ type: "error", error: error.message });
7974
}
8075
}
8176
};
8277

8378
const standardMode = async () => {
8479
figma.showUI(__html__, { width: 450, height: 550, themeColors: true });
8580
await initSettings();
86-
81+
8782
// Listen for selection changes
8883
figma.on("selectionchange", () => {
8984
safeRun(userPluginSettings);
@@ -97,13 +92,10 @@ const standardMode = async () => {
9792
figma.ui.onmessage = (msg) => {
9893
console.log("[node] figma.ui.onmessage", msg);
9994

100-
if (msg.type === "pluginSettingChanged") {
101-
(userPluginSettings as any)[msg.key] = msg.value;
95+
if (msg.type === "pluginSettingWillChange") {
96+
const { key, value } = msg as SettingWillChangeMessage<unknown>;
97+
(userPluginSettings as any)[key] = value;
10298
figma.clientStorage.setAsync("userPluginSettings", userPluginSettings);
103-
// figma.ui.postMessage({
104-
// type: "pluginSettingChanged",
105-
// data: userPluginSettings,
106-
// });
10799
safeRun(userPluginSettings);
108100
}
109101
};

apps/plugin/ui-src/App.tsx

Lines changed: 48 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,36 @@
11
import { useEffect, useState } from "react";
2-
import { FrameworkTypes, PluginSettings, PluginUI } from "plugin-ui";
2+
import { PluginUI } from "plugin-ui";
3+
import {
4+
FrameworkTypes,
5+
PluginSettings,
6+
ConversionMessage,
7+
Message,
8+
HTMLPreview,
9+
LinearGradientConversion,
10+
SolidColorConversion,
11+
ErrorMessage,
12+
SettingsChangedMessage,
13+
} from "types";
14+
import { postUISettingsChangingMessage } from "./messaging";
315

416
interface AppState {
517
code: string;
6-
selectedFramework: FrameworkTypes | null;
18+
selectedFramework: FrameworkTypes;
719
isLoading: boolean;
8-
htmlPreview: {
9-
size: { width: number; height: number };
10-
content: string;
11-
} | null;
12-
preferences: PluginSettings | null;
13-
colors: {
14-
hex: string;
15-
colorName: string;
16-
exportValue: string;
17-
contrastWhite: number;
18-
contrastBlack: number;
19-
}[];
20-
gradients: { cssPreview: string; exportedValue: string }[];
20+
htmlPreview: HTMLPreview;
21+
settings: PluginSettings | null;
22+
colors: SolidColorConversion[];
23+
gradients: LinearGradientConversion[];
2124
}
2225

26+
const emptyPreview = { size: { width: 0, height: 0 }, content: "" };
2327
export default function App() {
2428
const [state, setState] = useState<AppState>({
2529
code: "",
26-
selectedFramework: null,
30+
selectedFramework: "HTML",
2731
isLoading: false,
28-
htmlPreview: null,
29-
preferences: null,
32+
htmlPreview: emptyPreview,
33+
settings: null,
3034
colors: [],
3135
gradients: [],
3236
});
@@ -38,42 +42,47 @@ export default function App() {
3842

3943
useEffect(() => {
4044
window.onmessage = (event: MessageEvent) => {
41-
const message = event.data.pluginMessage;
42-
console.log("[ui] message received:", message);
43-
switch (message.type) {
45+
const untypedMessage = event.data.pluginMessage as Message;
46+
console.log("[ui] message received:", untypedMessage);
47+
48+
switch (untypedMessage.type) {
4449
case "code":
50+
const conversionMessage = untypedMessage as ConversionMessage;
4551
setState((prevState) => ({
4652
...prevState,
47-
code: message.data,
48-
htmlPreview: message.htmlPreview,
49-
colors: message.colors,
50-
gradients: message.gradients,
51-
preferences: message.preferences,
52-
selectedFramework: message.preferences.framework,
53+
...conversionMessage,
54+
selectedFramework: conversionMessage.settings.framework,
5355
}));
5456
break;
57+
5558
case "pluginSettingChanged":
59+
const settingsMessage = untypedMessage as SettingsChangedMessage;
5660
setState((prevState) => ({
5761
...prevState,
58-
preferences: message.data,
59-
selectedFramework: message.data.framework,
62+
settings: settingsMessage.settings,
63+
selectedFramework: settingsMessage.settings.framework,
6064
}));
6165
break;
66+
6267
case "empty":
68+
// const emptyMessage = untypedMessage as EmptyMessage;
6369
setState((prevState) => ({
6470
...prevState,
6571
code: "// No layer is selected.",
66-
htmlPreview: null,
72+
htmlPreview: emptyPreview,
6773
colors: [],
6874
gradients: [],
6975
}));
7076
break;
77+
7178
case "error":
79+
const errorMessage = untypedMessage as ErrorMessage;
80+
7281
setState((prevState) => ({
7382
...prevState,
7483
colors: [],
7584
gradients: [],
76-
code: `Error :(\n// ${message.data}`,
85+
code: `Error :(\n// ${errorMessage.error}`,
7786
}));
7887
break;
7988
default:
@@ -112,17 +121,9 @@ export default function App() {
112121
// code: "// Loading...",
113122
selectedFramework: updatedFramework,
114123
}));
115-
116-
parent.postMessage(
117-
{
118-
pluginMessage: {
119-
type: "pluginSettingChanged",
120-
key: "framework",
121-
value: updatedFramework,
122-
},
123-
},
124-
"*",
125-
);
124+
postUISettingsChangingMessage("framework", updatedFramework, {
125+
targetOrigin: "*",
126+
});
126127
};
127128
console.log("state.code", state.code.slice(0, 25));
128129

@@ -134,24 +135,12 @@ export default function App() {
134135
selectedFramework={state.selectedFramework}
135136
setSelectedFramework={handleFrameworkChange}
136137
htmlPreview={state.htmlPreview}
137-
preferences={state.preferences}
138-
onPreferenceChange={(key: string, value: boolean | string) => {
139-
parent.postMessage(
140-
{
141-
pluginMessage: {
142-
type: "pluginSettingChanged",
143-
key: key,
144-
value: value,
145-
},
146-
},
147-
"*",
148-
);
149-
}}
138+
settings={state.settings}
139+
onPreferenceChanged={(key: string, value: boolean | string) =>
140+
postUISettingsChangingMessage(key, value, { targetOrigin: "*" })
141+
}
150142
colors={state.colors}
151-
gradients={state.gradients.map((gradient) => ({
152-
...gradient,
153-
exportValue: gradient.exportedValue,
154-
}))}
143+
gradients={state.gradients}
155144
/>
156145
</div>
157146
);

apps/plugin/ui-src/messaging.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Message, SettingWillChangeMessage, UIMessage } from "types";
2+
3+
if (!parent || !parent.postMessage) {
4+
throw new Error("parent.postMessage() is not defined");
5+
}
6+
const postMessage = (message: UIMessage, options?: WindowPostMessageOptions) =>
7+
parent.postMessage(message, options);
8+
9+
export const postUIMessage = (
10+
message: Message,
11+
options?: WindowPostMessageOptions,
12+
) => postMessage({ pluginMessage: message }, options);
13+
14+
export const postUISettingsChangingMessage = <T>(
15+
key: string,
16+
value: T,
17+
options?: WindowPostMessageOptions,
18+
) => {
19+
const message: SettingWillChangeMessage<T> = {
20+
type: "pluginSettingWillChange",
21+
key,
22+
value,
23+
};
24+
postUIMessage(message, options);
25+
};

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"eslint": "^9.17.0",
1414
"eslint-config-custom": "workspace:*",
1515
"prettier": "^3.4.2",
16-
"turbo": "^2.3.3"
16+
"turbo": "^2.3.3",
17+
"typescript": "^5.7.2"
1718
}
1819
}

packages/backend/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
"dependencies": {
1616
"@figma/plugin-typings": "^1.105.0",
1717
"react": "18.3.1",
18-
"react-dom": "18.3.1"
18+
"react-dom": "18.3.1",
19+
"types": "workspace:*"
1920
},
2021
"devDependencies": {
2122
"@types/react": "^18.3.17",

0 commit comments

Comments
 (0)