|
阅读:572回复: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();
})(); |
|
|