@@ -5,6 +5,7 @@ import type {
55 GMUnRegisterMenuCommandParam ,
66 NotificationMessageOption ,
77 ScriptMenuItemOption ,
8+ SWScriptMenuItemOption ,
89 TScriptMenuItemID ,
910 TScriptMenuItemKey ,
1011} from "../service_worker/types" ;
@@ -42,6 +43,7 @@ const execEnvInit = (execEnv: GMApi) => {
4243 execEnv . contentEnvKey = randomMessageFlag ( ) ; // 不重复识别字串。用于区分 mainframe subframe 等执行环境
4344 execEnv . menuKeyRegistered = new Set ( ) ;
4445 execEnv . menuIdCounter = 0 ;
46+ execEnv . regMenuCounter = 0 ;
4547 }
4648} ;
4749
@@ -580,6 +582,10 @@ export default class GMApi extends GM_Base {
580582 // 每个 contentEnvKey(执行环境)初始化时会重设;不持久化、只保证当前环境内递增唯一。
581583 menuIdCounter : number | undefined ;
582584
585+ // 菜单注冊累计器 - 用於穩定同一Tab不同frame之選項的單獨項目不合併狀態
586+ // 每个 contentEnvKey(执行环境)初始化时会重设;不持久化、只保证当前环境内递增唯一。
587+ regMenuCounter : number | undefined ;
588+
583589 // 内容脚本执行环境识别符,用于区分 mainframe / subframe 等环境并作为 menu key 的命名空间。
584590 // 由 execEnvInit() 以 randomMessageFlag() 生成,避免跨 frame 的 ID 碰撞。
585591 // (同一环境跨脚本也不一样)
@@ -588,24 +594,50 @@ export default class GMApi extends GM_Base {
588594 @GMContext . API ( { alias : "GM.registerMenuCommand" } )
589595 GM_registerMenuCommand (
590596 name : string ,
591- listener : ( inputValue ?: any ) => void ,
597+ listener ? : ( inputValue ?: any ) => void ,
592598 options_or_accessKey ?: ScriptMenuItemOption | string
593599 ) : TScriptMenuItemID {
594600 if ( ! this . EE ) return - 1 ;
595601 execEnvInit ( this ) ;
602+ this . regMenuCounter ! += 1 ;
603+ // 兼容 GM_registerMenuCommand(name, options_or_accessKey)
604+ if ( ! options_or_accessKey && typeof listener === "object" ) {
605+ options_or_accessKey = listener ;
606+ listener = undefined ;
607+ }
596608 // 浅拷贝避免修改/共用参数
597- const options = (
609+ const options : SWScriptMenuItemOption = (
598610 typeof options_or_accessKey === "string"
599611 ? { accessKey : options_or_accessKey }
600612 : options_or_accessKey
601- ? { ...options_or_accessKey }
613+ ? { ...options_or_accessKey , id : undefined , individual : undefined } // id不直接储存在options (id 影响 groupKey 操作)
602614 : { }
603615 ) as ScriptMenuItemOption ;
604- let providedId : string | number | undefined = options . id ;
605- delete options . id ; // id不直接储存在options (id 影响 groupKey 操作)
616+ const isSeparator = ! listener && ! name ;
617+ let isIndividual = typeof options_or_accessKey === "object" ? options_or_accessKey . individual : undefined ;
618+ if ( isIndividual === undefined && isSeparator ) {
619+ isIndividual = true ;
620+ }
621+ options . mIndividualKey = isIndividual ? this . regMenuCounter : 0 ;
622+ if ( options . autoClose === undefined ) {
623+ options . autoClose = true ;
624+ }
625+ if ( options . nested === undefined ) {
626+ options . nested = true ;
627+ }
628+ if ( isSeparator ) {
629+ // GM_registerMenuCommand("") 时自动设为分隔线
630+ options . mSeparator = true ;
631+ name = "" ;
632+ listener = undefined ;
633+ } else {
634+ options . mSeparator = false ;
635+ }
636+ let providedId : string | number | undefined =
637+ typeof options_or_accessKey === "object" ? options_or_accessKey . id : undefined ;
606638 if ( providedId === undefined ) providedId = this . menuIdCounter ! += 1 ; // 如无指定,使用累计器id
607- const ret = providedId as TScriptMenuItemID ;
608- providedId = `t${ providedId } ` ; // 见 TScriptMenuItemID 注释
639+ const ret = providedId ! as TScriptMenuItemID ;
640+ providedId = `t${ providedId ! } ` ; // 见 TScriptMenuItemID 注释
609641 providedId = `${ this . contentEnvKey ! } .${ providedId } ` as TScriptMenuItemKey ; // 区分 subframe mainframe,见 TScriptMenuItemKey 注释
610642 const menuKey = providedId ; // menuKey为唯一键:{环境识别符}.t{注册ID}
611643 // 检查之前有否注册
@@ -616,7 +648,10 @@ export default class GMApi extends GM_Base {
616648 // 没注册过,先记录一下
617649 this . menuKeyRegistered ! . add ( menuKey ) ;
618650 }
619- this . EE . addListener ( "menuClick:" + menuKey , listener ) ;
651+ if ( listener ) {
652+ // GM_registerMenuCommand("hi", undefined, {accessKey:"h"}) 时TM不会报错
653+ this . EE . addListener ( "menuClick:" + menuKey , listener ) ;
654+ }
620655 // 发送至 service worker 处理(唯一键,显示名字,不包括id的其他设定)
621656 this . sendMessage ( "GM_registerMenuCommand" , [ menuKey , name , options ] as GMRegisterMenuCommandParam ) ;
622657 return ret ;
0 commit comments