From 34e8098bb9578061f5287c045ef25d7740d4b047 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Wed, 1 Oct 2025 18:38:52 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BA=8C=E7=BA=A7=E8=8F=9C=E5=8D=95&?= =?UTF-8?q?=E5=88=86=E9=9A=94=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/service/service_worker/popup.ts | 96 ++++++++++++------- src/pages/components/ScriptMenuList/index.tsx | 5 +- 2 files changed, 65 insertions(+), 36 deletions(-) diff --git a/src/app/service/service_worker/popup.ts b/src/app/service/service_worker/popup.ts index 944d5a77c..d3d770c81 100644 --- a/src/app/service/service_worker/popup.ts +++ b/src/app/service/service_worker/popup.ts @@ -40,32 +40,59 @@ export class PopupService { private systemConfig: SystemConfig ) {} - genScriptMenuByTabMap(menu: ScriptMenu[]) { - let n = 0; + genScriptMenuByTabMap(menuEntries: chrome.contextMenus.CreateProperties[], menu: ScriptMenu[]) { for (const { uuid, name, menus } of menu) { - // 如果是带输入框的菜单则不在页面内注册 - const nonInputMenus = menus.filter((item) => !item.options?.inputType); - // 创建脚本菜单 - if (nonInputMenus.length) { - n += nonInputMenus.length; - chrome.contextMenus.create({ - id: `scriptMenu_${uuid}`, - title: name, - contexts: ["all"], - parentId: "scriptMenu", - }); - nonInputMenus.forEach((menu) => { - // 创建菜单 - chrome.contextMenus.create({ - id: `scriptMenu_menu_${uuid}_${menu.id}`, - title: menu.name, + const subMenuEntries = [] as chrome.contextMenus.CreateProperties[]; + let withMenuItem = false; + // eslint-disable-next-line prefer-const + for (let { id, name, options } of menus) { + // 如果是带输入框的菜单则不在页面内注册 + if (options?.inputType) return; + let level = 3; + if (name[0] === "\xA7") { + // section sign (§) + level = 2; + name = name.substring(1); + // chrome.contextMenus的API限制:不支持一级菜单创建 (不支持 §§) + } + let createProperties: chrome.contextMenus.CreateProperties; + name = name.trim(); + if (!name.length) { + // 创建菜单分隔线 + createProperties = { + id: `scriptMenu_menu_${uuid}_${id}`, + type: "separator", contexts: ["all"], - parentId: `scriptMenu_${uuid}`, - }); - }); + }; + } else { + // 创建菜单项目 + createProperties = { + id: `scriptMenu_menu_${uuid}_${id}`, + title: name, + contexts: ["all"], + }; + withMenuItem = true; + } + if (level === 3) { + createProperties.parentId = `scriptMenu_${uuid}`; + } else if (level === 2) { + createProperties.parentId = `scriptMenu`; + } + subMenuEntries.push(createProperties); + } + if (withMenuItem) { + menuEntries.push( + { + // 创建脚本菜单 + id: `scriptMenu_${uuid}`, + title: name, + contexts: ["all"], + parentId: "scriptMenu", + }, + ...subMenuEntries + ); } } - return n; } // 生成chrome菜单 @@ -81,23 +108,24 @@ export class PopupService { if (!menu.length && !backgroundMenu.length) { return; } - let n = 0; - // 创建根菜单 - chrome.contextMenus.create({ - id: "scriptMenu", - title: "ScriptCat", - contexts: ["all"], - }); + const menuEntries = [] as chrome.contextMenus.CreateProperties[]; if (menu) { - n += this.genScriptMenuByTabMap(menu); + this.genScriptMenuByTabMap(menuEntries, menu); } // 后台脚本的菜单 if (backgroundMenu) { - n += this.genScriptMenuByTabMap(backgroundMenu); + this.genScriptMenuByTabMap(menuEntries, backgroundMenu); } - if (n === 0) { - // 如果没有菜单,删除菜单 - await chrome.contextMenus.remove("scriptMenu"); + if (menuEntries.length > 0) { + // 创建根菜单 + menuEntries.unshift({ + id: "scriptMenu", + title: "ScriptCat", + contexts: ["all"], + }); + for (const menuEntry of menuEntries) { + chrome.contextMenus.create(menuEntry); + } } } diff --git a/src/pages/components/ScriptMenuList/index.tsx b/src/pages/components/ScriptMenuList/index.tsx index bc646f9f2..133eec3ea 100644 --- a/src/pages/components/ScriptMenuList/index.tsx +++ b/src/pages/components/ScriptMenuList/index.tsx @@ -62,7 +62,8 @@ const MenuItem = React.memo(({ menu, uuid }: MenuItemProps) => { return null; } })(); - + const menuName = menu.name.replace(/^\xA7+/, "").trim(); + if (!menuName) return <>>; return (