Skip to content

Commit 6515ba9

Browse files
authored
feat: complete logic (#2)
1 parent 5bec9e4 commit 6515ba9

7 files changed

+148
-71
lines changed

manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "FigmaTranslate",
2+
"name": "AI Translator",
33
"id": "1364799721988996959",
44
"api": "1.0.0",
55
"main": "dist/main.js",

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
"description": "Figma contents are able to translate by AI",
55
"source": "src/index.ts",
66
"module": "dist/main.js",
7-
"types": "dist/types.d.ts",
87
"targets": {
9-
"main": {
8+
"module": {
109
"includeNodeModules": true
1110
}
1211
},
1312
"scripts": {
1413
"tsc": "tsc",
1514
"watch": "parcel watch",
16-
"build": "rm -rf .parcel-cache/ && rm -rf dist/ && parcel build"
15+
"build": "rm -rf .parcel-cache/ && rm -rf dist/ && cross-env NODE_ENV=production parcel build --no-source-maps",
16+
"build:dev": "rm -rf .parcel-cache/ && rm -rf dist/ && parcel build"
1717
},
1818
"keywords": [],
1919
"author": "wangym",
@@ -30,6 +30,7 @@
3030
"@types/lodash": "^4.17.0",
3131
"@typescript-eslint/eslint-plugin": "^6.12.0",
3232
"@typescript-eslint/parser": "^6.12.0",
33+
"cross-env": "^7.0.3",
3334
"eslint": "^8.54.0",
3435
"parcel": "^2.12.0",
3536
"parcel-plugin-typescript": "^1.0.0",

src/FigmaStorage.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export enum StorageKey {
22
APIkey = "APIkey",
3+
language = "language",
34
}
45

56
export class FigmaStorage {

src/Translator.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@ export class Translator {
3434
}),
3535
}).then((result) => {
3636
return result.json();
37-
});
37+
})
3838
}
3939
}

src/index.ts

+69-35
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,97 @@
1-
/**
2-
* - 发布插件,解决编译报错,watch
3-
* - 在input中回显 apikey
4-
* - 存储翻译结果
5-
* - UI 优化
6-
* - 接口请求错误提示
7-
*/
81
import { FigmaStorage, StorageKey } from "./FigmaStorage";
92
import { Translator } from "./Translator";
103
import { MessageData, MessageType } from "./typing";
114

