Compare commits
5 Commits
d9fdded7fb
...
e1a890a400
Author | SHA1 | Date | |
---|---|---|---|
e1a890a400 | |||
79e8b8869a | |||
d761c62500 | |||
d200809fee | |||
67ba515b2c |
34
example/gm_value/gm_value.js
Normal file
34
example/gm_value/gm_value.js
Normal file
@ -0,0 +1,34 @@
|
||||
// ==UserScript==
|
||||
// @name gm value
|
||||
// @namespace https://bbs.tampermonkey.net.cn/
|
||||
// @version 0.1.0
|
||||
// @description 可以持久化存储数据, 并且可以监听数据变化
|
||||
// @author You
|
||||
// @match https://bbs.tampermonkey.net.cn/
|
||||
// @run-at document-start
|
||||
// @grant GM_setValue
|
||||
// @grant GM_getValue
|
||||
// @grant GM_addValueChangeListener
|
||||
// @grant GM_listValues
|
||||
// @grant GM_deleteValue
|
||||
// @grant GM_cookie
|
||||
// ==/UserScript==
|
||||
|
||||
GM_addValueChangeListener("test_set", function (name, oldval, newval, remote) {
|
||||
console.log("test_set change", name, oldval, newval, remote);
|
||||
});
|
||||
|
||||
setInterval(() => {
|
||||
console.log(GM_getValue("test_set"));
|
||||
console.log(GM_listValues());
|
||||
}, 2000);
|
||||
|
||||
setTimeout(() => {
|
||||
GM_deleteValue("test_set");
|
||||
}, 3000);
|
||||
|
||||
GM_setValue("test_set", new Date().getTime());
|
||||
|
||||
console.log(GM_getValue("test_set2"));
|
||||
|
||||
GM_setValue("test_set2", new Date().getTime());
|
@ -5,13 +5,16 @@ import { MessageSend } from "@Packages/message/server";
|
||||
export default class MessageWriter implements Writer {
|
||||
send: MessageSend;
|
||||
|
||||
constructor(connect: MessageSend) {
|
||||
constructor(
|
||||
connect: MessageSend,
|
||||
private action: string = "logger"
|
||||
) {
|
||||
this.send = connect;
|
||||
}
|
||||
|
||||
write(level: LogLevel, message: string, label: LogLabel): void {
|
||||
this.send.sendMessage({
|
||||
action: "logger",
|
||||
action: this.action,
|
||||
data: {
|
||||
id: 0,
|
||||
level,
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { getStorageName } from "@App/pkg/utils/utils";
|
||||
import { db } from "./repo/dao";
|
||||
import { Script, ScriptAndCode, ScriptCodeDAO, ScriptDAO } from "./repo/scripts";
|
||||
import { Subscribe, SubscribeDAO } from "./repo/subscribe";
|
||||
import { Value, ValueDAO } from "./repo/value";
|
||||
import { Permission, PermissionDAO } from "./repo/permission";
|
||||
|
||||
// 0.10.0重构,重命名字段,统一使用小峰驼
|
||||
function renameField() {
|
||||
@ -34,98 +37,195 @@ function renameField() {
|
||||
export: "++id,&scriptId",
|
||||
});
|
||||
// 将脚本数据迁移到chrome.storage
|
||||
db.version(18).upgrade(async (tx) => {
|
||||
// 迁移脚本
|
||||
const scripts = await tx.table("scripts").toArray();
|
||||
const scriptDAO = new ScriptDAO();
|
||||
const scriptCodeDAO = new ScriptCodeDAO();
|
||||
await Promise.all(
|
||||
scripts.map((script: ScriptAndCode) => {
|
||||
const {
|
||||
uuid,
|
||||
name,
|
||||
namespace,
|
||||
author,
|
||||
originDomain,
|
||||
subscribeUrl,
|
||||
type,
|
||||
sort,
|
||||
status,
|
||||
runStatus,
|
||||
metadata,
|
||||
createtime,
|
||||
checktime,
|
||||
code,
|
||||
} = script;
|
||||
return scriptDAO
|
||||
.save({
|
||||
uuid,
|
||||
name,
|
||||
namespace,
|
||||
author,
|
||||
originDomain,
|
||||
subscribeUrl,
|
||||
type,
|
||||
sort,
|
||||
status,
|
||||
runStatus,
|
||||
metadata,
|
||||
createtime,
|
||||
checktime,
|
||||
})
|
||||
.then((s) =>
|
||||
scriptCodeDAO.save({
|
||||
uuid: s.uuid,
|
||||
db.version(18).upgrade(() => {
|
||||
// 默认使用的事务,这里加个延时,用db.open()打开数据库后,再执行
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
// 迁移脚本
|
||||
const scripts = await db.table("scripts").toArray();
|
||||
const scriptDAO = new ScriptDAO();
|
||||
const scriptCodeDAO = new ScriptCodeDAO();
|
||||
console.log("开始迁移脚本数据", scripts.length);
|
||||
await Promise.all(
|
||||
scripts.map(async (script: ScriptAndCode) => {
|
||||
const {
|
||||
uuid,
|
||||
name,
|
||||
namespace,
|
||||
author,
|
||||
originDomain,
|
||||
subscribeUrl,
|
||||
type,
|
||||
sort,
|
||||
status,
|
||||
runStatus,
|
||||
metadata,
|
||||
createtime,
|
||||
checktime,
|
||||
code,
|
||||
checkUpdateUrl,
|
||||
downloadUrl,
|
||||
selfMetadata,
|
||||
config,
|
||||
error,
|
||||
updatetime,
|
||||
lastruntime,
|
||||
nextruntime,
|
||||
} = script;
|
||||
const s = await scriptDAO.save({
|
||||
uuid,
|
||||
name,
|
||||
namespace,
|
||||
author,
|
||||
originDomain,
|
||||
origin,
|
||||
checkUpdateUrl,
|
||||
downloadUrl,
|
||||
metadata,
|
||||
selfMetadata,
|
||||
subscribeUrl,
|
||||
config,
|
||||
type,
|
||||
status,
|
||||
sort,
|
||||
runStatus,
|
||||
error,
|
||||
createtime,
|
||||
updatetime,
|
||||
checktime,
|
||||
lastruntime,
|
||||
nextruntime,
|
||||
});
|
||||
return scriptCodeDAO
|
||||
.save({
|
||||
uuid: s.uuid,
|
||||
code,
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log("脚本代码迁移失败", e);
|
||||
return Promise.reject(e);
|
||||
});
|
||||
})
|
||||
);
|
||||
// 迁移订阅
|
||||
const subscribe = await db.table("subscribe").toArray();
|
||||
const subscribeDAO = new SubscribeDAO();
|
||||
if (subscribe.length) {
|
||||
await Promise.all(
|
||||
subscribe.map((s: Subscribe) => {
|
||||
console.log("1234", s);
|
||||
const { url, name, code, author, scripts, metadata, status, createtime, updatetime, checktime } = s;
|
||||
return subscribeDAO.save({
|
||||
url,
|
||||
name,
|
||||
code,
|
||||
author,
|
||||
scripts,
|
||||
metadata,
|
||||
status,
|
||||
createtime,
|
||||
updatetime,
|
||||
checktime,
|
||||
});
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
// 迁移订阅
|
||||
const subscribe = await tx.table("subscribe").toArray();
|
||||
const subscribeDAO = new SubscribeDAO();
|
||||
await Promise.all(
|
||||
subscribe.map((s: Subscribe) => {
|
||||
const { url, name, code, author, scripts, metadata, status, createtime, updatetime, checktime } = s;
|
||||
return subscribeDAO.save({
|
||||
url,
|
||||
name,
|
||||
code,
|
||||
author,
|
||||
scripts,
|
||||
metadata,
|
||||
status,
|
||||
createtime,
|
||||
updatetime,
|
||||
checktime,
|
||||
});
|
||||
})
|
||||
);
|
||||
// 迁移value
|
||||
interface MV2Value {
|
||||
id: number;
|
||||
scriptId: number;
|
||||
storageName?: string;
|
||||
key: string;
|
||||
value: any;
|
||||
createtime: number;
|
||||
updatetime: number;
|
||||
}
|
||||
const values = await tx.table("value").toArray();
|
||||
const valueDAO = new ScriptCodeDAO();
|
||||
await Promise.all(
|
||||
values.map((v) => {
|
||||
const { scriptId, storageName, key, value, createtime } = v;
|
||||
return valueDAO.save({
|
||||
scriptId,
|
||||
storageName,
|
||||
key,
|
||||
value,
|
||||
createtime,
|
||||
});
|
||||
})
|
||||
);
|
||||
// 迁移permission
|
||||
}
|
||||
console.log("订阅数据迁移完成", subscribe.length);
|
||||
// 迁移value
|
||||
interface MV2Value {
|
||||
id: number;
|
||||
scriptId: number;
|
||||
storageName?: string;
|
||||
key: string;
|
||||
value: any;
|
||||
createtime: number;
|
||||
updatetime: number;
|
||||
}
|
||||
const values = await db.table("value").toArray();
|
||||
const valueDAO = new ValueDAO();
|
||||
const valueMap = new Map<string, Value>();
|
||||
await Promise.all(
|
||||
values.map((v: MV2Value) => {
|
||||
const { scriptId, storageName, key, value, createtime } = v;
|
||||
return db
|
||||
.table("scripts")
|
||||
.where("id")
|
||||
.equals(scriptId)
|
||||
.first((script: Script) => {
|
||||
if (script) {
|
||||
let data: { [key: string]: any } = {};
|
||||
if (!valueMap.has(script.uuid)) {
|
||||
valueMap.set(script.uuid, {
|
||||
uuid: script.uuid,
|
||||
storageName: getStorageName(script),
|
||||
data: data,
|
||||
createtime,
|
||||
updatetime: 0,
|
||||
});
|
||||
} else {
|
||||
data = valueMap.get(script.uuid)!.data;
|
||||
}
|
||||
data[key] = value;
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
// 保存到数据库
|
||||
await Promise.all(
|
||||
Array.from(valueMap.keys()).map((uuid) => {
|
||||
const { storageName, data, createtime } = valueMap.get(uuid)!;
|
||||
return valueDAO.save(storageName!, {
|
||||
uuid,
|
||||
storageName,
|
||||
data,
|
||||
createtime,
|
||||
updatetime: 0,
|
||||
});
|
||||
})
|
||||
);
|
||||
console.log("脚本value数据迁移完成", values.length);
|
||||
// 迁移permission
|
||||
const permissions = await db.table("permission").toArray();
|
||||
const permissionDAO = new PermissionDAO();
|
||||
await Promise.all(
|
||||
permissions.map((p: Permission & { scriptId: number }) => {
|
||||
const { scriptId, permission, permissionValue, createtime, updatetime, allow } = p;
|
||||
return db
|
||||
.table("scripts")
|
||||
.where("id")
|
||||
.equals(scriptId)
|
||||
.first((script: Script) => {
|
||||
if (script) {
|
||||
return permissionDAO.save({
|
||||
uuid: script.uuid,
|
||||
permission,
|
||||
permissionValue,
|
||||
createtime,
|
||||
updatetime,
|
||||
allow,
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
console.log("脚本permission数据迁移完成", permissions.length);
|
||||
// 打开页面,告知数据储存+升级至了mv3,重启一次扩展
|
||||
setTimeout(async () => {
|
||||
const scripts = await scriptDAO.all();
|
||||
console.log("脚本数据迁移完成", scripts.length);
|
||||
if (scripts.length > 0) {
|
||||
chrome.tabs.create({
|
||||
url: "https://docs.scriptcat.org/docs/change/v0.17/",
|
||||
});
|
||||
setTimeout(() => {
|
||||
chrome.runtime.reload();
|
||||
}, 1000);
|
||||
}
|
||||
}, 2000);
|
||||
} catch (e) {
|
||||
console.error("脚本数据迁移失败", e);
|
||||
}
|
||||
}, 200);
|
||||
});
|
||||
return db.open();
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import LoggerCore from "@App/app/logger/core";
|
||||
import Logger from "@App/app/logger/logger";
|
||||
import { ScriptRunResouce } from "@App/app/repo/scripts";
|
||||
import { Client, sendMessage } from "@Packages/message/client";
|
||||
import { CustomEventMessage } from "@Packages/message/custom_event_message";
|
||||
@ -83,7 +85,17 @@ export default class ContentRuntime {
|
||||
case "GM_log":
|
||||
// 拦截GM_log,打印到控制台
|
||||
// 由于某些页面会处理掉console.log,所以丢到这里来打印
|
||||
console.log(...data.params);
|
||||
switch (data.params.length) {
|
||||
case 1:
|
||||
console.log(data.params[0]);
|
||||
break;
|
||||
case 2:
|
||||
console.log("[" + data.params[1] + "]", data.params[0]);
|
||||
break;
|
||||
case 3:
|
||||
console.log("[" + data.params[1] + "]", data.params[0], data.params[2]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
@ -159,10 +159,11 @@ export default class GMApi {
|
||||
}
|
||||
if (value === undefined) {
|
||||
delete this.scriptRes.value[key];
|
||||
return this.sendMessage("GM_setValue", [key]);
|
||||
} else {
|
||||
this.scriptRes.value[key] = value;
|
||||
return this.sendMessage("GM_setValue", [key, value]);
|
||||
}
|
||||
return this.sendMessage("GM_setValue", [key, value]);
|
||||
}
|
||||
|
||||
@GMContext.API({ depend: ["GM_setValue"] })
|
||||
@ -391,7 +392,7 @@ export default class GMApi {
|
||||
anonymous: details.anonymous,
|
||||
user: details.user,
|
||||
password: details.password,
|
||||
maxRedirects: details.maxRedirects,
|
||||
redirect: details.redirect,
|
||||
};
|
||||
if (!param.headers) {
|
||||
param.headers = {};
|
||||
|
@ -20,6 +20,10 @@ export class OffscreenManager {
|
||||
|
||||
private serviceWorker = new ServiceWorkerClient(this.extensionMessage);
|
||||
|
||||
constructor(private extensionMessage:MessageSend) {
|
||||
|
||||
}
|
||||
|
||||
logger(data: Logger) {
|
||||
const dao = new LoggerDAO();
|
||||
dao.save(data);
|
||||
|
@ -10,6 +10,7 @@ import { v4 as uuidv4 } from "uuid";
|
||||
import Cache from "@App/app/cache";
|
||||
import CacheKey from "@App/app/cache_key";
|
||||
import { Subscribe } from "@App/app/repo/subscribe";
|
||||
import { Permission } from "@App/app/repo/permission";
|
||||
|
||||
export class ServiceWorkerClient extends Client {
|
||||
constructor(msg: MessageSend) {
|
||||
@ -59,6 +60,16 @@ export class ScriptClient extends Client {
|
||||
return this.do("excludeUrl", { uuid, url, remove });
|
||||
}
|
||||
|
||||
// 重置匹配项
|
||||
resetMatch(uuid: string, match: string[] | undefined) {
|
||||
return this.do("resetMatch", { uuid, match });
|
||||
}
|
||||
|
||||
// 重置排除项
|
||||
resetExclude(uuid: string, exclude: string[] | undefined) {
|
||||
return this.do("resetExclude", { uuid, exclude });
|
||||
}
|
||||
|
||||
requestCheckUpdate(uuid: string) {
|
||||
return this.do("requestCheckUpdate", uuid);
|
||||
}
|
||||
@ -72,6 +83,10 @@ export class ResourceClient extends Client {
|
||||
getScriptResources(script: Script): Promise<{ [key: string]: Resource }> {
|
||||
return this.do("getScriptResources", script);
|
||||
}
|
||||
|
||||
deleteResource(url: string) {
|
||||
return this.do("deleteResource", url);
|
||||
}
|
||||
}
|
||||
|
||||
export class ValueClient extends Client {
|
||||
@ -79,7 +94,7 @@ export class ValueClient extends Client {
|
||||
super(msg, "serviceWorker/value");
|
||||
}
|
||||
|
||||
getScriptValue(script: Script) {
|
||||
getScriptValue(script: Script): Promise<{ [key: string]: any }> {
|
||||
return this.do("getScriptValue", script);
|
||||
}
|
||||
|
||||
@ -154,6 +169,22 @@ export class PermissionClient extends Client {
|
||||
getPermissionInfo(uuid: string): ReturnType<PermissionVerify["getInfo"]> {
|
||||
return this.do("getInfo", uuid);
|
||||
}
|
||||
|
||||
deletePermission(uuid: string, permission: string, permissionValue: string) {
|
||||
return this.do("deletePermission", { uuid, permission, permissionValue });
|
||||
}
|
||||
|
||||
getScriptPermissions(uuid: string): ReturnType<PermissionVerify["getScriptPermissions"]> {
|
||||
return this.do("getScriptPermissions", uuid);
|
||||
}
|
||||
|
||||
addPermission(permission: Permission) {
|
||||
return this.do("addPermission", permission);
|
||||
}
|
||||
|
||||
resetPermission(uuid: string) {
|
||||
return this.do("resetPermission", uuid);
|
||||
}
|
||||
}
|
||||
|
||||
export class SynchronizeClient extends Client {
|
||||
|
@ -242,7 +242,7 @@ export default class GMApi {
|
||||
|
||||
@PermissionVerify.API()
|
||||
async GM_setValue(request: Request, sender: GetSender) {
|
||||
if (!request.params || request.params.length !== 2) {
|
||||
if (!request.params || request.params.length < 1) {
|
||||
throw new Error("param is failed");
|
||||
}
|
||||
const [key, value] = request.params;
|
||||
|
@ -96,15 +96,6 @@ export default class PermissionVerify {
|
||||
reject: (reason: any) => void;
|
||||
}> = new Queue();
|
||||
|
||||
async removePermissionCache(uuid: string) {
|
||||
// 先删除缓存
|
||||
(await Cache.getInstance().list()).forEach((key) => {
|
||||
if (key.startsWith(`permission:${uuid}:`)) {
|
||||
Cache.getInstance().del(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private permissionDAO: PermissionDAO = new PermissionDAO();
|
||||
|
||||
constructor(private group: Group) {}
|
||||
@ -310,9 +301,45 @@ export default class PermissionVerify {
|
||||
return Promise.resolve({ script, confirm, likeNum });
|
||||
}
|
||||
|
||||
async deletePermission(data: { uuid: string; permission: string; permissionValue: string }) {
|
||||
const oldConfirm = await this.permissionDAO.findByKey(data.uuid, data.permission, data.permissionValue);
|
||||
if (!oldConfirm) {
|
||||
throw new Error("permission not found");
|
||||
} else {
|
||||
await this.permissionDAO.delete(this.permissionDAO.key(oldConfirm));
|
||||
// 删除缓存
|
||||
Cache.getInstance().del(CacheKey.permissionConfirm(data.uuid, oldConfirm));
|
||||
}
|
||||
}
|
||||
|
||||
getScriptPermissions(uuid: string) {
|
||||
// 获取脚本的所有权限
|
||||
return this.permissionDAO.find((key, item) => item.uuid === uuid);
|
||||
}
|
||||
|
||||
// 添加权限
|
||||
async addPermission(permission: Permission) {
|
||||
await this.permissionDAO.save(permission);
|
||||
Cache.getInstance().del(CacheKey.permissionConfirm(permission.uuid, permission));
|
||||
}
|
||||
|
||||
// 重置权限
|
||||
async resetPermission(uuid: string) {
|
||||
// 删除所有权限
|
||||
const permissions = await this.permissionDAO.find((key, item) => item.uuid === uuid);
|
||||
permissions.forEach((item) => {
|
||||
this.permissionDAO.delete(this.permissionDAO.key(item));
|
||||
Cache.getInstance().del(CacheKey.permissionConfirm(uuid, item));
|
||||
});
|
||||
}
|
||||
|
||||
init() {
|
||||
this.dealConfirmQueue();
|
||||
this.group.on("confirm", this.userConfirm.bind(this));
|
||||
this.group.on("getInfo", this.getInfo.bind(this));
|
||||
this.group.on("deletePermission", this.deletePermission.bind(this));
|
||||
this.group.on("getScriptPermissions", this.getScriptPermissions.bind(this));
|
||||
this.group.on("addPermission", this.getInfo.bind(this));
|
||||
this.group.on("resetPermission", this.resetPermission.bind(this));
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +305,20 @@ export class ResourceService {
|
||||
return { url: urls[0], hash };
|
||||
}
|
||||
|
||||
async deleteResource(url: string) {
|
||||
// 删除缓存
|
||||
const res = await this.resourceDAO.get(url);
|
||||
if (!res) {
|
||||
throw new Error("resource not found");
|
||||
}
|
||||
Object.keys(res.link).forEach((key) => {
|
||||
this.cache.delete(key);
|
||||
});
|
||||
return this.resourceDAO.delete(url);
|
||||
}
|
||||
|
||||
init() {
|
||||
this.group.on("getScriptResources", this.getScriptResources.bind(this));
|
||||
this.group.on("deleteResource", this.deleteResource.bind(this));
|
||||
}
|
||||
}
|
||||
|
@ -384,15 +384,15 @@ export class RuntimeService {
|
||||
// 加载页面脚本, 会把脚本信息放入缓存中
|
||||
// 如果脚本开启, 则注册脚本
|
||||
async loadPageScript(script: Script) {
|
||||
const matches = script.metadata["match"];
|
||||
const scriptRes = await this.script.buildScriptRunResource(script);
|
||||
const matches = scriptRes.metadata["match"];
|
||||
if (!matches) {
|
||||
return;
|
||||
}
|
||||
const scriptRes = await this.script.buildScriptRunResource(script);
|
||||
|
||||
scriptRes.code = compileInjectScript(scriptRes);
|
||||
|
||||
matches.push(...(script.metadata["include"] || []));
|
||||
matches.push(...(scriptRes.metadata["include"] || []));
|
||||
const patternMatches = dealPatternMatches(matches);
|
||||
const scriptMatchInfo: ScriptMatchInfo = Object.assign(
|
||||
{ matches: patternMatches.result, excludeMatches: [], customizeExcludeMatches: [] },
|
||||
@ -435,11 +435,11 @@ export class RuntimeService {
|
||||
|
||||
// 如果脚本开启, 则注册脚本
|
||||
if (script.status === SCRIPT_STATUS_ENABLE) {
|
||||
if (!script.metadata["noframes"]) {
|
||||
if (!scriptRes.metadata["noframes"]) {
|
||||
registerScript.allFrames = true;
|
||||
}
|
||||
if (script.metadata["run-at"]) {
|
||||
registerScript.runAt = getRunAt(script.metadata["run-at"]);
|
||||
if (scriptRes.metadata["run-at"]) {
|
||||
registerScript.runAt = getRunAt(scriptRes.metadata["run-at"]);
|
||||
}
|
||||
if (await Cache.getInstance().get("registryScript:" + script.uuid)) {
|
||||
await chrome.userScripts.update([registerScript]);
|
||||
|
@ -320,6 +320,54 @@ export class ScriptService {
|
||||
});
|
||||
}
|
||||
|
||||
async resetExclude({ uuid, exclude }: { uuid: string; exclude: string[] | undefined }) {
|
||||
const script = await this.scriptDAO.get(uuid);
|
||||
if (!script) {
|
||||
throw new Error("script not found");
|
||||
}
|
||||
script.selfMetadata = script.selfMetadata || {};
|
||||
if (exclude) {
|
||||
script.selfMetadata.exclude = exclude;
|
||||
} else {
|
||||
delete script.selfMetadata.exclude;
|
||||
}
|
||||
return this.scriptDAO
|
||||
.update(uuid, script)
|
||||
.then(() => {
|
||||
// 广播一下
|
||||
this.mq.publish("installScript", { script, update: true });
|
||||
return true;
|
||||
})
|
||||
.catch((e) => {
|
||||
this.logger.error("reset exclude error", Logger.E(e));
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
|
||||
async resetMatch({ uuid, match }: { uuid: string; match: string[] | undefined }) {
|
||||
const script = await this.scriptDAO.get(uuid);
|
||||
if (!script) {
|
||||
throw new Error("script not found");
|
||||
}
|
||||
script.selfMetadata = script.selfMetadata || {};
|
||||
if (match) {
|
||||
script.selfMetadata.match = match;
|
||||
} else {
|
||||
delete script.selfMetadata.match;
|
||||
}
|
||||
return this.scriptDAO
|
||||
.update(uuid, script)
|
||||
.then(() => {
|
||||
// 广播一下
|
||||
this.mq.publish("installScript", { script, update: true });
|
||||
return true;
|
||||
})
|
||||
.catch((e) => {
|
||||
this.logger.error("reset match error", Logger.E(e));
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
|
||||
async checkUpdate(uuid: string, source: "user" | "system") {
|
||||
// 检查更新
|
||||
const script = await this.scriptDAO.get(uuid);
|
||||
@ -443,6 +491,8 @@ export class ScriptService {
|
||||
this.group.on("getCode", this.getCode.bind(this));
|
||||
this.group.on("getScriptRunResource", this.buildScriptRunResource.bind(this));
|
||||
this.group.on("excludeUrl", this.excludeUrl.bind(this));
|
||||
this.group.on("resetMatch", this.resetMatch.bind(this));
|
||||
this.group.on("resetExclude", this.resetExclude.bind(this));
|
||||
this.group.on("requestCheckUpdate", this.requestCheckUpdate.bind(this));
|
||||
|
||||
// 定时检查更新, 每10分钟检查一次
|
||||
|
@ -54,7 +54,11 @@ export class ValueService {
|
||||
});
|
||||
} else {
|
||||
oldValue = valueModel.data[key];
|
||||
valueModel.data[key] = value;
|
||||
if (value === undefined) {
|
||||
delete valueModel.data[key];
|
||||
} else {
|
||||
valueModel.data[key] = value;
|
||||
}
|
||||
await this.valueDAO.save(storageName, valueModel);
|
||||
}
|
||||
return true;
|
||||
|
@ -68,6 +68,7 @@
|
||||
"confirm_delete_backup_file": "确认删除备份文件",
|
||||
"confirm_update": "确认更新",
|
||||
"delete_success": "删除成功",
|
||||
"deleting": "删除中",
|
||||
"backup_strategy": "备份策略",
|
||||
"under_construction": "建设中",
|
||||
"development_debugging": "开发调试",
|
||||
|
@ -1,20 +1,19 @@
|
||||
import migrate from "./app/migrate";
|
||||
import { MessageSend } from "@Packages/message/server";
|
||||
import LoggerCore from "./app/logger/core";
|
||||
import DBWriter from "./app/logger/db_writer";
|
||||
import { LoggerDAO } from "./app/repo/logger";
|
||||
import MessageWriter from "./app/logger/message_writer";
|
||||
import { OffscreenManager } from "./app/service/offscreen";
|
||||
|
||||
migrate();
|
||||
import { ExtensionMessageSend } from "@Packages/message/extension_message";
|
||||
|
||||
function main() {
|
||||
// 初始化日志组件
|
||||
const extensionMessage: MessageSend = new ExtensionMessageSend();
|
||||
const loggerCore = new LoggerCore({
|
||||
writer: new DBWriter(new LoggerDAO()),
|
||||
writer: new MessageWriter(extensionMessage),
|
||||
labels: { env: "offscreen" },
|
||||
});
|
||||
loggerCore.logger().debug("offscreen start");
|
||||
// 初始化管理器
|
||||
const manager = new OffscreenManager();
|
||||
const manager = new OffscreenManager(extensionMessage);
|
||||
manager.initManager();
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,6 @@ const CodeEditor: React.ForwardRefRenderFunction<{ editor: editor.IStandaloneCod
|
||||
{ id, className, code, diffCode, editable },
|
||||
ref
|
||||
) => {
|
||||
const settings = useAppSelector((state) => state.setting);
|
||||
const [monacoEditor, setEditor] = useState<editor.IStandaloneCodeEditor>();
|
||||
const [enableEslint, setEnableEslint] = useState(false);
|
||||
const [eslintConfig, setEslintConfig] = useState("");
|
||||
@ -40,9 +39,11 @@ const CodeEditor: React.ForwardRefRenderFunction<{ editor: editor.IStandaloneCod
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("1231", code);
|
||||
if (diffCode === undefined || code === undefined || !div.current) {
|
||||
return () => {};
|
||||
}
|
||||
console.log("1232");
|
||||
let edit: editor.IStandaloneDiffEditor | editor.IStandaloneCodeEditor;
|
||||
const inlineDiv = document.getElementById(id) as HTMLDivElement;
|
||||
// @ts-ignore
|
||||
|
@ -1,22 +1,12 @@
|
||||
import { Resource } from "@App/app/repo/resource";
|
||||
import { Script } from "@App/app/repo/scripts";
|
||||
import { ResourceClient } from "@App/app/service/service_worker/client";
|
||||
import { message } from "@App/pages/store/global";
|
||||
import { base64ToBlob } from "@App/pkg/utils/script";
|
||||
import {
|
||||
Button,
|
||||
Drawer,
|
||||
Input,
|
||||
Message,
|
||||
Popconfirm,
|
||||
Space,
|
||||
Table,
|
||||
} from "@arco-design/web-react";
|
||||
import { Button, Drawer, Input, Message, Popconfirm, Space, Table } from "@arco-design/web-react";
|
||||
import { RefInputType } from "@arco-design/web-react/es/Input/interface";
|
||||
import { ColumnProps } from "@arco-design/web-react/es/Table";
|
||||
import {
|
||||
IconDelete,
|
||||
IconDownload,
|
||||
IconSearch,
|
||||
} from "@arco-design/web-react/icon";
|
||||
import { IconDelete, IconDownload, IconSearch } from "@arco-design/web-react/icon";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@ -33,14 +23,14 @@ const ScriptResource: React.FC<{
|
||||
}> = ({ script, visible, onCancel, onOk }) => {
|
||||
const [data, setData] = useState<ResourceListItem[]>([]);
|
||||
const inputRef = useRef<RefInputType>(null);
|
||||
// const resourceCtrl = IoC.instance(ResourceController) as ResourceController;
|
||||
const { t } = useTranslation();
|
||||
const resourceClient = new ResourceClient(message);
|
||||
|
||||
useEffect(() => {
|
||||
if (!script) {
|
||||
return () => {};
|
||||
}
|
||||
resourceCtrl.getResource(script).then((res) => {
|
||||
resourceClient.getScriptResources(script).then((res) => {
|
||||
const arr: ResourceListItem[] = [];
|
||||
Object.keys(res).forEach((key) => {
|
||||
// @ts-ignore
|
||||
@ -120,10 +110,21 @@ const ScriptResource: React.FC<{
|
||||
title={t("confirm_delete_resource")}
|
||||
onOk={() => {
|
||||
Message.info({
|
||||
content: t("delete_success"),
|
||||
content: t("deleting"),
|
||||
});
|
||||
resourceCtrl.deleteResource(value.id);
|
||||
setData(data.filter((_, i) => i !== index));
|
||||
resourceClient
|
||||
.deleteResource(value.url)
|
||||
.then(() => {
|
||||
Message.info({
|
||||
content: t("delete_success"),
|
||||
});
|
||||
setData(data.filter((_, i) => i !== index));
|
||||
})
|
||||
.catch((e) => {
|
||||
Message.error({
|
||||
content: t("delete_failed") + ": " + e.message,
|
||||
});
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Button type="text" iconOnly icon={<IconDelete />} />
|
||||
@ -154,7 +155,7 @@ const ScriptResource: React.FC<{
|
||||
onOk={() => {
|
||||
setData((prev) => {
|
||||
prev.forEach((v) => {
|
||||
resourceCtrl.deleteResource(v.id);
|
||||
resourceClient.deleteResource(v.url);
|
||||
});
|
||||
Message.info({
|
||||
content: t("clear_success"),
|
||||
|
@ -1,31 +1,24 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Script } from "@App/app/repo/scripts";
|
||||
import {
|
||||
Space,
|
||||
Popconfirm,
|
||||
Button,
|
||||
Divider,
|
||||
Typography,
|
||||
Modal,
|
||||
Input,
|
||||
} from "@arco-design/web-react";
|
||||
import { Script, ScriptDAO } from "@App/app/repo/scripts";
|
||||
import { Space, Popconfirm, Button, Divider, Typography, Modal, Input } from "@arco-design/web-react";
|
||||
import Table, { ColumnProps } from "@arco-design/web-react/es/Table";
|
||||
import { IconDelete } from "@arco-design/web-react/icon";
|
||||
import { scriptClient } from "@App/pages/store/features/script";
|
||||
|
||||
type MatchItem = {
|
||||
// id是为了避免match重复
|
||||
id: number;
|
||||
match: string;
|
||||
self: boolean;
|
||||
hasMatch: boolean;
|
||||
isExclude: boolean;
|
||||
byUser: boolean;
|
||||
hasMatch: boolean; // 是否已经匹配
|
||||
isExclude: boolean; // 是否是排除项
|
||||
};
|
||||
|
||||
const Match: React.FC<{
|
||||
script: Script;
|
||||
}> = ({ script }) => {
|
||||
// const scriptCtrl = IoC.instance(ScriptController) as ScriptController;
|
||||
const scriptDAO = new ScriptDAO();
|
||||
const [match, setMatch] = useState<MatchItem[]>([]);
|
||||
const [exclude, setExclude] = useState<MatchItem[]>([]);
|
||||
const [matchValue, setMatchValue] = useState<string>("");
|
||||
@ -37,7 +30,7 @@ const Match: React.FC<{
|
||||
useEffect(() => {
|
||||
if (script) {
|
||||
// 从数据库中获取是简单处理数据一致性的问题
|
||||
scriptCtrl.scriptDAO.findById(script.id).then((res) => {
|
||||
scriptDAO.get(script.uuid).then((res) => {
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
@ -48,28 +41,17 @@ const Match: React.FC<{
|
||||
});
|
||||
const v: MatchItem[] = [];
|
||||
matchArr.forEach((value, index) => {
|
||||
if (matchMap.has(value)) {
|
||||
v.push({
|
||||
id: index,
|
||||
match: value,
|
||||
self: false,
|
||||
hasMatch: false,
|
||||
isExclude: false,
|
||||
});
|
||||
} else {
|
||||
v.push({
|
||||
id: index,
|
||||
match: value,
|
||||
self: true,
|
||||
hasMatch: false,
|
||||
isExclude: false,
|
||||
});
|
||||
}
|
||||
v.push({
|
||||
id: index,
|
||||
match: value,
|
||||
byUser: !matchMap.has(value),
|
||||
hasMatch: false,
|
||||
isExclude: false,
|
||||
});
|
||||
});
|
||||
setMatch(v);
|
||||
|
||||
const excludeArr =
|
||||
res.selfMetadata?.exclude || res.metadata.exclude || [];
|
||||
const excludeArr = res.selfMetadata?.exclude || res.metadata.exclude || [];
|
||||
const excludeMap = new Map<string, boolean>();
|
||||
res.metadata.exclude?.forEach((m) => {
|
||||
excludeMap.set(m, true);
|
||||
@ -77,23 +59,13 @@ const Match: React.FC<{
|
||||
const e: MatchItem[] = [];
|
||||
excludeArr.forEach((value, index) => {
|
||||
const hasMatch = matchMap.has(value);
|
||||
if (excludeMap.has(value)) {
|
||||
e.push({
|
||||
id: index,
|
||||
match: value,
|
||||
self: false,
|
||||
hasMatch,
|
||||
isExclude: true,
|
||||
});
|
||||
} else {
|
||||
e.push({
|
||||
id: index,
|
||||
match: value,
|
||||
self: true,
|
||||
hasMatch,
|
||||
isExclude: true,
|
||||
});
|
||||
}
|
||||
e.push({
|
||||
id: index,
|
||||
match: value,
|
||||
byUser: !excludeMap.has(value),
|
||||
hasMatch,
|
||||
isExclude: true,
|
||||
});
|
||||
});
|
||||
setExclude(e);
|
||||
});
|
||||
@ -108,8 +80,8 @@ const Match: React.FC<{
|
||||
},
|
||||
{
|
||||
title: t("user_setting"),
|
||||
dataIndex: "self",
|
||||
key: "self",
|
||||
dataIndex: "byUser",
|
||||
key: "byUser",
|
||||
width: 100,
|
||||
render(col) {
|
||||
if (col) {
|
||||
@ -125,23 +97,24 @@ const Match: React.FC<{
|
||||
return (
|
||||
<Space>
|
||||
<Popconfirm
|
||||
title={`${t("confirm_delete_exclude")}${
|
||||
item.hasMatch ? ` ${t("after_deleting_match_item")}` : ""
|
||||
}`}
|
||||
title={`${t("confirm_delete_exclude")}${item.hasMatch ? ` ${t("after_deleting_match_item")}` : ""}`}
|
||||
onOk={() => {
|
||||
exclude.splice(exclude.indexOf(item), 1);
|
||||
scriptCtrl
|
||||
// 删除所有排除
|
||||
scriptClient
|
||||
.resetExclude(
|
||||
script.id,
|
||||
script.uuid,
|
||||
exclude.map((m) => m.match)
|
||||
)
|
||||
.then(() => {
|
||||
setExclude([...exclude]);
|
||||
// 如果包含在里面,再加回match
|
||||
if (item.hasMatch) {
|
||||
match.push(item);
|
||||
scriptCtrl
|
||||
// 重置匹配
|
||||
scriptClient
|
||||
.resetMatch(
|
||||
script.id,
|
||||
script.uuid,
|
||||
match.map((m) => m.match)
|
||||
)
|
||||
.then(() => {
|
||||
@ -159,24 +132,22 @@ const Match: React.FC<{
|
||||
return (
|
||||
<Space>
|
||||
<Popconfirm
|
||||
title={`${t("confirm_delete_match")}${
|
||||
item.self ? "" : ` ${t("after_deleting_exclude_item")}`
|
||||
}`}
|
||||
title={`${t("confirm_delete_match")}${item.byUser ? "" : ` ${t("after_deleting_exclude_item")}`}`}
|
||||
onOk={() => {
|
||||
match.splice(match.indexOf(item), 1);
|
||||
scriptCtrl
|
||||
scriptClient
|
||||
.resetMatch(
|
||||
script.id,
|
||||
script.uuid,
|
||||
match.map((m) => m.match)
|
||||
)
|
||||
.then(() => {
|
||||
setMatch([...match]);
|
||||
// 添加到exclue
|
||||
if (!item.self) {
|
||||
if (!item.byUser) {
|
||||
exclude.push(item);
|
||||
scriptCtrl
|
||||
scriptClient
|
||||
.resetExclude(
|
||||
script.id,
|
||||
script.uuid,
|
||||
exclude.map((m) => m.match)
|
||||
)
|
||||
.then(() => {
|
||||
@ -205,13 +176,13 @@ const Match: React.FC<{
|
||||
match.push({
|
||||
id: Math.random(),
|
||||
match: matchValue,
|
||||
self: true,
|
||||
byUser: true,
|
||||
hasMatch: false,
|
||||
isExclude: false,
|
||||
});
|
||||
scriptCtrl
|
||||
scriptClient
|
||||
.resetMatch(
|
||||
script.id,
|
||||
script.uuid,
|
||||
match.map((m) => m.match)
|
||||
)
|
||||
.then(() => {
|
||||
@ -237,13 +208,13 @@ const Match: React.FC<{
|
||||
exclude.push({
|
||||
id: Math.random(),
|
||||
match: excludeValue,
|
||||
self: true,
|
||||
byUser: true,
|
||||
hasMatch: false,
|
||||
isExclude: true,
|
||||
});
|
||||
scriptCtrl
|
||||
scriptClient
|
||||
.resetExclude(
|
||||
script.id,
|
||||
script.uuid,
|
||||
exclude.map((m) => m.match)
|
||||
)
|
||||
.then(() => {
|
||||
@ -276,7 +247,7 @@ const Match: React.FC<{
|
||||
<Popconfirm
|
||||
title={t("confirm_reset")}
|
||||
onOk={() => {
|
||||
scriptCtrl.resetMatch(script.id, undefined).then(() => {
|
||||
scriptClient.resetMatch(script.uuid, undefined).then(() => {
|
||||
setMatch([]);
|
||||
});
|
||||
}}
|
||||
@ -305,7 +276,7 @@ const Match: React.FC<{
|
||||
<Popconfirm
|
||||
title={t("confirm_reset")}
|
||||
onOk={() => {
|
||||
scriptCtrl.resetExclude(script.id, undefined).then(() => {
|
||||
scriptClient.resetExclude(script.uuid, undefined).then(() => {
|
||||
setExclude([]);
|
||||
});
|
||||
}}
|
||||
|
@ -2,26 +2,14 @@ import React, { useEffect, useState } from "react";
|
||||
import { Permission } from "@App/app/repo/permission";
|
||||
import { Script } from "@App/app/repo/scripts";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
Space,
|
||||
Popconfirm,
|
||||
Message,
|
||||
Button,
|
||||
Checkbox,
|
||||
Input,
|
||||
Modal,
|
||||
Select,
|
||||
Typography,
|
||||
} from "@arco-design/web-react";
|
||||
import { Space, Popconfirm, Message, Button, Checkbox, Input, Modal, Select, Typography } from "@arco-design/web-react";
|
||||
import Table, { ColumnProps } from "@arco-design/web-react/es/Table";
|
||||
import { IconDelete } from "@arco-design/web-react/icon";
|
||||
import { permissionClient } from "@App/pages/store/features/script";
|
||||
|
||||
const PermissionManager: React.FC<{
|
||||
script: Script;
|
||||
}> = ({ script }) => {
|
||||
// const permissionCtrl = IoC.instance(
|
||||
// PermissionController
|
||||
// ) as PermissionController;
|
||||
const [permission, setPermission] = useState<Permission[]>([]);
|
||||
const [permissionVisible, setPermissionVisible] = useState<boolean>(false);
|
||||
const [permissionValue, setPermissionValue] = useState<Permission>();
|
||||
@ -59,14 +47,15 @@ const PermissionManager: React.FC<{
|
||||
<Popconfirm
|
||||
title={t("confirm_delete_permission")}
|
||||
onOk={() => {
|
||||
permissionCtrl
|
||||
.deletePermission(script!.id, {
|
||||
permission: item.permission,
|
||||
permissionValue: item.permissionValue,
|
||||
})
|
||||
permissionClient
|
||||
.deletePermission(script.uuid, item.permission, item.permissionValue)
|
||||
.then(() => {
|
||||
Message.success(t("delete_success")!);
|
||||
setPermission(permission.filter((i) => i.id !== item.id));
|
||||
setPermission(
|
||||
permission.filter(
|
||||
(i) => !(i.permission == item.permission && i.permissionValue == item.permissionValue)
|
||||
)
|
||||
);
|
||||
})
|
||||
.catch(() => {
|
||||
Message.error(t("delete_failed")!);
|
||||
@ -83,7 +72,7 @@ const PermissionManager: React.FC<{
|
||||
|
||||
useEffect(() => {
|
||||
if (script) {
|
||||
permissionCtrl.getPermissions(script.id).then((list) => {
|
||||
permissionClient.getScriptPermissions(script.uuid).then((list) => {
|
||||
setPermission(list);
|
||||
});
|
||||
}
|
||||
@ -98,20 +87,17 @@ const PermissionManager: React.FC<{
|
||||
onOk={() => {
|
||||
if (permissionValue) {
|
||||
permission.push({
|
||||
id: 0,
|
||||
uuid: script.id,
|
||||
uuid: script.uuid,
|
||||
permission: permissionValue.permission,
|
||||
permissionValue: permissionValue.permissionValue,
|
||||
allow: permissionValue.allow,
|
||||
createtime: new Date().getTime(),
|
||||
updatetime: 0,
|
||||
});
|
||||
permissionCtrl
|
||||
.addPermission(script.id, permissionValue)
|
||||
.then(() => {
|
||||
setPermission([...permission]);
|
||||
setPermissionVisible(false);
|
||||
});
|
||||
permissionClient.addPermission(permissionValue).then(() => {
|
||||
setPermission([...permission]);
|
||||
setPermissionVisible(false);
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
@ -119,27 +105,22 @@ const PermissionManager: React.FC<{
|
||||
<Select
|
||||
value={permissionValue?.permission}
|
||||
onChange={(e) => {
|
||||
permissionValue &&
|
||||
setPermissionValue({ ...permissionValue, permission: e });
|
||||
permissionValue && setPermissionValue({ ...permissionValue, permission: e });
|
||||
}}
|
||||
>
|
||||
<Select.Option value="cors">{t("permission_cors")}</Select.Option>
|
||||
<Select.Option value="cookie">
|
||||
{t("permission_cookie")}
|
||||
</Select.Option>
|
||||
<Select.Option value="cookie">{t("permission_cookie")}</Select.Option>
|
||||
</Select>
|
||||
<Input
|
||||
value={permissionValue?.permissionValue}
|
||||
onChange={(e) => {
|
||||
permissionValue &&
|
||||
setPermissionValue({ ...permissionValue, permissionValue: e });
|
||||
permissionValue && setPermissionValue({ ...permissionValue, permissionValue: e });
|
||||
}}
|
||||
/>
|
||||
<Checkbox
|
||||
checked={permissionValue?.allow}
|
||||
onChange={(e) => {
|
||||
permissionValue &&
|
||||
setPermissionValue({ ...permissionValue, allow: e });
|
||||
permissionValue && setPermissionValue({ ...permissionValue, allow: e });
|
||||
}}
|
||||
>
|
||||
{t("allow")}
|
||||
@ -147,17 +128,14 @@ const PermissionManager: React.FC<{
|
||||
</Space>
|
||||
</Modal>
|
||||
<div className="flex flex-row justify-between pb-2">
|
||||
<Typography.Title heading={6}>
|
||||
{t("permission_management")}
|
||||
</Typography.Title>
|
||||
<Typography.Title heading={6}>{t("permission_management")}</Typography.Title>
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setPermissionValue({
|
||||
id: 0,
|
||||
uuid: script.id,
|
||||
uuid: script.uuid,
|
||||
permission: "cors",
|
||||
permissionValue: "",
|
||||
allow: true,
|
||||
@ -172,7 +150,7 @@ const PermissionManager: React.FC<{
|
||||
<Popconfirm
|
||||
title={t("confirm_reset")}
|
||||
onOk={() => {
|
||||
permissionCtrl.resetPermission(script.id).then(() => {
|
||||
permissionClient.resetPermission(script.uuid).then(() => {
|
||||
setPermission([]);
|
||||
});
|
||||
}}
|
||||
@ -183,12 +161,7 @@ const PermissionManager: React.FC<{
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
</div>
|
||||
<Table
|
||||
columns={columns}
|
||||
data={permission}
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
/>
|
||||
<Table columns={columns} data={permission} rowKey="id" pagination={false} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,13 +1,6 @@
|
||||
import { Script } from "@App/app/repo/scripts";
|
||||
import { Script, ScriptDAO } from "@App/app/repo/scripts";
|
||||
import { formatUnixTime } from "@App/pkg/utils/utils";
|
||||
import {
|
||||
Descriptions,
|
||||
Divider,
|
||||
Drawer,
|
||||
Empty,
|
||||
Input,
|
||||
Message,
|
||||
} from "@arco-design/web-react";
|
||||
import { Descriptions, Divider, Drawer, Empty, Input, Message } from "@arco-design/web-react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Match from "./Match";
|
||||
@ -19,14 +12,14 @@ const ScriptSetting: React.FC<{
|
||||
onOk: () => void;
|
||||
onCancel: () => void;
|
||||
}> = ({ script, visible, onCancel, onOk }) => {
|
||||
// const scriptCtrl = IoC.instance(ScriptController) as ScriptController;
|
||||
const scriptDAO = new ScriptDAO();
|
||||
const [checkUpdateUrl, setCheckUpdateUrl] = useState<string>("");
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
if (script) {
|
||||
scriptCtrl.scriptDAO.findById(script.id).then((v) => {
|
||||
scriptDAO.get(script.uuid).then((v) => {
|
||||
setCheckUpdateUrl(v?.downloadUrl || "");
|
||||
});
|
||||
}
|
||||
@ -56,9 +49,7 @@ const ScriptSetting: React.FC<{
|
||||
data={[
|
||||
{
|
||||
label: t("last_updated"),
|
||||
value: formatUnixTime(
|
||||
(script?.updatetime || script?.createtime || 0) / 1000
|
||||
),
|
||||
value: formatUnixTime((script?.updatetime || script?.createtime || 0) / 1000),
|
||||
},
|
||||
{
|
||||
label: "UUID",
|
||||
@ -83,8 +74,8 @@ const ScriptSetting: React.FC<{
|
||||
setCheckUpdateUrl(e);
|
||||
}}
|
||||
onBlur={() => {
|
||||
scriptCtrl
|
||||
.updateCheckUpdateUrl(script!.id, checkUpdateUrl)
|
||||
scriptDAO
|
||||
.update(script.uuid, { downloadUrl: checkUpdateUrl, checkUpdateUrl: checkUpdateUrl })
|
||||
.then(() => {
|
||||
Message.success(t("update_success")!);
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Script } from "@App/app/repo/scripts";
|
||||
import { Value } from "@App/app/repo/value";
|
||||
import { valueClient } from "@App/pages/store/features/script";
|
||||
import { valueType } from "@App/pkg/utils/utils";
|
||||
import { Button, Drawer, Form, Input, Message, Modal, Popconfirm, Select, Space, Table } from "@arco-design/web-react";
|
||||
import { RefInputType } from "@arco-design/web-react/es/Input/interface";
|
||||
@ -10,16 +11,20 @@ import { useTranslation } from "react-i18next";
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
interface ValueModel {
|
||||
key: string;
|
||||
value: any;
|
||||
}
|
||||
|
||||
const ScriptStorage: React.FC<{
|
||||
// eslint-disable-next-line react/require-default-props
|
||||
script?: Script;
|
||||
visible: boolean;
|
||||
onOk: () => void;
|
||||
onCancel: () => void;
|
||||
}> = ({ script, visible, onCancel, onOk }) => {
|
||||
const [data, setData] = useState<Value[]>([]);
|
||||
const [data, setData] = useState<ValueModel[]>([]);
|
||||
const inputRef = useRef<RefInputType>(null);
|
||||
const [currentValue, setCurrentValue] = useState<Value>();
|
||||
const [currentValue, setCurrentValue] = useState<ValueModel>();
|
||||
const [visibleEdit, setVisibleEdit] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
const { t } = useTranslation();
|
||||
@ -28,31 +33,13 @@ const ScriptStorage: React.FC<{
|
||||
if (!script) {
|
||||
return () => {};
|
||||
}
|
||||
// valueCtrl.getValues(script).then((values) => {
|
||||
// setData(values);
|
||||
// });
|
||||
// Monitor value changes
|
||||
// const channel = valueCtrl.watchValue(script);
|
||||
// channel.setHandler((value: Value) => {
|
||||
// setData((prev) => {
|
||||
// const index = prev.findIndex((item) => item.key === value.key);
|
||||
// if (index === -1) {
|
||||
// if (value.value === undefined) {
|
||||
// return prev;
|
||||
// }
|
||||
// return [value, ...prev];
|
||||
// }
|
||||
// if (value.value === undefined) {
|
||||
// prev.splice(index, 1);
|
||||
// return [...prev];
|
||||
// }
|
||||
// prev[index] = value;
|
||||
// return [...prev];
|
||||
// });
|
||||
// });
|
||||
return () => {
|
||||
// channel.disChannel();
|
||||
};
|
||||
valueClient.getScriptValue(script).then((value) => {
|
||||
setData(
|
||||
Object.keys(value).map((key) => {
|
||||
return { key: key, value: value[key] };
|
||||
})
|
||||
);
|
||||
});
|
||||
}, [script]);
|
||||
const columns: ColumnProps[] = [
|
||||
{
|
||||
@ -61,7 +48,6 @@ const ScriptStorage: React.FC<{
|
||||
key: "key",
|
||||
filterIcon: <IconSearch />,
|
||||
width: 140,
|
||||
// eslint-disable-next-line react/no-unstable-nested-components
|
||||
filterDropdown: ({ filterKeys, setFilterKeys, confirm }: any) => {
|
||||
return (
|
||||
<div className="arco-table-custom-filter">
|
||||
@ -120,7 +106,7 @@ const ScriptStorage: React.FC<{
|
||||
},
|
||||
{
|
||||
title: t("action"),
|
||||
render(_col, value: Value, index) {
|
||||
render(_col, value: { key: string; value: string }, index) {
|
||||
return (
|
||||
<Space>
|
||||
<Button
|
||||
@ -136,7 +122,7 @@ const ScriptStorage: React.FC<{
|
||||
iconOnly
|
||||
icon={<IconDelete />}
|
||||
onClick={() => {
|
||||
valueCtrl.setValue(script!.id, value.key, undefined);
|
||||
valueClient.setScriptValue(script!.uuid, value.key, undefined);
|
||||
Message.info({
|
||||
content: t("delete_success"),
|
||||
});
|
||||
@ -179,7 +165,7 @@ const ScriptStorage: React.FC<{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
valueCtrl.setValue(script!.id, value.key, value.value);
|
||||
valueClient.setScriptValue(script!.uuid, value.key, value.value);
|
||||
if (currentValue) {
|
||||
Message.info({
|
||||
content: t("update_success"),
|
||||
@ -201,13 +187,8 @@ const ScriptStorage: React.FC<{
|
||||
});
|
||||
setData([
|
||||
{
|
||||
id: 0,
|
||||
scriptId: script!.id,
|
||||
storageName: (script?.metadata.storagename && script?.metadata.storagename[0]) || "",
|
||||
key: value.key,
|
||||
value: value.value,
|
||||
createtime: Date.now(),
|
||||
updatetime: 0,
|
||||
},
|
||||
...data,
|
||||
]);
|
||||
@ -254,7 +235,7 @@ const ScriptStorage: React.FC<{
|
||||
onOk={() => {
|
||||
setData((prev) => {
|
||||
prev.forEach((v) => {
|
||||
valueCtrl.setValue(script!.id, v.key, undefined);
|
||||
valueClient.setScriptValue(script!.uuid, v.key, undefined);
|
||||
});
|
||||
Message.info({
|
||||
content: t("clear_success"),
|
||||
|
@ -8,12 +8,12 @@ import "@App/index.css";
|
||||
import { Provider } from "react-redux";
|
||||
import { store } from "@App/pages/store/store.ts";
|
||||
import LoggerCore from "@App/app/logger/core.ts";
|
||||
import { LoggerDAO } from "@App/app/repo/logger.ts";
|
||||
import DBWriter from "@App/app/logger/db_writer.ts";
|
||||
import MessageWriter from "@App/app/logger/message_writer.ts";
|
||||
import { message } from "../store/global.ts";
|
||||
|
||||
// 初始化日志组件
|
||||
const loggerCore = new LoggerCore({
|
||||
writer: new DBWriter(new LoggerDAO()),
|
||||
writer: new MessageWriter(message),
|
||||
labels: { env: "confirm" },
|
||||
});
|
||||
|
||||
|
@ -8,12 +8,12 @@ import "@App/index.css";
|
||||
import { Provider } from "react-redux";
|
||||
import { store } from "@App/pages/store/store.ts";
|
||||
import LoggerCore from "@App/app/logger/core.ts";
|
||||
import { LoggerDAO } from "@App/app/repo/logger.ts";
|
||||
import DBWriter from "@App/app/logger/db_writer.ts";
|
||||
import MessageWriter from "@App/app/logger/message_writer.ts";
|
||||
import { message } from "../store/global.ts";
|
||||
|
||||
// 初始化日志组件
|
||||
const loggerCore = new LoggerCore({
|
||||
writer: new DBWriter(new LoggerDAO()),
|
||||
writer: new MessageWriter(message),
|
||||
labels: { env: "import" },
|
||||
});
|
||||
|
||||
|
@ -8,12 +8,12 @@ import "@App/index.css";
|
||||
import { Provider } from "react-redux";
|
||||
import { store } from "@App/pages/store/store.ts";
|
||||
import LoggerCore from "@App/app/logger/core.ts";
|
||||
import { LoggerDAO } from "@App/app/repo/logger.ts";
|
||||
import DBWriter from "@App/app/logger/db_writer.ts";
|
||||
import MessageWriter from "@App/app/logger/message_writer.ts";
|
||||
import { message } from "../store/global.ts";
|
||||
|
||||
// 初始化日志组件
|
||||
const loggerCore = new LoggerCore({
|
||||
writer: new DBWriter(new LoggerDAO()),
|
||||
writer: new MessageWriter(message),
|
||||
labels: { env: "install" },
|
||||
});
|
||||
|
||||
|
@ -13,8 +13,12 @@ import { LoggerDAO } from "@App/app/repo/logger.ts";
|
||||
import DBWriter from "@App/app/logger/db_writer.ts";
|
||||
import registerEditor from "@App/pkg/utils/monaco-editor.ts";
|
||||
import storeSubscribe from "../store/subscribe.ts";
|
||||
import migrate from "@App/app/migrate.ts";
|
||||
|
||||
migrate();
|
||||
|
||||
registerEditor();
|
||||
|
||||
// 初始化日志组件
|
||||
const loggerCore = new LoggerCore({
|
||||
writer: new DBWriter(new LoggerDAO()),
|
||||
|
@ -32,11 +32,12 @@ type HotKey = {
|
||||
|
||||
const Editor: React.FC<{
|
||||
id: string;
|
||||
script: ScriptAndCode;
|
||||
script: Script;
|
||||
code: string;
|
||||
hotKeys: HotKey[];
|
||||
callbackEditor: (e: editor.IStandaloneCodeEditor) => void;
|
||||
onChange: (code: string) => void;
|
||||
}> = ({ id, script, hotKeys, callbackEditor, onChange }) => {
|
||||
}> = ({ id, script, code, hotKeys, callbackEditor, onChange }) => {
|
||||
const [node, setNode] = useState<{ editor: editor.IStandaloneCodeEditor }>();
|
||||
const ref = useCallback<(node: { editor: editor.IStandaloneCodeEditor }) => void>(
|
||||
(inlineNode) => {
|
||||
@ -77,7 +78,7 @@ const Editor: React.FC<{
|
||||
};
|
||||
}, [node?.editor]);
|
||||
|
||||
return <CodeEditor key={id} id={id} ref={ref} code={script.code} diffCode="" editable />;
|
||||
return <CodeEditor key={id} id={id} ref={ref} code={code} diffCode="" editable />;
|
||||
};
|
||||
|
||||
const WarpEditor = React.memo(Editor, (prev, next) => {
|
||||
@ -154,7 +155,8 @@ function ScriptEditor() {
|
||||
const [visible, setVisible] = useState<{ [key: string]: boolean }>({});
|
||||
const [editors, setEditors] = useState<
|
||||
{
|
||||
script: ScriptAndCode;
|
||||
script: Script;
|
||||
code: string;
|
||||
active: boolean;
|
||||
hotKeys: HotKey[];
|
||||
editor?: editor.IStandaloneCodeEditor;
|
||||
@ -218,7 +220,7 @@ function ScriptEditor() {
|
||||
setEditors((prev) => {
|
||||
for (let i = 0; i < prev.length; i += 1) {
|
||||
if (prev[i].script.uuid === newScript.uuid) {
|
||||
prev[i].script.code = prepareScript.scriptCode;
|
||||
prev[i].code = e.getValue();
|
||||
prev[i].isChanged = false;
|
||||
prev[i].script.name = newScript.name;
|
||||
break;
|
||||
@ -310,7 +312,7 @@ function ScriptEditor() {
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
LoggerCore.getLogger(Logger.E(err)).debug("debug script error");
|
||||
LoggerCore.logger(Logger.E(err)).debug("debug script error");
|
||||
Message.error({
|
||||
id: "debug_script",
|
||||
content: `构建失败: ${err}`,
|
||||
@ -398,7 +400,8 @@ function ScriptEditor() {
|
||||
});
|
||||
}
|
||||
prev.push({
|
||||
script: Object.assign(scripts[i], code),
|
||||
script: scripts[i],
|
||||
code: code?.code || "",
|
||||
active: true,
|
||||
hotKeys,
|
||||
isChanged: false,
|
||||
@ -725,7 +728,8 @@ function ScriptEditor() {
|
||||
return;
|
||||
}
|
||||
editors.push({
|
||||
script: Object.assign(script, code),
|
||||
script,
|
||||
code: code.code,
|
||||
active: true,
|
||||
hotKeys,
|
||||
isChanged: false,
|
||||
@ -874,6 +878,7 @@ function ScriptEditor() {
|
||||
key={`e_${item.script.uuid}`}
|
||||
id={`e_${item.script.uuid}`}
|
||||
script={item.script}
|
||||
code={item.code}
|
||||
hotKeys={item.hotKeys}
|
||||
callbackEditor={(e) => {
|
||||
setEditors((prev) => {
|
||||
@ -886,7 +891,7 @@ function ScriptEditor() {
|
||||
});
|
||||
}}
|
||||
onChange={(code) => {
|
||||
const isChanged = !(item.script.code === code);
|
||||
const isChanged = !(item.code === code);
|
||||
if (isChanged !== item.isChanged) {
|
||||
setEditors((prev) => {
|
||||
prev.forEach((v) => {
|
||||
|
@ -2,18 +2,18 @@ import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import App from "./App.tsx";
|
||||
import LoggerCore from "@App/app/logger/core.ts";
|
||||
import { LoggerDAO } from "@App/app/repo/logger.ts";
|
||||
import DBWriter from "@App/app/logger/db_writer.ts";
|
||||
import "@arco-design/web-react/dist/css/arco.css";
|
||||
import "@App/locales/locales";
|
||||
import "@App/index.css";
|
||||
import "./index.css";
|
||||
import { Provider } from "react-redux";
|
||||
import { store } from "../store/store.ts";
|
||||
import MessageWriter from "@App/app/logger/message_writer.ts";
|
||||
import { message } from "../store/global.ts";
|
||||
|
||||
// 初始化日志组件
|
||||
const loggerCore = new LoggerCore({
|
||||
writer: new DBWriter(new LoggerDAO()),
|
||||
writer: new MessageWriter(message),
|
||||
labels: { env: "install" },
|
||||
});
|
||||
|
||||
|
@ -48,14 +48,14 @@ async function setupOffscreenDocument() {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// 初始化管理器
|
||||
const message = new ExtensionMessage(true);
|
||||
// 初始化日志组件
|
||||
const loggerCore = new LoggerCore({
|
||||
writer: new DBWriter(new LoggerDAO()),
|
||||
labels: { env: "service_worker" },
|
||||
});
|
||||
loggerCore.logger().debug("service worker start");
|
||||
// 初始化管理器
|
||||
const message = new ExtensionMessage(true);
|
||||
const server = new Server("serviceWorker", message);
|
||||
const messageQueue = new MessageQueue();
|
||||
const manager = new ServiceWorkerManager(server, messageQueue, new ServiceWorkerMessageSend());
|
||||
|
@ -139,21 +139,6 @@ declare function GM_cookie(
|
||||
ondone: (cookie: GMTypes.Cookie[], error: unknown | undefined) => void
|
||||
): void;
|
||||
|
||||
/**
|
||||
* 可以通过GM_addValueChangeListener获取tabid
|
||||
* 再通过tabid(前后端通信可能用到,ValueChangeListener会返回tabid),获取storeid,后台脚本用.
|
||||
* 请注意这是一个实验性质的API,后续可能会改变
|
||||
* @param tabid 页面的tabid
|
||||
* @param ondone 完成事件
|
||||
* @param callback.storeid 该页面的storeid,可以给GM_cookie使用
|
||||
* @param callback.error 错误信息
|
||||
* @deprecated 已废弃,请使用GM_cookie("store", tabid)替代
|
||||
*/
|
||||
declare function GM_getCookieStore(
|
||||
tabid: number,
|
||||
ondone: (storeId: number | undefined, error: unknown | undefined) => void
|
||||
): void;
|
||||
|
||||
/**
|
||||
* 设置浏览器代理
|
||||
* @deprecated 正式版中已废弃,后续可能会在beta版本中添加
|
||||
@ -289,10 +274,7 @@ declare namespace CATType {
|
||||
}
|
||||
|
||||
declare namespace GMTypes {
|
||||
/*
|
||||
* store为获取隐身窗口之类的cookie,这是一个实验性质的API,后续可能会改变
|
||||
*/
|
||||
type CookieAction = "list" | "delete" | "set" | "store";
|
||||
type CookieAction = "list" | "delete" | "set";
|
||||
|
||||
type LoggerLevel = "debug" | "info" | "warn" | "error";
|
||||
|
||||
@ -308,17 +290,13 @@ declare namespace GMTypes {
|
||||
path?: string;
|
||||
secure?: boolean;
|
||||
session?: boolean;
|
||||
storeId?: string;
|
||||
httpOnly?: boolean;
|
||||
expirationDate?: number;
|
||||
// store用
|
||||
tabId?: number;
|
||||
}
|
||||
|
||||
interface Cookie {
|
||||
domain: string;
|
||||
name: string;
|
||||
storeId: string;
|
||||
value: string;
|
||||
session: boolean;
|
||||
hostOnly: boolean;
|
||||
@ -341,7 +319,7 @@ declare namespace GMTypes {
|
||||
active?: boolean;
|
||||
insert?: boolean;
|
||||
setParent?: boolean;
|
||||
useOpen?: boolean; // 这是一个实验性/不兼容其他管理器/不兼容Firefox的功能
|
||||
useOpen?: boolean; // 这是一个实验性/不兼容其他管理器/不兼容Firefox的功能 表示使用window.open打开新窗口 #178
|
||||
}
|
||||
|
||||
interface XHRResponse {
|
||||
@ -384,7 +362,7 @@ declare namespace GMTypes {
|
||||
user?: string;
|
||||
password?: string;
|
||||
nocache?: boolean;
|
||||
maxRedirects?: number;
|
||||
redirect?: "follow" | "error" | "manual";// 为了与tm保持一致, 在v0.17.0后废弃maxRedirects, 使用redirect替代, 会强制使用fetch模式
|
||||
|
||||
onload?: Listener<XHRResponse>;
|
||||
onloadstart?: Listener<XHRResponse>;
|
||||
|
1
src/types/main.d.ts
vendored
1
src/types/main.d.ts
vendored
@ -31,7 +31,6 @@ declare namespace GMSend {
|
||||
nocache?: boolean;
|
||||
dataType?: "FormData" | "Blob";
|
||||
redirect?: "follow" | "error" | "manual";
|
||||
maxRedirects?: number; // 为了与tm保持一致, 在v0.17.0后废弃, 使用redirect替代
|
||||
}
|
||||
|
||||
interface XHRFormData {
|
||||
|
2
src/types/scriptcat.d.ts
vendored
2
src/types/scriptcat.d.ts
vendored
@ -362,7 +362,7 @@ declare namespace GMTypes {
|
||||
user?: string;
|
||||
password?: string;
|
||||
nocache?: boolean;
|
||||
maxRedirects?: number;
|
||||
redirect?: "follow" | "error" | "manual";// 为了与tm保持一致, 在v0.17.0后废弃maxRedirects, 使用redirect替代, 会强制使用fetch模式
|
||||
|
||||
onload?: Listener<XHRResponse>;
|
||||
onloadstart?: Listener<XHRResponse>;
|
||||
|
Loading…
x
Reference in New Issue
Block a user