阅读:112回复:0
给右键加点高级设置
AI写的,没有售后
![]() (function() { 'use strict'; const CONFIG = { MENU_ID: 'advanced-settings-menu', SEPARATOR_ID: 'advanced-settings-separator', POPUP_ID: 'advanced-settings-popup', CONTEXT_MENU_ID: 'contentAreaContextMenu', MENU_LABEL: '高级设置' }; const ADVANCED_SETTINGS = new Map([ ['browser.tabs.closeTabByDblclick', '双击关闭标签页'], ['browser.tabs.closeWindowWithLastTab', '关闭最后一个标签页同时关闭窗口'], ['browser.compactmode.show', '定制密度增加紧凑模式'], ['browser.urlbar.openintab', '地址栏在新标签页打开'], ['browser.urlbar.trimURLs', '地址栏隐藏http/https'], ['browser.tabs.insertAfterCurrent', '在当前标签页右侧打开地址栏新标签页'], ['browser.newtabpage.activity-stream.improvesearch.handoffToAwesomebar', '主页搜索框输入跳到地址栏'] ]); const MENU_CONFIG = [ { type: 'settings', items: ADVANCED_SETTINGS }, { type: 'separator' }, { type: 'action', label: '重置全部', action: 'reset' }, { type: 'separator' }, { type: 'action', label: '关闭菜单', action: 'close' } ]; const safeExecute = (fn, fallback = null) => { try { return fn(); } catch (e) { console.error(e); return fallback; } }; const PreferenceManager = { getBoolPref: (name, def = false) => safeExecute(() => Services.prefs.getBoolPref(name, def), def), setBoolPref: (name, val) => safeExecute(() => (Services.prefs.setBoolPref(name, val), true), false), togglePref(name) { const current = this.getBoolPref(name); return this.setBoolPref(name, !current) ? !current : current; }, resetPrefs(names) { const results = new Map(); for (const name of names) { results.set(name, this.setBoolPref(name, false)); } return results; } }; const DOMUtils = { createXULElement(type, attrs = {}) { return safeExecute(() => { const el = document.createXULElement(type); Object.entries(attrs).forEach(([k, v]) => v != null && el.setAttribute(k, v)); return el; }); }, removeElements: ids => ids.forEach(id => document.getElementById(id)?.remove()), getElementById: id => document.getElementById(id) }; class MenuBuilder { constructor() { this.menuItems = new Map(); this.eventController = new AbortController(); } createMenuItem(config) { const creators = { settings: c => this.createSettingsItems(c.items), separator: () => [DOMUtils.createXULElement('menuseparator')], action: c => [this.createActionItem(c)] }; return creators[config.type]?.(config) || []; } createSettingsItems(settings) { const items = []; for (const [name, label] of settings) { const item = DOMUtils.createXULElement('menuitem', { id: `toggle-${name}`, label, type: 'checkbox', checked: PreferenceManager.getBoolPref(name), closemenu: 'none' }); if (item) { item.dataset.prefName = name; this.menuItems.set(name, item); items.push(item); } } return items; } createActionItem(config) { const item = DOMUtils.createXULElement('menuitem', { label: config.label, closemenu: config.action === 'close' ? 'auto' : 'none' }); if (item) item.dataset.action = config.action; return item; } buildMenu() { const fragment = document.createDocumentFragment(); MENU_CONFIG.forEach(config => { this.createMenuItem(config).forEach(item => item && fragment.appendChild(item)); }); return fragment; } updateMenuItem(name, checked) { this.menuItems.get(name)?.setAttribute('checked', checked); } destroy() { this.eventController.abort(); this.menuItems.clear(); } } class AdvancedSettingsMenu { constructor() { this.menuBuilder = null; this.isInitialized = false; } init() { if (this.isInitialized) return; const contextMenu = DOMUtils.getElementById(CONFIG.CONTEXT_MENU_ID); if (!contextMenu) return; this.cleanup(); this.createMenu(contextMenu); this.isInitialized = true; } cleanup() { DOMUtils.removeElements([CONFIG.MENU_ID, CONFIG.SEPARATOR_ID]); this.menuBuilder?.destroy(); } createMenu(contextMenu) { this.menuBuilder = new MenuBuilder(); const elements = { separator: DOMUtils.createXULElement('menuseparator', { id: CONFIG.SEPARATOR_ID }), menu: DOMUtils.createXULElement('menu', { id: CONFIG.MENU_ID, label: CONFIG.MENU_LABEL }), popup: DOMUtils.createXULElement('menupopup', { id: CONFIG.POPUP_ID }) }; if (!Object.values(elements).every(Boolean)) return; elements.popup.addEventListener('command', e => this.handleMenuCommand(e, contextMenu), { signal: this.menuBuilder.eventController.signal }); elements.popup.appendChild(this.menuBuilder.buildMenu()); elements.menu.appendChild(elements.popup); contextMenu.append(elements.separator, elements.menu); } handleMenuCommand(event, contextMenu) { const { prefName, action } = event.target.dataset; if (prefName) { const newValue = PreferenceManager.togglePref(prefName); event.target.setAttribute('checked', newValue); } else if (action === 'reset') { const results = PreferenceManager.resetPrefs(ADVANCED_SETTINGS.keys()); for (const [name, success] of results) { success && this.menuBuilder.updateMenuItem(name, false); } } else if (action === 'close') { contextMenu.hidePopup(); } } destroy() { this.cleanup(); this.isInitialized = false; } } const InitManager = { menu: null, init() { if (this.menu) return; this.menu = new AdvancedSettingsMenu(); if (document.readyState === 'complete') { this.menu.init(); } else { document.addEventListener('DOMContentLoaded', () => this.menu.init(), { once: true }); } window.addEventListener('unload', () => this.cleanup(), { once: true }); }, cleanup() { this.menu?.destroy(); this.menu = null; } }; InitManager.init(); })(); |
|
|