Skip to content

Commit f5ec7a4

Browse files
committed
♻️ 重构vscode功能
1 parent 06dfc18 commit f5ec7a4

9 files changed

Lines changed: 214 additions & 17 deletions

File tree

src/app/service/script/event.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
SCRIPT_STATUS_ENABLE,
99
ScriptDAO,
1010
} from "../../repo/scripts";
11-
import ScriptManager from "./manager";
11+
import ScriptManager, { InstallSource } from "./manager";
1212

1313
export type ScriptEvent =
1414
| "upsert"
@@ -49,10 +49,7 @@ export default class ScriptEventListener {
4949

5050
// 安装或者更新脚本,将数据保存到数据库
5151
@ListenEventDecorator("upsert")
52-
public upsertHandler(
53-
script: Script,
54-
upsertBy: "user" | "system" | "sync" = "user"
55-
) {
52+
public upsertHandler(script: Script, upsertBy: InstallSource = "user") {
5653
return new Promise((resolve, reject) => {
5754
const logger = this.logger.with({
5855
scriptId: script.id,

src/app/service/script/manager.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { Script, SCRIPT_STATUS_DISABLE, ScriptDAO } from "../../repo/scripts";
1212
import ScriptEventListener from "./event";
1313
import Hook from "../hook";
1414

15-
export type InstallSource = "user" | "system" | "sync" | "subscribe";
15+
export type InstallSource = "user" | "system" | "sync" | "subscribe" | "vscode";
1616

1717
// 脚本管理器,负责脚本实际的安装、卸载、更新等操作
1818
@IoC.Singleton(MessageHander, SystemConfig)
@@ -52,6 +52,9 @@ export class ScriptManager extends Manager {
5252
// 启动脚本检查更新
5353
// 十分钟对符合要求的脚本进行检查更新
5454
setInterval(() => {
55+
if (!this.systemConfig.checkScriptUpdateCycle) {
56+
return;
57+
}
5558
this.logger.debug("start check update");
5659
this.scriptDAO.table
5760
.where("checktime")

src/app/service/subscribe/manager.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ export default class SubscribeManager extends Manager {
5858
// 启动订阅检查更新
5959
// 十分钟对符合要求的订阅进行检查更新
6060
setInterval(() => {
61+
if (!this.systemConfig.checkScriptUpdateCycle) {
62+
return;
63+
}
6164
this.logger.debug("start check update");
6265
this.subscribeDAO.table
6366
.where("checktime")
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import IoC from "@App/app/ioc";
2+
import MessageInternal from "@App/app/message/internal";
3+
import Controller from "../controller";
4+
5+
@IoC.Singleton(MessageInternal)
6+
export default class SystemController extends Controller {
7+
internal: MessageInternal;
8+
9+
constructor(internal: MessageInternal) {
10+
super(internal, "system");
11+
this.internal = internal;
12+
}
13+
14+
connectVSCode() {
15+
return this.dispatchEvent("connectVSCode", {});
16+
}
17+
}

src/app/service/system/manager.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { ExternalMessage, ExtVersion, ExtServer } from "@App/app/const";
22
import IoC from "@App/app/ioc";
3+
import { v5 as uuidv5 } from "uuid";
34
import { MessageHander } from "@App/app/message/message";
45
import { ScriptDAO } from "@App/app/repo/scripts";
56
import { SystemConfig } from "@App/pkg/config/config";
7+
import { prepareScriptByCode } from "@App/pkg/utils/script";
68
import semver from "semver";
79
import Manager from "../manager";
10+
import ScriptManager from "../script/manager";
811

912
// value管理器,负责value等更新获取等操作
1013
@IoC.Singleton(MessageHander, SystemConfig)
@@ -13,10 +16,15 @@ export class SystemManager extends Manager {
1316

1417
scriptDAO: ScriptDAO;
1518

19+
scriptManager: ScriptManager;
20+
21+
wsVscode?: WebSocket;
22+
1623
constructor(message: MessageHander, systemConfig: SystemConfig) {
1724
super(message, "system");
1825
this.scriptDAO = new ScriptDAO();
1926
this.systemConfig = systemConfig;
27+
this.scriptManager = IoC.instance(ScriptManager) as ScriptManager;
2028
}
2129

2230
init() {
@@ -92,6 +100,75 @@ export class SystemManager extends Manager {
92100
return Promise.resolve(false);
93101
}
94102
);
103+
this.listenEvent("connectVSCode", this.connectVSCode.bind(this));
104+
105+
this.reconnectVSCode();
106+
}
107+
108+
reconnectVSCode() {
109+
let connectVSCodeTimer: any;
110+
const handler = () => {
111+
if (!this.wsVscode) {
112+
this.connectVSCode();
113+
}
114+
};
115+
if (this.systemConfig.vscodeReconnect) {
116+
connectVSCodeTimer = setInterval(() => {
117+
handler();
118+
}, 30 * 1000);
119+
}
120+
121+
SystemConfig.hook.addListener("update", (key, val) => {
122+
if (key === "vscodeReconnect") {
123+
if (val) {
124+
connectVSCodeTimer = setInterval(() => {
125+
handler();
126+
}, 30 * 1000);
127+
} else {
128+
clearInterval(connectVSCodeTimer);
129+
}
130+
}
131+
});
132+
}
133+
134+
connectVSCode() {
135+
return new Promise<void>((resolve, reject) => {
136+
// 与vsc扩展建立连接
137+
if (this.wsVscode) {
138+
this.wsVscode.close();
139+
}
140+
try {
141+
this.wsVscode = new WebSocket(this.systemConfig.vscodeUrl);
142+
} catch (e: any) {
143+
reject(e);
144+
return;
145+
}
146+
this.wsVscode.addEventListener("open", () => {
147+
this.wsVscode!.send('{"action":"hello"}');
148+
resolve();
149+
});
150+
this.wsVscode.addEventListener("message", async (ev) => {
151+
const data = JSON.parse(ev.data);
152+
switch (data.action) {
153+
case "onchange": {
154+
const code = data.data.script;
155+
const script = await prepareScriptByCode(
156+
code,
157+
"",
158+
uuidv5(code.data.uri, uuidv5.URL)
159+
);
160+
this.scriptManager.event.upsertHandler(script, "vscode");
161+
break;
162+
}
163+
default:
164+
}
165+
});
166+
167+
this.wsVscode.addEventListener("error", () => {
168+
reject(new Error("VSCode连接失败"));
169+
this.wsVscode = undefined;
170+
});
171+
});
95172
}
96173

97174
getNotice(): Promise<{ notice: string; isRead: boolean }> {

src/pages/options/routes/Setting.tsx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import React, { useState } from "react";
2-
import { Button, Card, Checkbox, Message, Space } from "@arco-design/web-react";
2+
import {
3+
Button,
4+
Card,
5+
Checkbox,
6+
Message,
7+
Select,
8+
Space,
9+
} from "@arco-design/web-react";
310
import FileSystemParams from "@App/pages/components/FileSystemParams";
411
import { SystemConfig } from "@App/pkg/config/config";
512
import IoC from "@App/app/ioc";
@@ -94,6 +101,24 @@ function Setting() {
94101
</Card>
95102
<Card title="更新" bordered={false}>
96103
<Space direction="vertical">
104+
<Space>
105+
<span>脚本/订阅检查更新间隔:</span>
106+
<Select
107+
defaultValue={systemConfig.checkScriptUpdateCycle.toString()}
108+
style={{
109+
width: 100,
110+
}}
111+
onChange={(value) => {
112+
systemConfig.checkScriptUpdateCycle = parseInt(value, 10);
113+
}}
114+
>
115+
<Select.Option value="0">从不</Select.Option>
116+
<Select.Option value="21600">6小时</Select.Option>
117+
<Select.Option value="43200">12小时</Select.Option>
118+
<Select.Option value="86400">每天</Select.Option>
119+
<Select.Option value="604800">每周</Select.Option>
120+
</Select>
121+
</Space>
97122
<Checkbox
98123
onChange={(checked) => {
99124
systemConfig.updateDisableScript = checked;

src/pages/options/routes/Tools.tsx

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { useRef, useState } from "react";
22
import {
33
Button,
44
Card,
5+
Checkbox,
56
Drawer,
67
Empty,
78
Input,
@@ -18,6 +19,9 @@ import { SystemConfig } from "@App/pkg/config/config";
1819
import { File, FileReader } from "@Pkg/filesystem/filesystem";
1920
import { formatUnixTime } from "@App/pkg/utils/utils";
2021
import FileSystemParams from "@App/pages/components/FileSystemParams";
22+
import { IconQuestionCircleFill } from "@arco-design/web-react/icon";
23+
import { RefInputType } from "@arco-design/web-react/es/Input/interface";
24+
import SystemController from "@App/app/service/system/controller";
2125

2226
function Tools() {
2327
const [loading, setLoading] = useState<{ [key: string]: boolean }>({});
@@ -32,6 +36,8 @@ function Tools() {
3236
}>(systemConfig.backup.params[fileSystemType] || {});
3337
const [backupFileList, setBackupFileList] = useState<File[]>([]);
3438

39+
const vscodeRef = useRef<RefInputType>(null);
40+
3541
return (
3642
<Space
3743
direction="vertical"
@@ -240,10 +246,63 @@ function Tools() {
240246
</Space>
241247
</Card>
242248

243-
<Card title="开发调试" bordered={false}>
249+
<Card
250+
title={
251+
<>
252+
<span>开发调试</span>
253+
<Button
254+
type="text"
255+
style={{
256+
height: 24,
257+
}}
258+
icon={
259+
<IconQuestionCircleFill
260+
style={{
261+
margin: 0,
262+
}}
263+
/>
264+
}
265+
href="https://www.bilibili.com/video/BV16q4y157CP"
266+
target="_blank"
267+
iconOnly
268+
/>
269+
</>
270+
}
271+
bordered={false}
272+
>
244273
<Space direction="vertical">
245274
<Title heading={6}>VSCode地址</Title>
246-
<Input />
275+
<Input
276+
ref={vscodeRef}
277+
defaultValue={systemConfig.vscodeUrl}
278+
onChange={(value) => {
279+
systemConfig.vscodeUrl = value;
280+
}}
281+
/>
282+
<Checkbox
283+
onChange={(checked) => {
284+
systemConfig.vscodeReconnect = checked;
285+
}}
286+
defaultChecked={systemConfig.vscodeReconnect}
287+
>
288+
自动连接vscode服务
289+
</Checkbox>
290+
<Button
291+
type="primary"
292+
onClick={() => {
293+
const ctrl = IoC.instance(SystemController) as SystemController;
294+
ctrl
295+
.connectVSCode()
296+
.then(() => {
297+
Message.success("连接成功");
298+
})
299+
.catch((e) => {
300+
Message.error(`连接失败: ${e}`);
301+
});
302+
}}
303+
>
304+
连接
305+
</Button>
247306
</Space>
248307
</Card>
249308
</Space>

src/pages/options/routes/script/ScriptEditor.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ function ScriptEditor() {
647647
))}
648648
</Tabs>
649649
<div className="flex flex-grow flex-1">
650-
{editors.map((item, index) => {
650+
{editors.map((item) => {
651651
// 先这样吧
652652
setTimeout(() => {
653653
if (item.active && item.editor) {
@@ -668,15 +668,23 @@ function ScriptEditor() {
668668
hotKeys={item.hotKeys}
669669
callbackEditor={(e) => {
670670
setEditors((prev) => {
671-
prev[index].editor = e;
671+
prev.forEach((v) => {
672+
if (v.script.uuid === item.script.uuid) {
673+
v.editor = e;
674+
}
675+
});
672676
return [...prev];
673677
});
674678
}}
675679
onChange={(code) => {
676680
const isChanged = !(item.code === code);
677681
if (isChanged !== item.isChanged) {
678682
setEditors((prev) => {
679-
prev[index].isChanged = isChanged;
683+
prev.forEach((v) => {
684+
if (v.script.id === item.script.id) {
685+
v.isChanged = isChanged;
686+
}
687+
});
680688
return [...prev];
681689
});
682690
}

src/pkg/utils/script.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ export async function fetchScriptInfo(
129129
export function copyScript(script: Script, old: Script): Script {
130130
const ret = script;
131131
ret.id = old.id;
132-
ret.uuid = old.uuid;
132+
// ret.uuid = old.uuid;
133133
ret.createtime = old.createtime;
134134
ret.lastruntime = old.lastruntime;
135135
// ret.delayruntime = old.delayruntime;
@@ -247,11 +247,16 @@ export function prepareScriptByCode(
247247
[, domain] = urlSplit;
248248
}
249249
}
250-
// N1-MTIwLjIyOC4wLjE4ODoxNjY4NTIyOTgyOjQ3OTYzNDc5NTMxMzQ1MzM0OQ==
251-
// N1-MTIwLjIyOC4wLjE4ODoxNjY4NTIyOTgyOjQ3OTYzNDc5NTMxMzQ1MzM0OQ==
250+
if (!uuid) {
251+
if (url) {
252+
uuid = uuidv5(url, uuidv5.URL);
253+
} else {
254+
uuid = uuidv4();
255+
}
256+
}
252257
let script: Script & { oldScript?: Script } = {
253258
id: 0,
254-
uuid: uuid || uuidv4(),
259+
uuid,
255260
name: metadata.name[0],
256261
code,
257262
author: metadata.author && metadata.author[0],
@@ -273,8 +278,11 @@ export function prepareScriptByCode(
273278
};
274279
const handler = async () => {
275280
let old: Script | undefined;
276-
if (uuid !== undefined) {
281+
if (uuid) {
277282
old = await dao.findByUUID(uuid);
283+
if (!old && url) {
284+
old = await dao.findByNameAndNamespace(script.name, script.namespace);
285+
}
278286
} else {
279287
old = await dao.findByNameAndNamespace(script.name, script.namespace);
280288
if (!old) {

0 commit comments

Comments
 (0)