popup细节
Some checks failed
test / Run tests (push) Failing after 3s
build / Build (push) Failing after 5s
Some checks failed
test / Run tests (push) Failing after 3s
build / Build (push) Failing after 5s
This commit is contained in:
@ -9,8 +9,20 @@
|
|||||||
// @grant GM_unregisterMenuCommand
|
// @grant GM_unregisterMenuCommand
|
||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
|
|
||||||
|
const id = GM_registerMenuCommand(
|
||||||
const id = GM_registerMenuCommand("测试菜单", () => {
|
"测试菜单",
|
||||||
|
() => {
|
||||||
console.log(id);
|
console.log(id);
|
||||||
GM_unregisterMenuCommand(id);
|
GM_unregisterMenuCommand(id);
|
||||||
}, "h");
|
},
|
||||||
|
"h"
|
||||||
|
);
|
||||||
|
|
||||||
|
const id2 = GM_registerMenuCommand(
|
||||||
|
"测试菜单2",
|
||||||
|
() => {
|
||||||
|
console.log(id2);
|
||||||
|
GM_unregisterMenuCommand(id2);
|
||||||
|
},
|
||||||
|
"j"
|
||||||
|
);
|
||||||
|
@ -143,11 +143,9 @@ export default class Cache {
|
|||||||
if (promise) {
|
if (promise) {
|
||||||
await promise;
|
await promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
promise = this.get(key)
|
promise = this.get(key)
|
||||||
.then((result) => set(result))
|
.then((result) => set(result))
|
||||||
.then((value) => {
|
.then((value) => {
|
||||||
console.log("tx", key, value);
|
|
||||||
if (value) {
|
if (value) {
|
||||||
return this.set(key, value);
|
return this.set(key, value);
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,10 @@ export class ScriptClient extends Client {
|
|||||||
getScriptRunResource(script: Script): Promise<ScriptRunResouce> {
|
getScriptRunResource(script: Script): Promise<ScriptRunResouce> {
|
||||||
return this.do("getScriptRunResource", script);
|
return this.do("getScriptRunResource", script);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
excludeUrl(uuid: string, url: string, remove: boolean) {
|
||||||
|
return this.do("excludeUrl", { uuid, url, remove });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ResourceClient extends Client {
|
export class ResourceClient extends Client {
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
Script,
|
Script,
|
||||||
ScriptDAO,
|
ScriptDAO,
|
||||||
SCRIPT_TYPE_NORMAL,
|
SCRIPT_TYPE_NORMAL,
|
||||||
|
SCRIPT_RUN_STATUS_RUNNING,
|
||||||
} from "@App/app/repo/scripts";
|
} from "@App/app/repo/scripts";
|
||||||
import {
|
import {
|
||||||
ScriptMenuRegisterCallbackValue,
|
ScriptMenuRegisterCallbackValue,
|
||||||
@ -54,9 +55,11 @@ export class PopupService {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
genScriptMenuByTabMap(menu: ScriptMenu[]) {
|
genScriptMenuByTabMap(menu: ScriptMenu[]) {
|
||||||
|
let n = 0;
|
||||||
menu.forEach((script) => {
|
menu.forEach((script) => {
|
||||||
// 创建脚本菜单
|
// 创建脚本菜单
|
||||||
if (script.menus.length) {
|
if (script.menus.length) {
|
||||||
|
n += script.menus.length;
|
||||||
chrome.contextMenus.create({
|
chrome.contextMenus.create({
|
||||||
id: `scriptMenu_` + script.uuid,
|
id: `scriptMenu_` + script.uuid,
|
||||||
title: script.name,
|
title: script.name,
|
||||||
@ -65,7 +68,6 @@ export class PopupService {
|
|||||||
});
|
});
|
||||||
script.menus.forEach((menu) => {
|
script.menus.forEach((menu) => {
|
||||||
// 创建菜单
|
// 创建菜单
|
||||||
console.log("create menu", menu);
|
|
||||||
chrome.contextMenus.create({
|
chrome.contextMenus.create({
|
||||||
id: `scriptMenu_menu_${script.uuid}_${menu.id}`,
|
id: `scriptMenu_menu_${script.uuid}_${menu.id}`,
|
||||||
title: menu.name,
|
title: menu.name,
|
||||||
@ -75,6 +77,7 @@ export class PopupService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成chrome菜单
|
// 生成chrome菜单
|
||||||
@ -86,6 +89,7 @@ export class PopupService {
|
|||||||
if (!menu.length && !backgroundMenu.length) {
|
if (!menu.length && !backgroundMenu.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let n = 0;
|
||||||
// 创建根菜单
|
// 创建根菜单
|
||||||
chrome.contextMenus.create({
|
chrome.contextMenus.create({
|
||||||
id: "scriptMenu",
|
id: "scriptMenu",
|
||||||
@ -93,18 +97,21 @@ export class PopupService {
|
|||||||
contexts: ["all"],
|
contexts: ["all"],
|
||||||
});
|
});
|
||||||
if (menu) {
|
if (menu) {
|
||||||
this.genScriptMenuByTabMap(menu);
|
n += this.genScriptMenuByTabMap(menu);
|
||||||
}
|
}
|
||||||
// 后台脚本的菜单
|
// 后台脚本的菜单
|
||||||
if (backgroundMenu) {
|
if (backgroundMenu) {
|
||||||
this.genScriptMenuByTabMap(backgroundMenu);
|
n += this.genScriptMenuByTabMap(backgroundMenu);
|
||||||
|
}
|
||||||
|
if (n === 0) {
|
||||||
|
// 如果没有菜单,删除菜单
|
||||||
|
chrome.contextMenus.remove("scriptMenu");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async registerMenuCommand(message: ScriptMenuRegisterCallbackValue) {
|
async registerMenuCommand(message: ScriptMenuRegisterCallbackValue) {
|
||||||
// 给脚本添加菜单
|
// 给脚本添加菜单
|
||||||
return this.txUpdateScriptMenu(message.tabId, async (data) => {
|
return this.txUpdateScriptMenu(message.tabId, async (data) => {
|
||||||
console.log("register menu", message, data);
|
|
||||||
const script = data.find((item) => item.uuid === message.uuid);
|
const script = data.find((item) => item.uuid === message.uuid);
|
||||||
if (script) {
|
if (script) {
|
||||||
const menu = script.menus.find((item) => item.id === message.id);
|
const menu = script.menus.find((item) => item.id === message.id);
|
||||||
@ -165,7 +172,7 @@ export class PopupService {
|
|||||||
hasUserConfig: !!script.config,
|
hasUserConfig: !!script.config,
|
||||||
metadata: script.metadata,
|
metadata: script.metadata,
|
||||||
runStatus: script.runStatus,
|
runStatus: script.runStatus,
|
||||||
runNum: 0,
|
runNum: script.type === SCRIPT_TYPE_NORMAL ? 0 : script.runStatus === SCRIPT_RUN_STATUS_RUNNING ? 1 : 0,
|
||||||
runNumByIframe: 0,
|
runNumByIframe: 0,
|
||||||
menus: [],
|
menus: [],
|
||||||
customExclude: (script as ScriptMatchInfo).customizeExcludeMatches || [],
|
customExclude: (script as ScriptMatchInfo).customizeExcludeMatches || [],
|
||||||
@ -175,21 +182,21 @@ export class PopupService {
|
|||||||
// 获取popup页面数据
|
// 获取popup页面数据
|
||||||
async getPopupData(req: GetPopupDataReq): Promise<GetPopupDataRes> {
|
async getPopupData(req: GetPopupDataReq): Promise<GetPopupDataRes> {
|
||||||
// 获取当前tabId
|
// 获取当前tabId
|
||||||
const scriptUuid = await this.runtime.getPageScriptByUrl(req.url);
|
const script = await this.runtime.getPageScriptByUrl(req.url, true);
|
||||||
// 与运行时脚本进行合并
|
// 与运行时脚本进行合并
|
||||||
const runScript = await this.getScriptMenu(req.tabId);
|
const runScript = await this.getScriptMenu(req.tabId);
|
||||||
// 筛选出未运行的脚本
|
// 合并数据
|
||||||
const notRunScript = scriptUuid.filter((script) => {
|
const scriptMenu = script.map((script) => {
|
||||||
return !runScript.find((item) => item.uuid === script.uuid);
|
const run = runScript.find((item) => item.uuid === script.uuid);
|
||||||
});
|
if (run) {
|
||||||
// 将未运行的脚本转换为菜单
|
// 如果脚本已经存在,则不添加,赋值状态
|
||||||
const scriptList = notRunScript.map((script): ScriptMenu => {
|
run.enable = script.status === SCRIPT_STATUS_ENABLE;
|
||||||
|
return run;
|
||||||
|
}
|
||||||
return this.scriptToMenu(script);
|
return this.scriptToMenu(script);
|
||||||
});
|
});
|
||||||
runScript.push(...scriptList);
|
|
||||||
// 后台脚本只显示开启或者运行中的脚本
|
// 后台脚本只显示开启或者运行中的脚本
|
||||||
|
return { scriptList: scriptMenu, backScriptList: await this.getScriptMenu(-1) };
|
||||||
return { scriptList: runScript, backScriptList: await this.getScriptMenu(-1) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getScriptMenu(tabId: number) {
|
async getScriptMenu(tabId: number) {
|
||||||
@ -263,17 +270,17 @@ export class PopupService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return this.txUpdateScriptMenu(-1, async (menu) => {
|
return this.txUpdateScriptMenu(-1, async (menu) => {
|
||||||
const scriptMenu = menu.find((item) => item.uuid === uuid);
|
const index = menu.findIndex((item) => item.uuid === uuid);
|
||||||
if (script.status === SCRIPT_STATUS_ENABLE) {
|
if (script.status === SCRIPT_STATUS_ENABLE) {
|
||||||
// 加入菜单
|
// 加入菜单
|
||||||
if (!scriptMenu) {
|
if (index === -1) {
|
||||||
const item = this.scriptToMenu(script);
|
const item = this.scriptToMenu(script);
|
||||||
menu.push(item);
|
menu.push(item);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 移出菜单
|
// 移出菜单
|
||||||
if (scriptMenu) {
|
if (index !== -1) {
|
||||||
menu.splice(menu.indexOf(scriptMenu), 1);
|
menu.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return menu;
|
return menu;
|
||||||
@ -281,9 +288,9 @@ export class PopupService {
|
|||||||
});
|
});
|
||||||
subscribeScriptDelete(this.mq, async ({ uuid }) => {
|
subscribeScriptDelete(this.mq, async ({ uuid }) => {
|
||||||
return this.txUpdateScriptMenu(-1, async (menu) => {
|
return this.txUpdateScriptMenu(-1, async (menu) => {
|
||||||
const scriptMenu = menu.find((item) => item.uuid === uuid);
|
const index = menu.findIndex((item) => item.uuid === uuid);
|
||||||
if (scriptMenu) {
|
if (index !== -1) {
|
||||||
menu.splice(menu.indexOf(scriptMenu), 1);
|
menu.splice(index, 1);
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -293,6 +300,7 @@ export class PopupService {
|
|||||||
return this.txUpdateScriptMenu(-1, async (menu) => {
|
return this.txUpdateScriptMenu(-1, async (menu) => {
|
||||||
const scriptMenu = menu.find((item) => item.uuid === uuid);
|
const scriptMenu = menu.find((item) => item.uuid === uuid);
|
||||||
if (scriptMenu) {
|
if (scriptMenu) {
|
||||||
|
scriptMenu.runNum = 1;
|
||||||
scriptMenu.runStatus = runStatus;
|
scriptMenu.runStatus = runStatus;
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ export class RuntimeService {
|
|||||||
// 加载页面脚本
|
// 加载页面脚本
|
||||||
await this.loadPageScript(script);
|
await this.loadPageScript(script);
|
||||||
if (!data.enable) {
|
if (!data.enable) {
|
||||||
await this.unregistryPageScript(script);
|
await this.unregistryPageScript(script.uuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -82,15 +82,9 @@ export class RuntimeService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 监听脚本删除
|
// 监听脚本删除
|
||||||
subscribeScriptDelete(this.mq, async (data) => {
|
subscribeScriptDelete(this.mq, async ({ uuid }) => {
|
||||||
const script = await this.scriptDAO.get(data.uuid);
|
await this.unregistryPageScript(uuid);
|
||||||
if (!script) {
|
this.deleteScriptMatch(uuid);
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (script.type === SCRIPT_TYPE_NORMAL) {
|
|
||||||
await this.unregistryPageScript(script);
|
|
||||||
this.deleteScriptMatch(script.uuid);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 将开启的脚本发送一次enable消息
|
// 将开启的脚本发送一次enable消息
|
||||||
@ -138,24 +132,29 @@ export class RuntimeService {
|
|||||||
return sendMessage(new ExtensionContentMessageSend(tabId, options), "content/runtime/" + action, data);
|
return sendMessage(new ExtensionContentMessageSend(tabId, options), "content/runtime/" + action, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPageScriptUuidByUrl(url: string) {
|
async getPageScriptUuidByUrl(url: string, includeCustomize?: boolean) {
|
||||||
const match = await this.loadScriptMatchInfo();
|
const match = await this.loadScriptMatchInfo();
|
||||||
// 匹配当前页面的脚本
|
// 匹配当前页面的脚本
|
||||||
const matchScriptUuid = match.match(url!);
|
const matchScriptUuid = match.match(url!);
|
||||||
// 排除自定义匹配
|
// 包含自定义排除的脚本
|
||||||
const excludeScriptUuid = this.scriptCustomizeMatch.match(url!);
|
if (includeCustomize) {
|
||||||
const excludeMatch = new Set<string>();
|
const excludeScriptUuid = this.scriptCustomizeMatch.match(url!);
|
||||||
excludeScriptUuid.forEach((uuid) => {
|
const match = new Set<string>();
|
||||||
excludeMatch.add(uuid);
|
excludeScriptUuid.forEach((uuid) => {
|
||||||
});
|
match.add(uuid);
|
||||||
return matchScriptUuid.filter((value) => {
|
});
|
||||||
// 过滤掉自定义排除的脚本
|
matchScriptUuid.forEach((uuid) => {
|
||||||
return !excludeMatch.has(value);
|
match.add(uuid);
|
||||||
});
|
});
|
||||||
|
// 转化为数组
|
||||||
|
console.log("matchScriptUuid", matchScriptUuid);
|
||||||
|
return Array.from(match);
|
||||||
|
}
|
||||||
|
return matchScriptUuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPageScriptByUrl(url: string) {
|
async getPageScriptByUrl(url: string, includeCustomize?: boolean) {
|
||||||
const matchScriptUuid = await this.getPageScriptUuidByUrl(url);
|
const matchScriptUuid = await this.getPageScriptUuidByUrl(url, includeCustomize);
|
||||||
return matchScriptUuid.map((uuid) => {
|
return matchScriptUuid.map((uuid) => {
|
||||||
return Object.assign({}, this.scriptMatchCache?.get(uuid));
|
return Object.assign({}, this.scriptMatchCache?.get(uuid));
|
||||||
});
|
});
|
||||||
@ -266,15 +265,7 @@ export class RuntimeService {
|
|||||||
Object.keys(data).forEach((key) => {
|
Object.keys(data).forEach((key) => {
|
||||||
const item = data[key];
|
const item = data[key];
|
||||||
cache.set(item.uuid, item);
|
cache.set(item.uuid, item);
|
||||||
item.matches.forEach((match) => {
|
this.syncAddScriptMatch(item);
|
||||||
this.scriptMatch.add(match, item.uuid);
|
|
||||||
});
|
|
||||||
item.excludeMatches.forEach((match) => {
|
|
||||||
this.scriptMatch.exclude(match, item.uuid);
|
|
||||||
});
|
|
||||||
item.customizeExcludeMatches.forEach((match) => {
|
|
||||||
this.scriptCustomizeMatch.exclude(match, item.uuid);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -305,6 +296,11 @@ export class RuntimeService {
|
|||||||
await this.loadScriptMatchInfo();
|
await this.loadScriptMatchInfo();
|
||||||
}
|
}
|
||||||
this.scriptMatchCache!.set(item.uuid, item);
|
this.scriptMatchCache!.set(item.uuid, item);
|
||||||
|
this.syncAddScriptMatch(item);
|
||||||
|
this.saveScriptMatchInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
syncAddScriptMatch(item: ScriptMatchInfo) {
|
||||||
// 清理一下老数据
|
// 清理一下老数据
|
||||||
this.scriptMatch.del(item.uuid);
|
this.scriptMatch.del(item.uuid);
|
||||||
this.scriptCustomizeMatch.del(item.uuid);
|
this.scriptCustomizeMatch.del(item.uuid);
|
||||||
@ -316,9 +312,8 @@ export class RuntimeService {
|
|||||||
this.scriptMatch.exclude(match, item.uuid);
|
this.scriptMatch.exclude(match, item.uuid);
|
||||||
});
|
});
|
||||||
item.customizeExcludeMatches.forEach((match) => {
|
item.customizeExcludeMatches.forEach((match) => {
|
||||||
this.scriptCustomizeMatch.exclude(match, item.uuid);
|
this.scriptCustomizeMatch.add(match, item.uuid);
|
||||||
});
|
});
|
||||||
this.saveScriptMatchInfo();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateScriptStatus(uuid: string, status: SCRIPT_STATUS) {
|
async updateScriptStatus(uuid: string, status: SCRIPT_STATUS) {
|
||||||
@ -329,11 +324,11 @@ export class RuntimeService {
|
|||||||
this.saveScriptMatchInfo();
|
this.saveScriptMatchInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteScriptMatch(uuid: string) {
|
async deleteScriptMatch(uuid: string) {
|
||||||
if (!this.scriptMatchCache) {
|
if (!this.scriptMatchCache) {
|
||||||
return;
|
await this.loadScriptMatchInfo();
|
||||||
}
|
}
|
||||||
this.scriptMatchCache.delete(uuid);
|
this.scriptMatchCache!.delete(uuid);
|
||||||
this.scriptMatch.del(uuid);
|
this.scriptMatch.del(uuid);
|
||||||
this.scriptCustomizeMatch.del(uuid);
|
this.scriptCustomizeMatch.del(uuid);
|
||||||
this.saveScriptMatchInfo();
|
this.saveScriptMatchInfo();
|
||||||
@ -394,24 +389,28 @@ export class RuntimeService {
|
|||||||
if (script.metadata["run-at"]) {
|
if (script.metadata["run-at"]) {
|
||||||
registerScript.runAt = getRunAt(script.metadata["run-at"]);
|
registerScript.runAt = getRunAt(script.metadata["run-at"]);
|
||||||
}
|
}
|
||||||
await chrome.userScripts.register([registerScript]);
|
if (await Cache.getInstance().get("registryScript:" + script.uuid)) {
|
||||||
|
await chrome.userScripts.update([registerScript]);
|
||||||
|
} else {
|
||||||
|
await chrome.userScripts.register([registerScript]);
|
||||||
|
}
|
||||||
await Cache.getInstance().set("registryScript:" + script.uuid, true);
|
await Cache.getInstance().set("registryScript:" + script.uuid, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async unregistryPageScript(script: Script) {
|
async unregistryPageScript(uuid: string) {
|
||||||
if (!(await Cache.getInstance().get("registryScript:" + script.uuid))) {
|
if (!(await Cache.getInstance().get("registryScript:" + uuid))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
chrome.userScripts.unregister(
|
chrome.userScripts.unregister(
|
||||||
{
|
{
|
||||||
ids: [script.uuid],
|
ids: [uuid],
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
// 删除缓存
|
// 删除缓存
|
||||||
Cache.getInstance().del("registryScript:" + script.uuid);
|
Cache.getInstance().del("registryScript:" + uuid);
|
||||||
// 修改脚本状态为disable
|
// 修改脚本状态为disable
|
||||||
this.updateScriptStatus(script.uuid, SCRIPT_STATUS_DISABLE);
|
this.updateScriptStatus(uuid, SCRIPT_STATUS_DISABLE);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ export class ScriptService {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info("delete success");
|
logger.info("delete success");
|
||||||
this.mq.publish("deleteScript", { uuid });
|
this.mq.publish("deleteScript", { uuid });
|
||||||
return {};
|
return true;
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
logger.error("delete error", Logger.E(e));
|
logger.error("delete error", Logger.E(e));
|
||||||
@ -279,6 +279,32 @@ export class ScriptService {
|
|||||||
return Promise.resolve(ret);
|
return Promise.resolve(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async excludeUrl({ uuid, url, remove }: { uuid: string; url: string; remove: boolean }) {
|
||||||
|
const script = await this.scriptDAO.get(uuid);
|
||||||
|
if (!script) {
|
||||||
|
throw new Error("script not found");
|
||||||
|
}
|
||||||
|
script.selfMetadata = script.selfMetadata || {};
|
||||||
|
let excludes = script.selfMetadata.exclude || script.metadata.exclude || [];
|
||||||
|
if (remove) {
|
||||||
|
excludes = excludes.filter((item) => item !== url);
|
||||||
|
} else {
|
||||||
|
excludes.push(url);
|
||||||
|
}
|
||||||
|
script.selfMetadata.exclude = excludes;
|
||||||
|
return this.scriptDAO
|
||||||
|
.update(uuid, script)
|
||||||
|
.then(() => {
|
||||||
|
// 广播一下
|
||||||
|
this.mq.publish("installScript", { script, update: true });
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
this.logger.error("exclude url error", Logger.E(e));
|
||||||
|
throw e;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.listenerScriptInstall();
|
this.listenerScriptInstall();
|
||||||
|
|
||||||
@ -290,5 +316,6 @@ export class ScriptService {
|
|||||||
this.group.on("updateRunStatus", this.updateRunStatus.bind(this));
|
this.group.on("updateRunStatus", this.updateRunStatus.bind(this));
|
||||||
this.group.on("getCode", this.getCode.bind(this));
|
this.group.on("getCode", this.getCode.bind(this));
|
||||||
this.group.on("getScriptRunResource", this.buildScriptRunResource.bind(this));
|
this.group.on("getScriptRunResource", this.buildScriptRunResource.bind(this));
|
||||||
|
this.group.on("excludeUrl", this.excludeUrl.bind(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,13 +46,13 @@ dayjs.extend(relativeTime);
|
|||||||
|
|
||||||
export function i18nName(script: { name: string; metadata: Metadata }) {
|
export function i18nName(script: { name: string; metadata: Metadata }) {
|
||||||
return script.metadata[`name:${i18n.language.toLowerCase()}`]
|
return script.metadata[`name:${i18n.language.toLowerCase()}`]
|
||||||
? script.metadata[`name:${i18n.language.toLowerCase()}`][0]
|
? script.metadata[`name:${i18n.language.toLowerCase()}`]![0]
|
||||||
: script.name;
|
: script.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function i18nDescription(script: { metadata: Metadata }) {
|
export function i18nDescription(script: { metadata: Metadata }) {
|
||||||
return script.metadata[`description:${i18n.language.toLowerCase()}`]
|
return script.metadata[`description:${i18n.language.toLowerCase()}`]
|
||||||
? script.metadata[`description:${i18n.language.toLowerCase()}`][0]
|
? script.metadata[`description:${i18n.language.toLowerCase()}`]![0]
|
||||||
: script.metadata.description;
|
: script.metadata.description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
"webRequest",
|
"webRequest",
|
||||||
"userScripts",
|
"userScripts",
|
||||||
"contextMenus",
|
"contextMenus",
|
||||||
|
"unlimitedStorage",
|
||||||
"declarativeNetRequest"
|
"declarativeNetRequest"
|
||||||
],
|
],
|
||||||
"host_permissions": [
|
"host_permissions": [
|
||||||
|
@ -14,10 +14,12 @@ import { RiPlayFill, RiStopFill } from "react-icons/ri";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { ScriptIcons } from "@App/pages/options/routes/utils";
|
import { ScriptIcons } from "@App/pages/options/routes/utils";
|
||||||
import { ScriptMenu, ScriptMenuItem } from "@App/app/service/service_worker/popup";
|
import { ScriptMenu, ScriptMenuItem } from "@App/app/service/service_worker/popup";
|
||||||
import { MessageSender } from "@Packages/message/server";
|
|
||||||
import { selectMenuExpandNum } from "@App/pages/store/features/setting";
|
import { selectMenuExpandNum } from "@App/pages/store/features/setting";
|
||||||
import { useAppSelector } from "@App/pages/store/hooks";
|
import { useAppSelector } from "@App/pages/store/hooks";
|
||||||
import { popupClient } from "@App/pages/store/features/script";
|
import { popupClient, runtimeClient, scriptClient } from "@App/pages/store/features/script";
|
||||||
|
import { i18nName } from "@App/locales/locales";
|
||||||
|
import { subscribeScriptRunStatus } from "@App/app/service/queue";
|
||||||
|
import { messageQueue } from "@App/pages/store/global";
|
||||||
|
|
||||||
const CollapseItem = Collapse.Item;
|
const CollapseItem = Collapse.Item;
|
||||||
|
|
||||||
@ -26,7 +28,7 @@ function isExclude(script: ScriptMenu, host: string) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < script.customExclude.length; i += 1) {
|
for (let i = 0; i < script.customExclude.length; i += 1) {
|
||||||
if (script.customExclude[i] === `*://${host}*`) {
|
if (script.customExclude[i] === `*://${host}/*`) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,32 +58,28 @@ const ScriptMenuList: React.FC<{
|
|||||||
setList(script);
|
setList(script);
|
||||||
}, [script]);
|
}, [script]);
|
||||||
|
|
||||||
// useEffect(() => {
|
useEffect(() => {
|
||||||
// // 监听脚本运行状态
|
// 监听脚本运行状态
|
||||||
// const channel = runtimeCtrl.watchRunStatus();
|
const unsub = subscribeScriptRunStatus(messageQueue, ({ uuid, runStatus }) => {
|
||||||
// channel.setHandler(([id, status]: any) => {
|
setList((prev) => {
|
||||||
// setList((prev) => {
|
const newList = [...prev];
|
||||||
// const newList = [...prev];
|
const index = newList.findIndex((item) => item.uuid === uuid);
|
||||||
// const index = newList.findIndex((item) => item.id === id);
|
if (index !== -1) {
|
||||||
// if (index !== -1) {
|
newList[index].runStatus = runStatus;
|
||||||
// newList[index].runStatus = status;
|
}
|
||||||
// }
|
return newList;
|
||||||
// return newList;
|
});
|
||||||
// });
|
});
|
||||||
// });
|
return () => {
|
||||||
// return () => {
|
unsub();
|
||||||
// channel.disChannel();
|
};
|
||||||
// };
|
}, []);
|
||||||
// }, []);
|
|
||||||
|
|
||||||
const sendMenuAction = (uuid: string, menu: ScriptMenuItem) => {
|
const sendMenuAction = (uuid: string, menu: ScriptMenuItem) => {
|
||||||
popupClient.menuClick(uuid, menu).then(() => {
|
popupClient.menuClick(uuid, menu).then(() => {
|
||||||
window.close();
|
window.close();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// 监听菜单按键
|
|
||||||
|
|
||||||
// 菜单展开
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -110,21 +108,15 @@ const ScriptMenuList: React.FC<{
|
|||||||
size="small"
|
size="small"
|
||||||
checked={item.enable}
|
checked={item.enable}
|
||||||
onChange={(checked) => {
|
onChange={(checked) => {
|
||||||
let p: Promise<any>;
|
scriptClient
|
||||||
if (checked) {
|
.enable(item.uuid, checked)
|
||||||
p = scriptCtrl.enable(item.id).then(() => {
|
.then(() => {
|
||||||
item.enable = true;
|
item.enable = checked;
|
||||||
|
setList([...list]);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
Message.error(err);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
p = scriptCtrl.disable(item.id).then(() => {
|
|
||||||
item.enable = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
p.catch((err) => {
|
|
||||||
Message.error(err);
|
|
||||||
}).finally(() => {
|
|
||||||
setList([...list]);
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
@ -138,7 +130,7 @@ const ScriptMenuList: React.FC<{
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ScriptIcons script={item} size={20} />
|
<ScriptIcons script={item} size={20} />
|
||||||
{item.name}
|
{i18nName(item)}
|
||||||
</span>
|
</span>
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
@ -154,9 +146,9 @@ const ScriptMenuList: React.FC<{
|
|||||||
icon={item.runStatus !== SCRIPT_RUN_STATUS_RUNNING ? <RiPlayFill /> : <RiStopFill />}
|
icon={item.runStatus !== SCRIPT_RUN_STATUS_RUNNING ? <RiPlayFill /> : <RiStopFill />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (item.runStatus !== SCRIPT_RUN_STATUS_RUNNING) {
|
if (item.runStatus !== SCRIPT_RUN_STATUS_RUNNING) {
|
||||||
runtimeCtrl.startScript(item.id);
|
runtimeClient.runScript(item.uuid);
|
||||||
} else {
|
} else {
|
||||||
runtimeCtrl.stopScript(item.id);
|
runtimeClient.stopScript(item.uuid);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -168,7 +160,7 @@ const ScriptMenuList: React.FC<{
|
|||||||
type="secondary"
|
type="secondary"
|
||||||
icon={<IconEdit />}
|
icon={<IconEdit />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.open(`/src/options.html#/script/editor/${item.id}`, "_blank");
|
window.open(`/src/options.html#/script/editor/${item.uuid}`, "_blank");
|
||||||
window.close();
|
window.close();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -181,7 +173,7 @@ const ScriptMenuList: React.FC<{
|
|||||||
type="secondary"
|
type="secondary"
|
||||||
icon={<IconMinus />}
|
icon={<IconMinus />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
scriptCtrl.exclude(item.id, `*://${url.host}*`, isExclude(item, url.host)).finally(() => {
|
scriptClient.excludeUrl(item.uuid, `*://${url.host}/*`, isExclude(item, url.host)).finally(() => {
|
||||||
window.close();
|
window.close();
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@ -194,8 +186,8 @@ const ScriptMenuList: React.FC<{
|
|||||||
title={t("confirm_delete_script")}
|
title={t("confirm_delete_script")}
|
||||||
icon={<IconDelete />}
|
icon={<IconDelete />}
|
||||||
onOk={() => {
|
onOk={() => {
|
||||||
setList(list.filter((i) => i.id !== item.id));
|
setList(list.filter((i) => i.uuid !== item.uuid));
|
||||||
scriptCtrl.delete(item.id).catch((e) => {
|
scriptClient.delete(item.uuid).catch((e) => {
|
||||||
Message.error(`{t('delete_failed')}: ${e}`);
|
Message.error(`{t('delete_failed')}: ${e}`);
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@ -259,7 +251,7 @@ const ScriptMenuList: React.FC<{
|
|||||||
type="secondary"
|
type="secondary"
|
||||||
icon={<IconSettings />}
|
icon={<IconSettings />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.open(`/src/options.html#/?userConfig=${item.id}`, "_blank");
|
window.open(`/src/options.html#/?userConfig=${item.uuid}`, "_blank");
|
||||||
window.close();
|
window.close();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -71,22 +71,16 @@ import { i18nName } from "@App/locales/locales";
|
|||||||
import { getValues, ListHomeRender, ScriptIcons } from "./utils";
|
import { getValues, ListHomeRender, ScriptIcons } from "./utils";
|
||||||
import { useAppDispatch, useAppSelector } from "@App/pages/store/hooks";
|
import { useAppDispatch, useAppSelector } from "@App/pages/store/hooks";
|
||||||
import {
|
import {
|
||||||
deleteScript,
|
|
||||||
requestEnableScript,
|
requestEnableScript,
|
||||||
fetchAndSortScriptList,
|
fetchAndSortScriptList,
|
||||||
requestDeleteScript,
|
requestDeleteScript,
|
||||||
ScriptLoading,
|
ScriptLoading,
|
||||||
selectScripts,
|
selectScripts,
|
||||||
sortScript,
|
sortScript,
|
||||||
upsertScript,
|
|
||||||
requestStopScript,
|
requestStopScript,
|
||||||
requestRunScript,
|
requestRunScript,
|
||||||
} from "@App/pages/store/features/script";
|
} from "@App/pages/store/features/script";
|
||||||
import { selectScriptListColumnWidth } from "@App/pages/store/features/setting";
|
import { selectScriptListColumnWidth } from "@App/pages/store/features/setting";
|
||||||
import { MessageQueue, Unsubscribe } from "@Packages/message/message_queue";
|
|
||||||
import { subscribeScriptDelete, subscribeScriptInstall, subscribeScriptRunStatus } from "@App/app/service/queue";
|
|
||||||
import { RuntimeClient } from "@App/app/service/service_worker/client";
|
|
||||||
import { ExtensionMessage, ExtensionMessageSend } from "@Packages/message/extension_message";
|
|
||||||
|
|
||||||
type ListType = Script & { loading?: boolean };
|
type ListType = Script & { loading?: boolean };
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import ScriptStorage from "@App/pages/components/ScriptStorage";
|
|||||||
import ScriptResource from "@App/pages/components/ScriptResource";
|
import ScriptResource from "@App/pages/components/ScriptResource";
|
||||||
import ScriptSetting from "@App/pages/components/ScriptSetting";
|
import ScriptSetting from "@App/pages/components/ScriptSetting";
|
||||||
import { scriptClient } from "@App/pages/store/features/script";
|
import { scriptClient } from "@App/pages/store/features/script";
|
||||||
|
import { i18nName } from "@App/locales/locales";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const { Row } = Grid;
|
const { Row } = Grid;
|
||||||
@ -377,7 +378,7 @@ function ScriptEditor() {
|
|||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
scriptDAO.all().then(async (scripts) => {
|
scriptDAO.all().then(async (scripts) => {
|
||||||
setScriptList(scripts);
|
setScriptList(scripts.sort((a, b) => a.sort - b.sort));
|
||||||
// 如果有id则打开对应的脚本
|
// 如果有id则打开对应的脚本
|
||||||
if (uuid) {
|
if (uuid) {
|
||||||
for (let i = 0; i < scripts.length; i += 1) {
|
for (let i = 0; i < scripts.length; i += 1) {
|
||||||
@ -734,7 +735,7 @@ function ScriptEditor() {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{script.name}
|
{i18nName(script)}
|
||||||
</Button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -65,6 +65,10 @@ function App() {
|
|||||||
const list = resp.scriptList;
|
const list = resp.scriptList;
|
||||||
list.sort((a, b) => {
|
list.sort((a, b) => {
|
||||||
if (a.enable === b.enable) {
|
if (a.enable === b.enable) {
|
||||||
|
// 根据菜单数排序
|
||||||
|
if (a.menus.length !== b.menus.length) {
|
||||||
|
return b.menus.length - a.menus.length;
|
||||||
|
}
|
||||||
if (a.runNum !== b.runNum) {
|
if (a.runNum !== b.runNum) {
|
||||||
return b.runNum - a.runNum;
|
return b.runNum - a.runNum;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user