value变更
Some checks failed
test / Run tests (push) Failing after 3s
build / Build (push) Failing after 5s

This commit is contained in:
王一之 2025-04-08 23:54:06 +08:00
parent 3e660a2ea8
commit 9f70b7eb7a
7 changed files with 110 additions and 28 deletions

View File

@ -15,8 +15,8 @@
// ==/UserScript==
GM_addValueChangeListener("test_set", function (name, oldval, newval, remote, tabid) {
GM_cookie("store", tabid,(storeId) => {
console.log("store",storeId);
GM_cookie("store", tabid, (storeId) => {
console.log("store", storeId);
});
});
@ -30,3 +30,7 @@ setTimeout(() => {
}, 3000);
GM_setValue("test_set", new Date().getTime());
console.log(GM_getValue("test_set2"));
GM_setValue("test_set2", new Date().getTime());

View File

@ -9,6 +9,7 @@ import Cache, { incr } from "@App/app/cache";
import { unsafeHeaders } from "@App/runtime/utils";
import EventEmitter from "eventemitter3";
import { MessageQueue } from "@Packages/message/message_queue";
import { RuntimeService } from "./runtime";
// GMApi,处理脚本的GM API调用请求
@ -36,7 +37,8 @@ export default class GMApi {
private group: Group,
private send: MessageSend,
private mq: MessageQueue,
private value: ValueService
private value: ValueService,
private runtime: RuntimeService
) {
this.logger = LoggerCore.logger().with({ service: "runtime/gm_api" });
}
@ -69,12 +71,13 @@ export default class GMApi {
}
@PermissionVerify.API()
GM_setValue(request: Request): Promise<any> {
async GM_setValue(request: Request) {
console.log("setValue", request);
if (!request.params || request.params.length !== 2) {
return Promise.reject(new Error("param is failed"));
}
const [key, value] = request.params;
return this.value.setValue(request.script.uuid, key, value);
await this.value.setValue(request.script.uuid, key, value);
}
// 根据header生成dnr规则

View File

@ -26,13 +26,13 @@ export default class ServiceWorkerManager {
const resource = new ResourceService(this.api.group("resource"), this.mq);
resource.init();
const value = new ValueService(this.api.group("value"));
value.init();
const value = new ValueService(this.api.group("value"), this.sender);
const script = new ScriptService(this.api.group("script"), this.mq, value, resource);
script.init();
const runtime = new RuntimeService(this.api.group("runtime"), this.sender, this.mq, value, script);
runtime.init();
const popup = new PopupService(this.api.group("popup"), this.mq, runtime);
popup.init();
value.init(runtime, popup);
}
}

View File

@ -20,6 +20,7 @@ import {
subscribeScriptMenuRegister,
subscribeScriptRunStatus,
} from "../queue";
import { storageKey } from "@App/runtime/utils";
export type ScriptMenuItem = {
id: number;
@ -33,6 +34,7 @@ export type ScriptMenuItem = {
export type ScriptMenu = {
uuid: string; // 脚本uuid
name: string; // 脚本名称
storageName: string; // 脚本存储名称
enable: boolean; // 脚本是否启用
updatetime: number; // 脚本更新时间
hasUserConfig: boolean; // 是否有用户配置
@ -124,12 +126,6 @@ export class PopupService {
frameId: message.frameId,
documentId: message.documentId,
});
} else {
menu.name = message.name;
menu.accessKey = message.accessKey;
menu.tabId = message.tabId;
menu.frameId = message.frameId;
menu.documentId = message.documentId;
}
}
this.updateScriptMenu();
@ -167,6 +163,7 @@ export class PopupService {
return {
uuid: script.uuid,
name: script.name,
storageName: storageKey(script),
enable: script.status === SCRIPT_STATUS_ENABLE,
updatetime: script.updatetime || 0,
hasUserConfig: !!script.config,
@ -195,6 +192,13 @@ export class PopupService {
}
return this.scriptToMenu(script);
});
runScript.forEach((script) => {
const index = scriptMenu.findIndex((item) => item.uuid === script.uuid);
// 把运行了但是不在匹配中的脚本加入菜单
if (index === -1) {
scriptMenu.push(script);
}
});
// 后台脚本只显示开启或者运行中的脚本
return { scriptList: scriptMenu, backScriptList: await this.getScriptMenu(-1) };
}
@ -221,7 +225,9 @@ export class PopupService {
}) {
// 设置数据
return this.txUpdateScriptMenu(tabId, async (data) => {
data = [];
if (!frameId) {
data = [];
}
// 设置脚本运行次数
scripts.forEach((script) => {
const scriptMenu = data.find((item) => item.uuid === script.uuid);

View File

@ -46,7 +46,7 @@ export class RuntimeService {
async init() {
// 启动gm api
const gmApi = new GMApi(this.group, this.sender, this.mq, this.value);
const gmApi = new GMApi(this.group, this.sender, this.mq, this.value, this);
gmApi.start();
this.group.on("stopScript", this.stopScript.bind(this));
@ -147,7 +147,6 @@ export class RuntimeService {
match.add(uuid);
});
// 转化为数组
console.log("matchScriptUuid", matchScriptUuid);
return Array.from(match);
}
return matchScriptUuid;
@ -187,6 +186,14 @@ export class RuntimeService {
const enableScript = scripts.filter((item) => item);
// 加载value
await Promise.all(
enableScript.map(async (script) => {
const value = await this.value.getScriptValue(script!);
script!.value = value;
})
);
this.mq.emit("pageLoad", {
tabId: chromeSender.tab?.id,
frameId: chromeSender.frameId,

View File

@ -1,16 +1,25 @@
import LoggerCore from "@App/app/logger/core";
import Logger from "@App/app/logger/logger";
import { Script, ScriptDAO } from "@App/app/repo/scripts";
import { Script, SCRIPT_TYPE_NORMAL, ScriptDAO } from "@App/app/repo/scripts";
import { ValueDAO } from "@App/app/repo/value";
import { storageKey } from "@App/runtime/utils";
import { Group } from "@Packages/message/server";
import { Group, MessageSend } from "@Packages/message/server";
import { RuntimeService } from "./runtime";
import { PopupService } from "./popup";
import { ValueUpdateData } from "@App/runtime/content/exec_script";
import { sendMessage } from "@Packages/message/client";
export class ValueService {
logger: Logger;
scriptDAO: ScriptDAO = new ScriptDAO();
valueDAO: ValueDAO = new ValueDAO();
private popup: PopupService | undefined;
private runtime: RuntimeService | undefined;
constructor(private group: Group) {
constructor(
private group: Group,
private send: MessageSend
) {
this.logger = LoggerCore.logger().with({ service: "value" });
}
@ -19,33 +28,63 @@ export class ValueService {
if (!ret) {
return {};
}
return Promise.resolve(ret?.data);
return ret.data;
}
async setValue(uuid: string, key: string, value: any): Promise<boolean> {
async setValue(uuid: string, key: string, value: any, sender?: any): Promise<boolean> {
// 查询出脚本
const script = await this.scriptDAO.get(uuid);
if (!script) {
return Promise.reject(new Error("script not found"));
}
// 查询老的值
const oldValue = await this.valueDAO.get(storageKey(script));
if (!oldValue) {
this.valueDAO.save(storageKey(script), {
const storageName = storageKey(script);
const valueModel = await this.valueDAO.get(storageName);
let oldValue;
if (!valueModel) {
this.valueDAO.save(storageName, {
uuid: script.uuid,
storageName: storageKey(script),
storageName: storageName,
data: { [key]: value },
createtime: Date.now(),
updatetime: Date.now(),
});
} else {
oldValue.data[key] = value;
this.valueDAO.save(storageKey(script), oldValue);
oldValue = valueModel.data[key];
valueModel.data[key] = value;
this.valueDAO.save(storageName, valueModel);
}
const sendData: ValueUpdateData = {
oldValue,
sender,
value,
key,
uuid,
storageKey: storageName,
};
// 判断是后台脚本还是前台脚本
console.log("value update", script, sendData);
if (script.type === SCRIPT_TYPE_NORMAL) {
chrome.tabs.query({}, (tabs) => {
// 推送到所有加载了本脚本的tab中
tabs.forEach(async (tab) => {
const scriptMenu = await this.popup!.getScriptMenu(tab.id!);
if (scriptMenu.find((item) => item.storageName === storageName)) {
this.runtime!.sendMessageToTab(tab.id!, "valueUpdate", sendData);
}
});
});
} else {
// 推送到offscreen中
sendMessage(this.send, "offscreen/runtime/valueUpdate", sendData);
}
return Promise.resolve(true);
}
init() {
init(runtime: RuntimeService, popup: PopupService) {
this.popup = popup;
this.runtime = runtime;
this.group.on("getScriptValue", this.getScriptValue.bind(this));
}
}

View File

@ -178,6 +178,29 @@ export default class GMApi {
this.GM_setValue(name, undefined);
}
valueChangeId: number | undefined;
@GMContext.API()
public GM_addValueChangeListener(name: string, listener: GMTypes.ValueChangeListener): number {
if (!this.valueChangeId) {
this.valueChangeId = 1;
} else {
this.valueChangeId += 1;
}
this.valueChangeListener.set(this.valueChangeId, { name, listener });
return this.valueChangeId;
}
@GMContext.API()
public GM_removeValueChangeListener(listenerId: number): void {
this.valueChangeListener.delete(listenerId);
}
@GMContext.API()
public GM_listValues(): string[] {
return Object.keys(this.scriptRes.value);
}
@GMContext.API()
GM_log(message: string, level?: GMTypes.LoggerLevel, labels?: GMTypes.LoggerLabel) {
if (typeof message !== "string") {