125
(async function () {
136
const figmaStorage = new FigmaStorage();
147
const translator = new Translator();
8+
const translateCacheMap = new Map<string, string>();
159

16-
if (figma.editorType === "figma") {
17-
// TODO add logic
18-
figma.showUI(__html__);
19-
}
20-
21-
if (figma.editorType === "figjam") {
22-
const APIkey = await figmaStorage.get(StorageKey.APIkey);
23-
24-
figma.showUI(__html__);
25-
26-
if (APIkey) {
27-
console.log(`Get the open-api key: ${APIkey}`);
28-
translator.setAPIkey(APIkey);
10+
async function translate() {
11+
const selectedNodes = figma.currentPage.selection;
12+
const currentNode = selectedNodes[0] as
13+
| {
14+
text: TextSublayerNode;
15+
}
16+
| undefined;
2917

18+
if (currentNode === undefined) {
19+
return;
20+
}
21+
22+
let characters: string | undefined;
23+
if (
24+
(
25+
currentNode as {
26+
text: TextSublayerNode;
27+
}
28+
).text
29+
) {
30+
characters = currentNode.text.characters;
3031
}
3132

33+
if ((currentNode as unknown as TextSublayerNode).characters) {
34+
characters = (currentNode as unknown as TextSublayerNode).characters;
35+
}
3236

33-
figma.on("selectionchange", async () => {
34-
const selectedNodes = figma.currentPage.selection;
35-
36-
console.log(selectedNodes, "selectedNodes");
37-
38-
const currentNode = selectedNodes[0] as {
39-
text: TextSublayerNode;
40-
};
41-
42-
if (currentNode.text) {
43-
const characters = currentNode.text.characters;
44-
45-
figma.ui.postMessage(
37+
if (characters) {
38+
if (translateCacheMap.has(characters)) {
39+
return figma.ui.postMessage(
4640
new MessageData(MessageType.translate, {
47-
value: "Loading...",
41+
value: translateCacheMap.get(characters)!,
4842
data: { characters },
4943
})
5044
);
45+
}
5146

47+
figma.ui.postMessage(
48+
new MessageData(MessageType.translate, {
49+
value: "Loading...",
50+
data: { characters },
51+
})
52+
);
53+
54+
try {
5255
const result = await translator.translate(characters);
5356

57+
const value = result.choices[0].message.content;
5458
figma.ui.postMessage(
5559
new MessageData(MessageType.translate, {
56-
value: result.choices[0].message.content,
60+
value: value,
5761
data: { characters },
5862
})
5963
);
64+
translateCacheMap.set(characters, value);
65+
} catch (error) {
66+
console.error(error);
67+
figma.notify("fetch api error");
6068
}
69+
}
70+
}
71+
72+
if (figma.editorType === "figma") {
73+
// TODO add logic
74+
figma.showUI(__html__);
75+
}
76+
77+
if (figma.editorType === "figjam") {
78+
const APIkey = await figmaStorage.get(StorageKey.APIkey);
79+
80+
figma.showUI(__html__);
81+
82+
if (APIkey) {
83+
// console.log(`Get the open-api key: ${APIkey}`);
84+
translator.setAPIkey(APIkey);
85+
figma.ui.postMessage(
86+
new MessageData(MessageType.APIkey, {
87+
value: APIkey,
88+
})
89+
);
90+
translate();
91+
}
92+
93+
figma.on("selectionchange", async () => {
94+
await translate();
6195
});
6296

6397
figma.ui.onmessage = async (msg: MessageData) => {

ui.html

+64-30
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,69 @@
1-
<input type="password" name="APIkey" id="APIkey">
2-
<p id="origin">
3-
4-
</p>
5-
<p id="translator">
6-
7-
</p>
8-
<script>
9-
10-
window.addEventListener('message', event => {
11-
const message = event.data;
12-
console.log('Received message:', message);
13-
if (message.pluginMessage.type === "translate") {
14-
const origin = document.getElementById('origin');
15-
const translator = document.getElementById('translator');
16-
origin.innerText = message.pluginMessage.payload.data.characters
17-
translator.innerText = message.pluginMessage.payload.value
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Figma translate</title>
8+
<style>
9+
body {
10+
font-family: sans-serif;
11+
font-size: 12px;
1812
}
19-
});
2013

21-
const APIkeyInput = document.getElementById('APIkey')
22-
APIkeyInput.onchange = function (event) {
23-
const value = event.target.value;
24-
console.log('Input value changed:', value);
14+
p {
15+
margin: 0;
16+
padding: 5px 0;
2517

26-
parent.postMessage({
27-
pluginMessage: {
28-
type: 'APIkey', payload: {
29-
value
30-
}
18+
}
19+
20+
#origin {
21+
color: #b44646;
22+
}
23+
</style>
24+
</head>
25+
26+
<body>
27+
<div>
28+
<label for="APIkey">Open AI key:</label>
29+
<input type="password" name="APIkey" id="APIkey">
30+
</div>
31+
<p id="origin"></p>
32+
<hr>
33+
<p id="translator"></p>
34+
<script>
35+
const APIkeyInput = document.getElementById('APIkey')
36+
37+
window.addEventListener('message', event => {
38+
const message = event.data;
39+
console.log('Received message:', message);
40+
if (message.pluginMessage.type === "translate") {
41+
const origin = document.getElementById('origin');
42+
const translator = document.getElementById('translator');
43+
origin.innerText = message.pluginMessage.payload.data.characters
44+
translator.innerText = message.pluginMessage.payload.value
3145
}
32-
}, '*')
33-
};
3446

35-
</script>
47+
if (message.pluginMessage.type === "APIkey") {
48+
APIkeyInput.value = message.pluginMessage.payload.value
49+
}
50+
});
51+
52+
53+
APIkeyInput.onchange = function (event) {
54+
const value = event.target.value;
55+
console.log('Input value changed:', value);
56+
57+
parent.postMessage({
58+
pluginMessage: {
59+
type: 'APIkey', payload: {
60+
value
61+
}
62+
}
63+
}, '*')
64+
};
65+
66+
</script>
67+
</body>
68+
69+
</html>

yarn.lock

+8-1
Original file line numberDiff line numberDiff line change
@@ -1716,7 +1716,14 @@ cosmiconfig@^8.0.0:
17161716
parse-json "^5.2.0"
17171717
path-type "^4.0.0"
17181718

1719-
cross-spawn@^7.0.2:
1719+
cross-env@^7.0.3:
1720+
version "7.0.3"
1721+
resolved "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
1722+
integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
1723+
dependencies:
1724+
cross-spawn "^7.0.1"
1725+
1726+
cross-spawn@^7.0.1, cross-spawn@^7.0.2:
17201727
version "7.0.3"
17211728
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
17221729
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==

0 commit comments

Comments
 (0)