11import { kStyleIdPrefix , UCD } from '@/js/consts' ;
2- import { configDialog } from '@/js/dom-util' ;
2+ import { configDialog , getEventKeyName } from '@/js/dom-util' ;
33import { API } from '@/js/msg-api' ;
44import { __values } from '@/js/prefs' ;
5- import { MAC } from '@/js/ua' ;
5+ import { CHROME , MAC } from '@/js/ua' ;
66import { getActiveTab } from '@/js/util-webext' ;
77import { tabId , tabUrl } from '.' ;
88import * as hotkeys from './hotkeys' ;
99import { closeMenu , menu , openMenu } from './menu' ;
1010import { createStyleElement , installed , reSort } from './render' ;
1111
12- /** @type {{[sel: string]: (this: HTMLElement, evt: MouseEvent, entry?: HTMLElement) => any} } */
12+ /**
13+ * @callback OnClickHandler
14+ * @this {HTMLElement}
15+ * @param {MouseEvent } evt
16+ * @param {StyleEntryElement } [entry]
17+ * @param {number } [button]
18+ */
19+ /** @type {{[sel: string]: OnClickHandler} } */
1320export const OnClick = {
1421 '.style-name' : Object . assign ( ( evt , entry ) => {
1522 if ( evt . button
@@ -20,47 +27,42 @@ export const OnClick = {
2027 else openEditor ( evt , entry ) ;
2128 }
2229 } , {
23- btn1 : true ,
24- btn2 : true ,
30+ btn : 1 + 2 ,
2531 } ) ,
2632 async input ( evt , entry = this ) {
2733 await API . styles . toggle ( entry . styleId , this . checked ) ;
2834 reSort ( ) ;
2935 } ,
3036 '.configure' : Object . assign ( configure , {
31- btn2 : true ,
37+ btn : 1 + 2 ,
3238 } ) ,
3339 '.menu-button' : Object . assign ( ( event , entry ) => openMenu ( entry ) , {
34- btn2 : true ,
40+ btn : 2 ,
3541 } ) ,
3642 '.style-edit-link' : openEditor ,
3743} ;
3844export const styleFinder = { } ;
3945
40- window . onclick =
41- window . onauxclick =
42- window . oncontextmenu = event => {
43- let { button} = event ;
44- if ( button === 1 && event . type !== 'auxclick'
45- || button === 2 && event . type !== 'contextmenu' )
46- return ;
47- const { target} = event ;
48- const entry = target . closest ( '.entry' ) ;
49- if ( ! entry )
50- return ;
51- let el = target ;
52- let fn = OnClick [ '.' + el . className ] || OnClick [ el . localName ] ;
53- button = button && `btn${ button } ` ;
54- for ( const selector in OnClick ) {
55- if ( fn || ( fn = ( el = target . closest ( selector ) ) && OnClick [ selector ] ) ) {
56- if ( ! button || fn [ button ] ) {
57- if ( button ) event . preventDefault ( ) ;
58- fn . call ( el , event , entry ) ;
59- }
60- return ;
61- }
46+ /** Explicit handling of auxclick or contextmenu for right-click as Firefox loses user gesture */
47+ let elClick ;
48+ window . onmousedown = window . onkeydown = evt => {
49+ elClick = evt . target ;
50+ } ;
51+ window . onmouseup = evt => {
52+ if ( elClick === evt . target )
53+ clickRouter ( evt ) ;
54+ } ;
55+ window . onkeyup = evt => {
56+ switch ( elClick === evt . target && getEventKeyName ( evt ) ) {
57+ case 'ContextMenu' :
58+ case 'Shift-F10' :
59+ clickRouter ( evt , 2 ) ;
6260 }
6361} ;
62+ if ( __ . BUILD !== 'firefox' && ( __ . MV3 || CHROME ) ) {
63+ // suppressing context menu in Chrome
64+ window . oncontextmenu = evt => elClick !== evt . target ;
65+ }
6466
6567Object . assign ( $ ( '#find-styles-btn' ) , {
6668 onclick : openStyleFinder ,
@@ -93,29 +95,40 @@ export async function handleUpdate({style}) {
9395}
9496
9597/**
96- * @this {HTMLAnchorElement} either <a target=_blank href=...> or <a> for a config icon
97- * @param {KeyboardEvent | MouseEvent } event
98- * @param {StyleEntryElement } entry
98+ * @param {MouseEvent|KeyboardEvent } event
99+ * @param {number } [btn]
99100 */
100- export async function configure ( event , entry ) {
101+ function clickRouter ( event , btn = event . button ) {
102+ const entry = elClick . closest ( '.entry' ) ;
103+ if ( ! entry )
104+ return ;
105+ let el = elClick ;
106+ let fn = OnClick [ '.' + el . className ] || OnClick [ el . localName ] ;
107+ for ( const selector in OnClick ) {
108+ if ( fn || ( fn = ( el = elClick . closest ( selector ) ) && OnClick [ selector ] ) ) {
109+ if ( ! btn || fn . btn & /* using binary AND */ btn ) {
110+ event . preventDefault ( ) ;
111+ fn . call ( el , event , entry , btn ) ;
112+ }
113+ return ;
114+ }
115+ }
116+ }
117+
118+ export async function configure ( event , entry , button ) {
101119 if ( ! this . target ) {
102- let mode ;
103- if ( __ . MV3 && (
104- event . type === 'contextmenu' ||
120+ let mode , sbCH , sbFF ;
121+ if ( ( __ . BUILD === 'chrome' ? sbCH = chrome . sidePanel : sbFF = browser . sidebarAction ) && (
122+ button ||
105123 ! ( mode = __values [ 'config.sidePanel' ] ) ||
106124 mode > 0 && entry . styleMeta [ UCD ] . vars >= mode
107125 ) ) {
108- await chrome . sidePanel . setOptions ( {
109- tabId,
110- path : `sidepanel.html?` + new URLSearchParams ( {
111- tabId,
112- id : entry . styleId ,
113- } ) ,
114- } ) ;
115- await chrome . sidePanel . open ( { tabId} ) ;
116- } else {
117- hotkeys . pause ( ( ) => configDialog ( entry . styleId ) ) ;
126+ const p = `sidepanel.html?id=${ entry . styleId } ` ;
127+ if ( sbCH ) sbCH . setOptions ( { tabId, path : p } ) ;
128+ else sbFF . setPanel ( { tabId, panel : p } ) ;
129+ return sbCH ?. open ( { tabId} ) || sbFF . open ( ) ;
118130 }
131+ hotkeys . pause ( ( ) => configDialog ( entry . styleId ) ) ;
119132 } else {
120133 openURLandHide . call ( this , event ) ;
121134 }
0 commit comments