Всё вроде выбирается. Код кнопки у меня отсюда.
+ изменения раз, два.
Такая же фигня на 91 esr.
Dobrov
Просто вы понакрутили дров в своем скрипте, так что он работает не так как ожидалось. Или использовали на 78esr те фиксы которые для версий выше предназначались.
Оригинальный же, от Dumby, даже с правками, так себя не ведет. Ссылки на использованные фиксы искать лень, но что-то брал и из вашего с ним обсуждения.
Отсутствует
Vitaliy V. — насколько я понял, в CustomStylesScripts.jsm нет возможности подключать jsm-скрипты ?
Сделайте в новой версии UserChromeFiles подключение не только js но и jsm-скриптов. Пока поправил user_chrome.js так:
scriptsbackground: [ // В фоне [System Principal] { path: "custom_script.js", }, ……………… { path: "ClickPicSave.jsm", }, if (s.path) // правка в user_chrome.js if (/\.jsm$/i.test(s.path)) ChromeUtils.import(`chrome://user_chrome_files/content/custom_scripts/${s.path}`) else Services.scriptloader.loadSubScript(`chrome://user_chrome_files/content/custom_scripts/${s.path}`, scope);
Просто вы понакрутили дров в своем скрипте, так что он работает не так как ожидалось.
Оригинальный же, от Dumby, даже с правками, так себя не ведет.
Не накрутил, а оптимизировал и по возможности сократил код, исключил клики и подсказки и повысил удобство использования.
Всё вроде выбирается.
_zt и xrun1 - Неверно! Я тоже тестировал все версии кода! Вот код xrun1 со всеми правками:
// Быстрое переключение параметров about:config (async (name, id, func) => { if (name == "Object") return CustomizableUI.createWidget(func()); var win = name == "Window", g = Components.utils.import("resource://gre/modules/Services.jsm", {}); if (g[id]) {if (win) return;} else g[id] = func(); if (win) return CustomizableUI.createWidget(g[id]); addDestructor(r => r[5] == "e" && delete g[id]); g[id].onCreated(this); })(this.constructor.name, "QuickToggleAboutConfigSettings", () => { var {prefs} = Services, db = prefs.getDefaultBranch(""); var pv = parseInt(Services.appinfo.platformVersion); var xul_ns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; //===================================================================================== // refresh: // false - reload current tab // true - reload current tab skip cache // // restart: // false - restart browser // true - restart browser with confirm var primary = [{ pref: ["network.proxy.type", "Настройки прокси"], userChoice: 5, userAlt: 1, refresh: true, values: [ [0, "Не проксировать", "0"], [5, "Системные (из IE)", "5"], [2, "Авто (pacfile)", "2"], [1, "Прописанные", "1"], [4, "Автоопределение", "4"] ]}, null, { pref: ["permissions.default.image", "Загружать графику"], userChoice: 1, refresh: true, values: [[1, "Да"], [3, "С сайта"], [2, "Нет"]] },{ pref: ["browser.display.use_document_fonts", "Загружать web-шрифты"], userChoice: 1, refresh: true, values: [[1, "Да"], [0, "Нет"]] },{ pref: ["javascript.enabled", "Выполнять скрипты Java"], userChoice: true, refresh: true, values: [[true, "Да"], [false, "Нет"]] },{ pref: ["media.autoplay.default", "Автозапуск медиа"], userChoice: 5, refresh: true, values: [ [5, "Блокировать все", "5"], [1, "Блокировать не приглушенное", "1"], [0, "Разрешить все", "0"] ]},{ pref: ["media.autoplay.blocking_policy", "Автозапуск (политика)"], userChoice: 1, userAlt: 2, refresh: true, values: [ [1, "Временная", "1"], [2, "По действию", "2"], [0, "Постоянная", "0"] ]},{ pref: ["network.cookie.cookieBehavior", "Cookies"], userChoice: 1, userAlt: 3, refresh: false, values: [ [1, "Не принимать сторонние"], [3, "Не принимать с не посещенных"], [4, "Не принимать от трекеров"], [2, "Не принимать со всех"], [0, "Принимать со всех"] ]}, null, { pref: ["dom.storage.enabled", "Локальное хранилище"], userChoice: true },{ pref: ["browser.tabs.remote.force-enable", "Многопоточный режим вкладок"], userChoice: true, userAlt: false, values: [[true, "Да"], [false, "Нет"]] } ]; //===================================================================================== var secondary = [{ pref: ["dom.serviceWorkers.enabled", "Видео dom.serviceWorkers"], userChoice: false },{ pref: ["dom.enable_performance", "Статус загрузки страницы"], userChoice: false }, null, { pref: ["browser.cache.memory.enable", "Кэш в оперативной памяти"], userChoice: true }, null, { pref: ["intl.accept_languages", "Язык для веб-страниц"], userChoice: "en-US, en", values: [["en-US, en", "en-US, en"], ["en-US, en, ru-RU, ru", "en-US, en, ru-RU, ru"]] },{ pref: ["browser.display.document_color_use", "Использовать цвета сайтов"], userChoice: 0, values: [[0, "Авто", "0"], [1, "Всегда", "1"], [2, "Никогда", "2"]] }, null, { pref: ["network.http.sendRefererHeader", "Referer - для чего"], userChoice: 1, values: [[0, "Ни для чего", "0"], [1, "Только ссылки", "1"], [2, "Ссылки и изобр.", "2"]] },{ pref: ["network.http.referer.trimmingPolicy", "Referer - что"], userChoice: 0, values: [[0, "Полный URL", "0"], [1, "scheme+host+port+path", "1"], [2, "scheme+host+port", "2"]] },{ pref: ["network.http.referer.XOriginPolicy", "RefererXO - когда"], userChoice: 0, values: [[0, "В любом случае", "0"], [1, "При совп. баз. домена", "1"], [2, "При совпадении адреса", "2"]] },{ pref: ["network.http.referer.XOriginTrimmingPolicy", "RefererXO - что"], userChoice: 0, values: [[0, "Полный URL", "0"], [1, "scheme+host+port+path", "1"], [2, "scheme+host+port", "2"]] },{ pref: ["network.http.referer.spoofSource", "Referer - корень сайта"], userChoice: false }, null, { pref: ["media.peerconnection.enabled", "WebRTC утечка IP"], userChoice: false } ]; return { label: "Quick toggle", id: "QuickToggleAboutConfigSettings", localized: false, image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFPSURBVDhPnVPNSsNAEJ5tamnBk+A7BMEcikohp/gi9i18nRafQoT00kK16tnn8CJo4vp9m5m41eSgH0zmd3d+diJ/gfdedvl0QW7k1PcLwem+3TjowZagK+Nn6yc3gNCJ+LCCh9LzzTMdqeoNbkQSFZmpJLGCW5Gx2hZaQahMbZ52VuDSfHpnAVJXOb4FKzianbzCXiLrHLYl5C3t5NTRwtxaKJxUTZ/JcOTr6q2Rxwf0aVb2/hLs4KqL3Isckz/mmSdRRksjyg+z7IM6LzDCBfuvAEOJmIKBOqAWmo1YodxLlQNsyO0rsIV/AZM+JGc2a4GgzhZ2p9mFmrpboCMqNYBDdMlwompoTWN6F2nFT5hBXb0PEpmo/Gk+oH+RrqNZINPeIlnZViV1jQuLFJQuWGB0gJdwgShvqdPXZv6J+F/QS7oXqQ9xBTFZ5oa8fAGs9fed5YhPSwAAAABJRU5ErkJggg==", onCreated(btn) { btn.setAttribute("image", this.image); var doc = btn.ownerDocument; btn.btn = true; btn.domParent = null; btn.popups = new btn.ownerGlobal.Array(); this.createPopup(doc, btn, "primary", primary); this.createPopup(doc, btn, "secondary", secondary); this.createCloseMenusOption(doc, btn); btn.linkedObject = this; for(var type of ["command", "contextmenu"]) btn.setAttribute("on" + type, `linkedObject.${type}(event)`); }, createPopup(doc, btn, name, data) { var popup = doc.createElementNS(xul_ns, "menupopup"); var prop = name + "Popup"; btn.popups.push(btn[prop] = popup); popup.id = this.id + "-" + prop; for (var type of ["popupshowing", "click"]) popup.setAttribute("on" + type, `parentNode.linkedObject.${type}(event)`); for(var obj of data) popup.append(this.createElement(doc, obj)); btn.append(popup); }, map: {b: "Bool", n: "Int", s: "String"}, createElement(doc, obj) { if (!obj) return doc.createElementNS(xul_ns, "menuseparator"); var pref = doc.ownerGlobal.Object.create(null), node, img, bool; for(var [key, val] of Object.entries(obj)) { if (key == "pref") { var [apref, lab, akey, ttt] = val; pref.pref = apref; pref.lab = lab || apref; if (ttt) pref.ttt = ttt; } else if (key == "image") img = val, pref.img = true; else if (key != "values") pref[key] = val; else pref.hasVals = true; } var type = prefs.getPrefType(pref.pref); var str = this.map[type == prefs.PREF_INVALID ? obj.values ? (typeof obj.values[0][0])[0] : "b" : type == prefs.PREF_BOOL ? "b" : type == prefs.PREF_INT ? "n" : "s" ]; pref.get = prefs[`get${str}Pref`]; pref.set = prefs[`set${str}Pref`]; node = doc.createElementNS(xul_ns, "menu"); node.className = "menu-iconic"; node.setAttribute("closemenu", "none"); img && node.setAttribute("image", img); akey && node.setAttribute("accesskey", akey); (node.pref = pref).vals = doc.ownerGlobal.Object.create(null); this.createRadios(doc, str.startsWith("B") && !pref.hasVals ? [[true, "true"], [false, "false"]] : obj.values, node.appendChild(doc.createElementNS(xul_ns, "menupopup")) ); if ("userChoice" in obj) pref.noAlt = !("userAlt" in obj); return node; }, createCloseMenusOption(doc, btn) { var pn = this.closePref = "QuickToggleAboutConfigSettings.closeMenus"; var data = [null, { pref: [pn, "Закрывать меню этой кнопки"], values: [[true, "Да"], [false, "Нет"]] }]; var setCloseMenus = e => { e.stopPropagation(); var trg = e.target, {pref, val} = trg, updPopup = true, clear; switch(e.type) { case "command": pref = (trg = trg.closest("menu")).pref; updPopup = false; break; case "click": if (e.button) return; break; case "contextmenu": e.preventDefault(); clear = pref; } if (!pref) return; if (clear) prefs.clearUserPref(pn); else if (!updPopup && val === pref.val) return; else pref.set(pn, val !== undefined ? val : !pref.val); this.upd(trg); updPopup && this.popupshowing(null, trg.querySelector("menupopup")); } (this.createCloseMenusOption = (doc, btn) => { for(var obj of data) btn.secondaryPopup.append(this.createElement(doc, obj)); var m = btn.secondaryPopup.lastChild; m.style.cssText = "fill: lightblue !important; list-style-image: url(chrome://browser/skin/menu.svg) !important;"; m.setAttribute("oncommand", "setCloseMenus(event)"); m.onclick = m.oncontextmenu = m.setCloseMenus = setCloseMenus; })(doc, btn); }, UserChoiceImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACRUlEQVR42qWTS2gTQRjH/zPJZo2BDfgkB62vYg5CjQdvRUE8WB8HKyahYotIQQOeFKGCF7EgvQlBqOCjWFKlevBRDyL4uHloLXhYqWJroaEqlETSptndGb+ZPDH0ojN8O8vA98vv+/Itw38u1nSRYRE6UhKyg4FF1R292/Q+xhhLi4TIrgjgIzwe4MbgmR2nrZMtxxEN63zYORuPZp7gzpehvCu9XjfuPmwCUHIiEtw4fK89zVvD2+FHAD56quXBpV3CVO4ret6nxHzxZxdBRuqADCKmz7RHD9y2tlmbYbBVfwE8DXBkEd/y39H5+mze8ZyoSIpsFXC9u/VE3/ldpyg5AAMEoJMTQi2hANKBgyKdy0h/eoChqcf9MimvVAHjd/fdiG0NRwgQpDAp1agBpDZwdHKJLKZzc+h5e3kCSexh5c5j8fmhW0HGpNZXFkqfsQpAKgcFKGmAlAxHXp5bkkmsrhosjh4cCIJ5pG5qfQXgtMslqO1qgEMWTPrR+eriEhoA4wN7L8TWh0KVXzfgY2RQAUjVBenWLH4UCrj04Wa9BNXEo5va+w63xCiJ6WRVP2MVgNQIgjgEA17MTODZ7Lt+AtSaGDG4377a1m2FAkKrc11/dUwIID1dSKHEcW3yft4RbpR6kK1PYgaJtaY1nNp5jIeMsjKNbs1AWRUcjvTnp2Kh9LtLJGTDINUhcTIZ3L+hzdq9ZgvWmSF9/Wu5gI8L03gzP5l3hddL/3/zKDdA9MdE0UERrdzaFGMUaap75Y/pX9Yfap76EQYaCeEAAAAASUVORK5CYII=", notUserChoiceImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACNUlEQVR42qXTT2jTUBwH8G9e0ta2ks5ND0Ww/qX1oGyevEwQnOBA6EHXwLwoUh3eRGRs501RPE6xgp6KrexQECZY8DBPXmbRS4Z/K0gRtmmDa2yb5PlLX7p2Gwpi4EfCy8sn3/dPwn9e0saGnCRF6XYFnA9DkhKtRs51ep6jmtEcp/JHIM9Yivl9mf0XNDV2Ngn1YLzVxdB1lJ8U8P5hzuCWnR6xrPwmIM8kLRjdkT326BaLHNgLKAFA9ouXdhOw6qi++4j589cd89vSaMqyc2sAPUXlgF8fyt9WI3t2Av4w4NsCMJ8AHAKav6hqqH76iuLINcNuNhOawyttYCp+7tRE/6XT9GFQAG4CpniATQkIaNQIMVG6/xSL2WfTGueTbWDh5L2rA9t29QGBrQQEPUDuAuoEmFSr+P5lGc8v33mtAUfaQO3M4/GgDOoYCIkUin8D0BDDoBQ2ZMxqN0wCQh0gMxaUnYb4uzt+dwIZ8wBHTGQbYAHMpu+uAxaGxpMDvSr3AHcFaAIlD+BtoN6ag5WqhOLNwrohTMWPH5roP7pdLIwb3wW6EziWGAZhpVdLWHzxdpqAyc4yKrJ+4uKg2oMV+lgRK9CdwAVsG1WpF8UH84Zt2QkCKmsbiRAtFAllB5OHWQ9fpr81OwlcgBL9kPrwsvDGMQ1zNMV5ZyN1ISlZYZl9/TE1tjuMSFgA1VWO8uef+FAqG47tpFMcm7dyFyIOEzBMlfCadao5qhk39l9P479evwFbiOcRSXKueAAAAABJRU5ErkJggg==", UserAltImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIfSURBVDhPpVM9b9NQFD02cSKKFVGKIFFREFsmFiCA1AEQQrQjC0gssLCkC0jJj0iFWFoGdiT4Ay0SEmJBhPI5FBokikL4SCC0Te2UxInt13Mdu1CVrVc6713fe86x/T6w09DCeTNKJ7Q0pzyUmoCmZYOiUhXms8RMcd6vB7UwthhM5fTLWix2L3PmYjKdOwdz9DDFGtr1KuovnqD29JGlfO9Goew9DCV/DaZy2pXE8PD9Y/mbupk6xE6cVWPQhEujHo2+4fXdO76ztnq1UPYfSCcwKB1HWjeMyunCraSZOsDqbkBPsBOTNoMGvkOTLto/f+F56bble262OK/qesiYzIydTJojFLjrgEe4bcIOEdXWYe6LITN2KgmFSRFGBuPpo0eAngX0SexTJHD5LOgLpEZTcgKuUuMijAyy5l7+r0NSb21g5LQI5gGYSy2AjYBLjQyRAUniTnJXsBoayBzm3RBBndwwIoOK3fgNdIREQYCV/0DqLdiNZqCRITKYayx85RfQuUNiZ3k7IgO+vfGeXGpkiAyma++WLHtZhZ8o5H/FEVpos1V7u8TFwLQId8nw+Afa51Oq2vyycmlk9KCW0GXFZeu63IUO8z88Bx5s28SbuUXfddzrxVcobxpI0GTh7H734/dPzQt9d0/CGBpCPB7nbhmwbAPVxR4+PPtsuU7/WuElth/lKORUcsoTE8TgMg0WbJaY4Zu3XKYdBrABARUk+ls4DfQAAAAASUVORK5CYII=", upd(node) { var {pref} = node, def = false, user = false, val; if (prefs.getPrefType(pref.pref) != prefs.PREF_INVALID) { var pn = pref.pref; try {val = pref.defVal = db[pref.get.name](pn); def = true} catch(ex) {def = false;} var user = prefs.prefHasUserValue(pn); if (user) try {val = pref.get(pn, undefined);} catch(ex) {} } if (val == pref.val && def == pref.def && user == pref.user) return; pref.val = val; pref.def = def; pref.user = user; var exists = def || user; var ttt = exists ? val : "Этого префа не существует"; if (ttt === "") ttt = "[ empty_string ]"; ttt += "\n" + pref.pref; if (pref.ttt) ttt += "\n" + pref.ttt; node.tooltipText = ttt; var img, alt = "userAlt" in pref && val == pref.userAlt; if (alt) img = this.UserAltImg; if ("userChoice" in pref) if (val == pref.userChoice) //node.style.removeProperty("color"), img = this.UserChoiceImg; else { //node.style.setProperty("color", "maroon", "important"); if (!alt) img = this.notUserChoiceImg; } if (!pref.img) img ? node.setAttribute("image", img) : node.removeAttribute("image"); user ? node.style.setProperty("font-style", "italic", "important") : node.style.removeProperty("font-style"); var {lab} = pref; if (exists && pref.hasVals) { if (val in pref.vals) var sfx = pref.vals[val] || val; else var sfx = user ? "Другое" : "По умолчанию"; lab += ` — "${sfx}"`; } node.setAttribute("label", lab); }, createRadios(doc, vals, popup) { for(var arr of vals) { if (!arr) { popup.append(doc.createElementNS(xul_ns, "menuseparator")); continue; } var [val, lab, key, ttt] = arr; var menuitem = doc.createElementNS(xul_ns, "menuitem"); menuitem.setAttribute("type", "radio"); menuitem.setAttribute("closemenu", "none"); menuitem.style.setProperty("font-style", "italic", "important"), menuitem.setAttribute("label", popup.parentNode.pref.vals[val] = lab); key && menuitem.setAttribute("accesskey", key); var tip = menuitem.val = val; if (ttt) tip += "\n" + ttt; menuitem.tooltipText = tip; popup.append(menuitem); } }, openPopup(popup) { var btn = popup.parentNode; if (btn.domParent != btn.parentNode) { btn.domParent = btn.parentNode; var pos; if (btn.matches(".widget-overflow-list > :scope")) pos = "after_start"; else var win = btn.ownerGlobal, {width, height, top, bottom, left, right} = btn.closest("toolbar").getBoundingClientRect(), pos = width > height ? `${win.innerHeight - bottom > top ? "after" : "before"}_start` : `${win.innerWidth - right > left ? "end" : "start"}_before`; for(var p of btn.popups) p.setAttribute("position", pos); } popup.openPopup(btn); }, maybeRestart(node, conf) { if (conf && !Services.prompt.confirm(null, this.label, "Перезапустить браузер?")) return; var cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool); Services.obs.notifyObservers(cancel, "quit-application-requested", "restart"); return cancel.data ? Services.prompt.alert(null, this.label, "Запрос на выход отменен.") : this.restart(); }, async restart() { var meth = Services.appinfo.inSafeMode ? "restartInSafeMode" : "quit"; Services.startup[meth](Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); }, regexpRefresh: /^(?:view-source:)?(?:https?|ftp)/, maybeRe(node, fe) { var {pref} = node; if ("restart" in pref) { if (this.maybeRestart(node, pref.restart)) return; } else this.popupshowing(fe, node.parentNode); if ("refresh" in pref) { var win = node.ownerGlobal; if (this.regexpRefresh.test(win.gBrowser.currentURI.spec)) pref.refresh ? win.BrowserReloadSkipCache() : win.BrowserReload(); } }, maybeClosePopup(e, trg) { !e.ctrlKey && prefs.getBoolPref(this.closePref, undefined) && trg.parentNode.hidePopup(); }, command(e) { var trg = e.target; if (trg.btn) return this.openPopup(trg.primaryPopup); var menu = trg.closest("menu"), newVal = trg.val; this.maybeClosePopup(e, menu); if (newVal != menu.pref.val) menu.pref.set(menu.pref.pref, newVal), this.maybeRe(menu, true); }, popupshowing(e, trg = e.target) { if (trg.state == "closed") return; if (trg.id) { for(var node of trg.children) { if (node.nodeName.endsWith("r")) continue; this.upd(node); !e && node.open && this.popupshowing(null, node.querySelector("menupopup")); } return; } var {pref} = trg.closest("menu"), findChecked = true; var findDef = "defVal" in pref; var checked = trg.querySelector("[checked]"); if (checked) { if (checked.val == pref.val) { if (findDef) findChecked = false; else return; } else checked.removeAttribute("checked"); } if (findDef) { var def = trg.querySelector("menuitem:not([style*=font-style]"); if (def) if (def.val == pref.defVal) { if (findChecked) findDef = false; else return; } else def.style.setProperty("font-style", "italic", "important"); } for(var node of trg.children) if ("val" in node) { if (findChecked && node.val == pref.val) { node.setAttribute("checked", true); if (findDef) findChecked = false; else break; } if (findDef && node.val == pref.defVal) { node.style.removeProperty("font-style"); if (findChecked) findDef = false; else break; } } }, contextmenu(e) { var trg = e.target; if (trg.btn) { if (e.ctrlKey || e.shiftKey) return; if (e.detail == 2) return trg.secondaryPopup.hidePopup(); this.openPopup(trg.secondaryPopup); } else if ("pref" in trg) { this.maybeClosePopup(e, trg); if (trg.pref.user) prefs.clearUserPref(trg.pref.pref), this.maybeRe(trg); } e.preventDefault(); }, click(e) { if (e.button) return; var trg = e.target, {pref} = trg; if (!pref) return; this.maybeClosePopup(e, trg); if (!("noAlt" in pref)) return; if (pref.val == pref.userChoice) if (pref.noAlt) return; else pref.set(pref.pref, pref.userAlt); else pref.set(pref.pref, pref.userChoice); this.maybeRe(trg); } }; });
Отредактировано Dobrov (17-02-2022 11:11:09)
Отсутствует
насколько я понял, в CustomStylesScripts.jsm нет возможности подключать jsm-скрипты ?
scriptsbackground: [ // В фоне [System Principal] { func: 'ChromeUtils.import("chrome://user_chrome_files/content/custom_scripts/xxxxxxxx.jsm");', },
«The Truth Is Out There»
Отсутствует
но сброшенная опция "Многопоточный режим вкладок" не выбирается!
Что я понимаю не так? 97.0 Добавил опцию в свой файл, т.к. не пользуюсь и сделал видео (лежит на ЯД). ЛКМ - красный, ПКМ - синий.
Отредактировано xrun1 (17-02-2022 15:22:12)
Отсутствует
Перелопатил форум на предмет скрита auto_hide_sidebar.uc.js, оказывается для userChromeJS его не так-то просто подключить.
Собрал до кучи из примеров, теперь он автономен и можно просто положит в папку crome с именем auto_hide_sidebar.uc.js или подключить в user_chrome_files, auto_hide_sidebar.css больше отдельно не нужен.
data:application/x-javascript;base64,Ly8gPT1Vc2VyU2NyaXB0PT0KLy8gQG5hbWUJQXV0byBIaWRlIFNpZGViYXIKLy8gQGF1dGhvcglWaXRhbGl5IFYuCi8vIEBpbmNsdWRlCW1haW4KLy8gQHNodXRkb3duCXRoaXMuYXV0b2hpZGVzaWRlYmFyLmRlc3RydWN0b3IoKTsKLy8gQG5vdGUJaHR0cHM6Ly9naXRodWIuY29tL1ZpdGFsaXlWc3R5bGUvVml0YWxpeVZzdHlsZS5naXRodWIuaW8vdHJlZS9tYXN0ZXIvc3R5bGVzZmYvdXNlcl9jaHJvbWVfZmlsZXMvCi8vIEBvbmx5b25jZQovLyA9PS9Vc2VyU2NyaXB0PT0KCih0aGlzLmF1dG9oaWRlc2lkZWJhciA9IHsKCXNpZGViYXI6IG51bGwsCgl0aW1lcjogbnVsbCwKCWRlbGF5OiBudWxsLAoJbGlzdGVuZXI6IG51bGwsCglldmVudHM6IFsiZHJhZ2VudGVyIiwgImRyb3AiLCAiZHJhZ2V4aXQiLCAiTW96TGF5ZXJUcmVlUmVhZHkiLCAibW91c2VlbnRlciIsICJtb3VzZWxlYXZlIl0sCglnZXQgdW5sb2FkbGlzdGVuZXJzKCkgewoJCWRlbGV0ZSB0aGlzLnVubG9hZGxpc3RlbmVyczsKCQl3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigidW5sb2FkIiwgdGhpcywgeyBvbmNlOiB0cnVlIH0pOwoJCXJldHVybiB0aGlzLnVubG9hZGxpc3RlbmVycyA9IFtdOwoJfSwKCWluaXQoKSB7CgkJdmFyIHNpZGViYXIgPSB0aGlzLnNpZGViYXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIjc2lkZWJhci1ib3giKTsKCQlpZiAoIXNpZGViYXIpIHJldHVybjsKCQlmb3IgKGxldCB0eXBlIG9mIHRoaXMuZXZlbnRzKQoJCQlzaWRlYmFyLmFkZEV2ZW50TGlzdGVuZXIodHlwZSwgdGhpcyk7CgkJdGhpcy51bmxvYWRsaXN0ZW5lcnMucHVzaCgiYXV0b2hpZGVzaWRlYmFyIik7CgkJdmFyIHBvcHVwID0gdGhpcy5wb3B1cCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIiNzaWRlYmFyTWVudS1wb3B1cCIpOwoJCWlmICghcG9wdXApIHJldHVybjsKCQlwb3B1cC5hZGRFdmVudExpc3RlbmVyKCJwb3B1cHNob3dpbmciLCB0aGlzKTsKCQlsZXQgc3R5bGUgPSB0aGlzLnN0eWxlCgkJdmFyIHNzcyA9IENjWydAbW96aWxsYS5vcmcvY29udGVudC9zdHlsZS1zaGVldC1zZXJ2aWNlOzEnXS5nZXRTZXJ2aWNlKENpLm5zSVN0eWxlU2hlZXRTZXJ2aWNlKTsKCQlsZXQgbmV3VVJJUGFyYW0gPSB7CgkJCWFVUkw6ICdkYXRhOnRleHQvY3NzLCcgKyBlbmNvZGVVUklDb21wb25lbnQoc3R5bGUpLAoJCQlhT3JpZ2luQ2hhcnNldDogbnVsbCwKCQkJYUJhc2VVUkk6IG51bGwKCQl9CgkJbGV0IGNzc1VyaSA9IFNlcnZpY2VzLmlvLm5ld1VSSShuZXdVUklQYXJhbS5hVVJMLAoJCQkJCQluZXdVUklQYXJhbS5hT3JpZ2luQ2hhcnNldCwKCQkJCQkJbmV3VVJJUGFyYW0uYUJhc2VVUkkpOwoJCXNzcy5sb2FkQW5kUmVnaXN0ZXJTaGVldChjc3NVcmksIHNzcy5BR0VOVF9TSEVFVCk7Cgl9LAoJZGVzdHJ1Y3RvcigpIHsKCQl2YXIgc2lkZWJhciA9IHRoaXMuc2lkZWJhcjsKCQlmb3IgKGxldCB0eXBlIG9mIHRoaXMuZXZlbnRzKQoJCQlzaWRlYmFyLnJlbW92ZUV2ZW50TGlzdGVuZXIodHlwZSwgdGhpcyk7CgkJaWYgKCF0aGlzLnBvcHVwKSByZXR1cm47CgkJdGhpcy5wb3B1cC5yZW1vdmVFdmVudExpc3RlbmVyKCJwb3B1cHNob3dpbmciLCB0aGlzKTsKCX0sCgloYW5kbGVFdmVudChlKSB7CgkJdGhpc1tlLnR5cGVdKGUpOwoJfSwKCU1vekxheWVyVHJlZVJlYWR5KGUpIHsKCQlpZiAoZS5vcmlnaW5hbFRhcmdldD8uaWQgPT0gIndlYmV4dC1wYW5lbHMtYnJvd3NlciIgJiYgIXRoaXMuc2lkZWJhci5oYXNBdHRyaWJ1dGUoInNpZGViYXJkcmFnIikpIHsKCQkJd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoIm1vdXNlZG93biIsICgpID0+IHsKCQkJCXRoaXMuZHJvcCgpOwoJCQl9LCB7IG9uY2U6IHRydWUgfSk7CgkJCXRoaXMuZHJhZ2VudGVyKCk7CgkJfQoJfSwKCWNsaWNrOiBmdW5jdGlvbihldmVudCkgewoJCXZhciBzaWRlYmFyID0gdGhpcy5zaWRlYmFyOwoJCXZhciBib3hPYmogPSBzaWRlYmFyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLCBib3hTY3JuID0gIXNpZGViYXIuYm94T2JqZWN0ID8gc2lkZWJhciA6IHNpZGViYXIuYm94T2JqZWN0OwoJCWlmIChldmVudC5zY3JlZW5ZIDwgYm94U2Nybi5zY3JlZW5ZIHx8IGV2ZW50LnNjcmVlblk+IGJveFNjcm4uc2NyZWVuWSArIGJveE9iai5oZWlnaHQgfHwgZXZlbnQuc2NyZWVuWCA8IGJveFNjcm4uc2NyZWVuWHx8IGV2ZW50LnNjcmVlblggPiBib3hTY3JuLnNjcmVlblggKyBib3hPYmoud2lkdGgpIHsKCQkJd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoImNsaWNrIiwgdGhpcywgZmFsc2UpOwoJCQl0aGlzLmxpc3RlbmVyID0gZmFsc2U7CgkJCWlmIChzaWRlYmFyLmhhc0F0dHJpYnV0ZSgic2lkZWJhcmRyYWciKSkKCQkJCXNpZGViYXIucmVtb3ZlQXR0cmlidXRlKCJzaWRlYmFyZHJhZyIpOwoJCX0KCX0sCgltb3VzZWVudGVyOiBmdW5jdGlvbigpIHsKCQl2YXIgc2lkZWJhciA9IHRoaXMuc2lkZWJhcjsKCQlpZiAoIXNpZGViYXIuaGFzQXR0cmlidXRlKCJzaWRlYmFyZHJhZyIpICYmICF0aGlzLmxpc3RlbmVyKSB7CgkJCWNsZWFyVGltZW91dCh0aGlzLnRpbWVyKTsKCQkJdmFyIGRlbGF5ID0gdGhpcy5kZWxheSB8fCAodGhpcy5kZWxheSA9ICtnZXRDb21wdXRlZFN0eWxlKHNpZGViYXIpLmdldFByb3BlcnR5VmFsdWUoInRyYW5zaXRpb24tZGVsYXkiKS5yZXBsYWNlKC9bXjAtOVwuXS9nLCAiIikgKiAxMDAwKTsKCQkJdGhpcy50aW1lciA9IHNldFRpbWVvdXQoKCkgPT4gewoJCQkJc2lkZWJhci5zZXRBdHRyaWJ1dGUoInNpZGViYXJkcmFnIiwgInRydWUiKTsKCQkJCXRoaXMubGlzdGVuZXIgPSB0cnVlOwoJCQkJd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIiwgdGhpcywgZmFsc2UpOwoJCQl9LCBkZWxheSk7CgkJfQoJfSwKCW1vdXNlbGVhdmU6IGZ1bmN0aW9uKCkgewoJCWNsZWFyVGltZW91dCh0aGlzLnRpbWVyKTsKCX0sCglwb3B1cHNob3dpbmcoKSB7CgkJdGhpcy5wb3B1cC5hZGRFdmVudExpc3RlbmVyKCJwb3B1cGhpZGRlbiIsICgpID0+IHsKCQkJdGhpcy5kcm9wKCk7CgkJfSwgeyBvbmNlOiB0cnVlIH0pOwoJCXRoaXMuZHJhZ2VudGVyKCk7Cgl9LAoJZHJhZ2VudGVyKCkgewoJCWlmICghdGhpcy5zaWRlYmFyLmhhc0F0dHJpYnV0ZSgic2lkZWJhcmRyYWciKSkKCQkJdGhpcy5zaWRlYmFyLnNldEF0dHJpYnV0ZSgic2lkZWJhcmRyYWciLCAidHJ1ZSIpOwoJfSwKCWRyb3AoKSB7CgkJaWYgKHRoaXMuc2lkZWJhci5oYXNBdHRyaWJ1dGUoInNpZGViYXJkcmFnIikpCgkJCXRoaXMuc2lkZWJhci5yZW1vdmVBdHRyaWJ1dGUoInNpZGViYXJkcmFnIik7Cgl9LAoJZHJhZ2V4aXQoZSkgewoJCXZhciBzaWRlYmFyID0gdGhpcy5zaWRlYmFyOwoJCXZhciBib3hPYmogPSBzaWRlYmFyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLCBib3hTY3JuID0gIXNpZGViYXIuYm94T2JqZWN0ID8gc2lkZWJhciA6IHNpZGViYXIuYm94T2JqZWN0OwoJCWlmICgoIWUucmVsYXRlZFRhcmdldCB8fCBlLnNjcmVlblkgPD0gKGJveFNjcm4uc2NyZWVuWSArIDUpIHx8IGUuc2NyZWVuWT49IChib3hTY3JuLnNjcmVlblkgKyBib3hPYmouaGVpZ2h0IC0gNSkKCQkJfHwgZS5zY3JlZW5YIDw9IChib3hTY3JuLnNjcmVlblggKyA1KSB8fCBlLnNjcmVlblggPj0gKGJveFNjcm4uc2NyZWVuWCArIGJveE9iai53aWR0aCAtIDUpKQoJCQkmJiBzaWRlYmFyLmhhc0F0dHJpYnV0ZSgic2lkZWJhcmRyYWciKSkKCQkJc2lkZWJhci5yZW1vdmVBdHRyaWJ1dGUoInNpZGViYXJkcmFnIik7Cgl9LAoJc3R5bGU6IGBALW1vei1kb2N1bWVudCB1cmwoImNocm9tZTovL2Jyb3dzZXIvY29udGVudC9icm93c2VyLnhodG1sIikgewoJCQkjc2lkZWJhci1ib3ggewoJCQkJLS12LXNpZGViYXItbWluLXdpZHRoOiAycHg7CgkJCQktLXYtc2lkZWJhci1taW4td2lkdGgtbm9ybWFsOiA1cHg7CgkJCQktLXYtc2lkZWJhci1tYXgtd2lkdGg6IDMwZW07CgkJCQktLXYtc2lkZWJhci10cmFuc2l0aW9uLWRlbGF5LXNob3c6IC4zczsKCQkJCS0tdi1zaWRlYmFyLXRyYW5zaXRpb24tZGVsYXktaGlkZTogLjZzOwoJCQkJLS12LXNpZGViYXItdHJhbnNpdGlvbi1kdXJhdGlvbjogLjNzOwoJCQkgLyogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqLwoKCQkJIHBvc2l0aW9uOiByZWxhdGl2ZSAhaW1wb3J0YW50OwoJCQkgei1pbmRleDogMiAhaW1wb3J0YW50OwoJCQkgbWluLXdpZHRoOiB2YXIoLS12LXNpZGViYXItbWF4LXdpZHRoKSAhaW1wb3J0YW50OwoJCQkgd2lkdGg6IHZhcigtLXYtc2lkZWJhci1tYXgtd2lkdGgpICFpbXBvcnRhbnQ7CgkJCSBtYXgtd2lkdGg6IHZhcigtLXYtc2lkZWJhci1tYXgtd2lkdGgpICFpbXBvcnRhbnQ7CgkJCSBvdmVyZmxvdzogaGlkZGVuICFpbXBvcnRhbnQ7CgkJCSBvcGFjaXR5OiAwICFpbXBvcnRhbnQ7CgkJCSAtLXYtc2lkZWJhci1tYXJnaW4tbWF4LXdpZHRoOiBjYWxjKC0xICogdmFyKC0tdi1zaWRlYmFyLW1heC13aWR0aCkpOwoJCQkgLS12LXNpZGViYXItdHJhbnNmb3JtLWxvY2FsZS1kaXI6IC0xOwoJCQkgLS12LXNpZGViYXItdHJhbnNmb3JtLWxvY2FsZS1kaXItdmlzaWJsZTogMTsKCQkJIG1hcmdpbi1pbmxpbmUtc3RhcnQ6IDAgIWltcG9ydGFudDsKCQkJIG1hcmdpbi1pbmxpbmUtZW5kOiB2YXIoLS12LXNpZGViYXItbWFyZ2luLW1heC13aWR0aCkgIWltcG9ydGFudDsKCQkJIGJvcmRlcjogbm9uZSAhaW1wb3J0YW50OwoJCQkgYm9yZGVyLWlubGluZS1lbmQ6IDFweCBzb2xpZCB2YXIoLS1zaWRlYmFyLWJvcmRlci1jb2xvciwgVGhyZWVEU2hhZG93KSAhaW1wb3J0YW50OwoJCQkgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKGNhbGModmFyKC0tdi1zaWRlYmFyLXRyYW5zZm9ybS1sb2NhbGUtZGlyKSAqICh2YXIoLS12LXNpZGViYXItbWF4LXdpZHRoKSAtIHZhcigtLXYtc2lkZWJhci1taW4td2lkdGgpKSkpICFpbXBvcnRhbnQ7CgkJCSB0cmFuc2l0aW9uLXRpbWluZy1mdW5jdGlvbjogbGluZWFyLCBzdGVwLXN0YXJ0ICFpbXBvcnRhbnQ7CgkJCSB0cmFuc2l0aW9uLWRlbGF5OiB2YXIoLS12LXNpZGViYXItdHJhbnNpdGlvbi1kZWxheS1oaWRlKSwgY2FsYyh2YXIoLS12LXNpZGViYXItdHJhbnNpdGlvbi1kZWxheS1oaWRlKSArIHZhcigtLXYtc2lkZWJhci10cmFuc2l0aW9uLWR1cmF0aW9uKSkgIWltcG9ydGFudDsKCQkJIHRyYW5zaXRpb24tZHVyYXRpb246IHZhcigtLXYtc2lkZWJhci10cmFuc2l0aW9uLWR1cmF0aW9uKSwgMHMgIWltcG9ydGFudDsKCQkJIHRyYW5zaXRpb24tcHJvcGVydHk6IHRyYW5zZm9ybSwgb3BhY2l0eSAhaW1wb3J0YW50OwoJCSB9CgkJICNzaWRlYmFyLWJveFtwb3NpdGlvbmVuZD0idHJ1ZSJdIHsKCQkJIG1hcmdpbi1pbmxpbmUtc3RhcnQ6IHZhcigtLXYtc2lkZWJhci1tYXJnaW4tbWF4LXdpZHRoKSAhaW1wb3J0YW50OwoJCQkgbWFyZ2luLWlubGluZS1lbmQ6IDAgIWltcG9ydGFudDsKCQkJIGJvcmRlci1pbmxpbmUtc3RhcnQ6IDFweCBzb2xpZCB2YXIoLS1zaWRlYmFyLWJvcmRlci1jb2xvciwgVGhyZWVEU2hhZG93KSAhaW1wb3J0YW50OwoJCQkgYm9yZGVyLWlubGluZS1lbmQ6IG5vbmUgIWltcG9ydGFudDsKCQkgfQoJCSAjc2lkZWJhci1ib3hbcG9zaXRpb25lbmQ9InRydWUiXTotbW96LWxvY2FsZS1kaXIobHRyKSwKCQkgI3NpZGViYXItYm94Om5vdChbcG9zaXRpb25lbmQ9InRydWUiXSk6LW1vei1sb2NhbGUtZGlyKHJ0bCkgewoJCQkgLS12LXNpZGViYXItdHJhbnNmb3JtLWxvY2FsZS1kaXI6IDE7CgkJCSAtLXYtc2lkZWJhci10cmFuc2Zvcm0tbG9jYWxlLWRpci12aXNpYmxlOiAtMTsKCQkgfQoJCSA6cm9vdFt2X3ZlcnRpY2FsX2Jhcl9hdXRvaGlkZV1bdl92ZXJ0aWNhbF9iYXJfc2lkZWJhcj0idHJ1ZSJdICNzaWRlYmFyLWJveDpub3QoOmhvdmVyLFtzaWRlYmFyZHJhZ10pLAoJCSA6cm9vdFt2X3ZlcnRpY2FsX2Jhcl9hdXRvaGlkZV06bm90KFt2X3ZlcnRpY2FsX2Jhcl9zaWRlYmFyXSkgI3NpZGViYXItYm94Om5vdCg6aG92ZXIsW3NpZGViYXJkcmFnXSkgewoJCQkgdHJhbnNpdGlvbi1kZWxheTogMHMsIHZhcigtLXYtc2lkZWJhci10cmFuc2l0aW9uLWR1cmF0aW9uKSAhaW1wb3J0YW50OwoJCSB9CgkJIDpyb290W3NpemVtb2RlPSJub3JtYWwiXSAjc2lkZWJhci1ib3ggewoJCQkgLS12LXNpZGViYXItbWluLXdpZHRoOiB2YXIoLS12LXNpZGViYXItbWluLXdpZHRoLW5vcm1hbCkgIWltcG9ydGFudDsKCQkgfQoJCSAjc2lkZWJhci1ib3g6aG92ZXIsCgkJICNzaWRlYmFyLWJveFtzaWRlYmFyZHJhZ10gewoJCQkJCQl0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoMHB4KSAhaW1wb3J0YW50OwoJCQkgb3BhY2l0eTogMSAhaW1wb3J0YW50OwoJCQkgdHJhbnNpdGlvbi1kZWxheTogdmFyKC0tdi1zaWRlYmFyLXRyYW5zaXRpb24tZGVsYXktc2hvdykgIWltcG9ydGFudDsKCQkgfQoJCSA6cm9vdFt2X3ZlcnRpY2FsX2Jhcl92aXNpYmxlXVt2X3ZlcnRpY2FsX2Jhcl9zdGFydD0idHJ1ZSJdICNzaWRlYmFyLWJveDpub3QoW3Bvc2l0aW9uZW5kPSJ0cnVlIl0pLAoJCSA6cm9vdFt2X3ZlcnRpY2FsX2Jhcl92aXNpYmxlXVt2X3ZlcnRpY2FsX2Jhcl9zdGFydD0iZmFsc2UiXSAjc2lkZWJhci1ib3hbcG9zaXRpb25lbmQ9InRydWUiXSB7CgkJCSB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoY2FsYyh2YXIoLS12LXNpZGViYXItdHJhbnNmb3JtLWxvY2FsZS1kaXItdmlzaWJsZSkgKiB2YXIoLS12LXZlcnRpY2FsX2Jhcl93aWR0aCwgMHB4KSkpICFpbXBvcnRhbnQ7CgkJCSBvcGFjaXR5OiAxICFpbXBvcnRhbnQ7CgkJCSB0cmFuc2l0aW9uLWRlbGF5OiAwcyAhaW1wb3J0YW50OwoJCSB9CgkJICNicm93c2VyID4gI3NpZGViYXItc3BsaXR0ZXIgewoJCQkgZGlzcGxheTogbm9uZSAhaW1wb3J0YW50OwoJCSB9CgkJICNzaWRlYmFyLWJveCA+ICNzaWRlYmFyIHsKCQkJIG1pbi13aWR0aDogMCAhaW1wb3J0YW50OwoJCQkgd2lkdGg6IGF1dG8gIWltcG9ydGFudDsKCQkJIG1heC13aWR0aDogbm9uZSAhaW1wb3J0YW50OwoJCQkgLW1vei1ib3gtZmxleDogMSAhaW1wb3J0YW50OwoJCSB9CgkJIH1gCn0pLmluaXQodGhpcyk7Cg==
Жизнь иногда такое выкидывает, что хочется подобрать...
Отсутствует
для userChromeJS
скрипт ваш неправильный во первых он скорее всего не работает в таком виде в userChromeJS разве что там есть массив unloadlisteners, я не курсе
ну и loadAndRegisterSheet не для использования в оконных скриптах тем более без проверки загружен уже стиль или нет, лучше заменить хотя бы на windowUtils.loadSheetUsingURIString(string, type);
понятно что в ваших .uc.js скриптах loadAndRegisterSheet часто присутствует но это не значит что надо тоже такое городить.
или подключить в user_chrome_files
вот это совсем лишнее учитывая что он там уже присутствует по умолчанию и с нормальной (кешированной) загрузкой стиля
Добавлено 17-02-2022 20:17:21
насколько я понял, в CustomStylesScripts.jsm нет возможности подключать jsm-скрипты ?
Как вариант добавить перед строкой var UcfStylesScripts = {
эту
var jsmImport = path => `ChromeUtils.import("chrome://user_chrome_files/content/custom_scripts/${path}.jsm")`;
и далее добавлять названия скриптов или путь/название
scriptsbackground: [ // В фоне [System Principal]
{ func: jsmImport("path/scriptName"), },
Отредактировано Vitaliy V. (17-02-2022 20:20:37)
Отсутствует
Dobrov
Ну тут бабка надвое сказала, мне например, ваши комбайны, с кучей кликов, совсем не кажутся удобными и жесты мне неудобны. Но это не значит, что я против, я вижу что многим жесты нравятся. А вот массив кликов, ну это как в играх, например в Devil May Cry я ни при каком раскладе играть не буду, а ваши решения напоминают боевку этой игры.
насколько я понял, в CustomStylesScripts.jsm нет возможности подключать jsm-скрипты
Dumby же давал загрузчик:
(async url => ChromeUtils.import(url))( "chrome://user_chrome_files/content/custom_scripts/scriptName" ); (async url => ChromeUtils.import(url))( "chrome://user_chrome_files/content/custom_scripts/scriptName" );
scriptsbackground: [ // В фоне [System Principal] ... { path: "custom_js/name.js", },
Отредактировано _zt (18-02-2022 00:07:30)
Отсутствует
Как вариант добавить var jsmImport = path =>
Не работает на скрипте "Замена текста в имени вкладки", у которого надо грузить функцию, я попробовал перенести код, но не получилось:
Как исправить код, чтобы он грузил обычный jsm и jsm с функцией, которая выполнится при загрузке скрипта ?
var jsmImport = (name, funcName) => ` // подключить jsm [выполнить функцию] var {href, pathname} = new URL("chrome://user_chrome_files/content/custom_scripts/${name}"); var obj = ChromeUtils.import(href); funcName && obj[funcName](); `; { func: jsmImport("UCFTitleChangedChild.jsm", "registerUCFTitleChanged"), },
var EXPORTED_SYMBOLS = ["registerUCFTitleChanged", "UCFTitleChangedChild"]; var reg = /-\sПоиск\sв\sGoogle$| \| Форум Mozilla Россия$|^Смотреть дораму |^Смотреть бесплатно дораму |^Сериал \| Фильм | - DoramaTV/; var hosts = ["https://www.google.com/search?*", "https://www.google.ru/search?*", "https://doramatv.live/*", "https://forum.mozilla-russia.org"]; function registerUCFTitleChanged() { // исправление заголовка вкладки ChromeUtils.registerWindowActor("UCFTitleChanged", { child: { moduleURI: "chrome://user_chrome_files/content/custom_scripts/UCFTitleChangedChild.jsm", events: { DOMTitleChanged: { capture: true }, }, }, matches: hosts, messageManagerGroups: ["browsers"], }); } class UCFTitleChangedChild extends JSWindowActorChild { handleEvent(e) { if (reg.test(this.document.title)) this.document.title = this.document.title.replace(reg, ""); } }
var loadscript = (name, funcName) => { try { var {href, pathname} = new URL(`chrome://user_chrome_files/content/custom_scripts/${name}`); if (/\.jsm$/i.test(pathname)) { var obj = ChromeUtils.import(href); funcName && obj[funcName](); } else Services.scriptloader.loadSubScript(href); return true; } catch(ex) {Cu.reportError(ex);} } loadscript("ucf_aom-button.js"); loadscript("UCFTitleChangedChild.jsm", "registerUCFTitleChanged");
Отсутствует
Dumby - Просьба убрать longPress из скрипта перехвата кликов - я пробовал, но срабатывает и обычный и двойной клик сразу…
После длительного юзания неудобство в том, что при нажатии кнопок действие происходит с задержкой в пол-секунды. Можно ли переделать код на стандартные события click, doubleclick, wheel — чтобы действие при нажатии кнопок выполнялось сразу?
Преимущество твоего кода в том, что легко можно прописать клики для любых кнопок панели инструментов, а в более простом примере на форуме нет разбора по #id нажатых кнопок и нет скролла…
Можешь набросать только часть кода для перехвата кликов/$id кнопок ? (я сам переделаю скрипт по ссылке)
Нужно обычный и двойной клик кнопок мыши, колёсико и разбор событий по кнопка, как в вышеуказанном коде:
data = { "#downloads-button": { mousedownTarget: true, 2(trg, forward) { bright(trg, forward); // яркость по wheel ± }, 128() { saveSelectionToTxt();}, // СКМ Click 260(btn) { // Double ПКМ Click
Отсутствует
Не работает на скрипте "Замена текста в имени вкладки", у которого надо грузить функцию
и в чем проблема, не надо там ничего переделывать с функцией jsmImport
{ func: `${jsmImport("UCFTitleChangedChild")}.registerUCFTitleChanged();`, },
Добавлено 18-02-2022 13:55:47
Но работает в custom_script_win.js
это же опечатка или действительно в win запускаешь?
Отредактировано Vitaliy V. (18-02-2022 13:55:47)
Отсутствует
это же опечатка или действительно в win запускаешь?
Спасибо! Но в будущих версиях UCF возможно сделать подключение jsm-скриптов попроще? Без всяких `` кавычек, так, как для js сделано ?
Было так и имена вкладок менялись, но сейчас прописал правильно в CustomStylesScripts.jsm:
scriptsbackground: [ // В фоне [System Principal]
Отредактировано Dobrov (18-02-2022 15:31:52)
Отсутствует
del
Отредактировано Vitaliy V. (14-04-2022 01:32:38)
Отсутствует
Dumby - В скрипте "Simple Session Manager" одна иконка прописана 2 раза. Как сократить код и передать её как переменную в regStyle() ?
onCreated(btn) { ………… btn.setAttribute("image", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8………… regStyle() { ………… #${pid} > menu { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8……………
Кроме того, восстановление сессий в новые вкладки с кликом средней кнопки + Ctrl не очень удобно, добавил для этого пункт меню: "Восстановить в новых вкладках"
А вообще для восстановления удобнее сразу кликать по имени сохранённой сесии (и восстанавливать в новых вкладках при клике с нажатым Ctrl), а в подменю оставить только: Переименовать и Удалить.
// https://forum.mozilla-russia.org/viewtopic.php?pid=798085#p798085 (async (pid, mp) => CustomizableUI.createWidget(({ id: "797321", label: "Simple Session Manager", tooltiptext: "Управление сессиями", localized: false, init() { this.handleEvent = e => this[e.type](e); this.onTimeout = () => this.saveSession() || this.save(); Services.obs.addObserver(this, "quit-application"); var {openMenu} = this; this.render = function() { this.openMenu = openMenu; this.constructor.prototype.render.call(this); } delete this.init; return this; }, onCreated(btn) { btn.type = "menu"; btn.phTimestamp = 0; btn.render = this.render; btn._handleClick = this.click; // btn.setAttribute("image", "chrome://user_chrome_files/content/custom_styles/svg/download-resume.svg"); btn.setAttribute("image", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEnQAABJ0BfDRroQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGxSURBVDiNnZE/T1NRGMZ/7zn3lmKLkIKpaUxZFINEJZ0YHXRwcnBxMQ6aOJi4+FH8Dm5OOjA4+AEYGCTRook1JlVIVUrbW/rnPg63UtReIr7bOXmf5/ye59jDlanHS3O+wn/Mu+/DF8HFeVe5f+vaPTdfPpF4UNvk6frmhwAvXOEsvrR0IoN47xM4CHCADmDQBkAHbdTrTBRZdgYLs6NTD/MiMC+gC8MO6ke8ffWsXv3S3JpksHouv7Z4/UEeM8z6IwKfEGjYRt0G1d3m1p3n0Y1JBi/vTtfKw1Yec2CHBDFmXYjboAgL4tTc5pXsmcNcDxIDUFQHuqgfYT69OAuE9qqAoX4jIcAL7b9H+0deOYYg3tkYXxx2EAo7dQYEBF/TEULD5oow7KHut18RhGVD3GwxMZ36YWn6IJd37vQCSMSNBpYQCMs43PQMAJXlwtr6k7CGfo9iznN1ebGY7Ak1NSJwYERYJgM+Q+nClVzp/OXc3wWMwdT+jAVKCMwLC2PUeoMrrEI4m94BQq0a6mxjoca/YKFgUCfeqR8jPhoHcIAHe3ST2+UFLv2T8o/5uMvrnx9Wn65p5nMEAAAAAElFTkSuQmCC"); var popup = btn.ownerDocument.createXULElement("menupopup"); popup.filler = this; popup.id = pid; popup.setAttribute("onpopupshowing", "event.defaultPrevented || filler.fill(event)"); btn.prepend(popup); btn.addEventListener("mousedown", this); popup.addEventListener("command", this); btn.ownerGlobal.addEventListener("unload", () => { btn.removeEventListener("mousedown", this); popup.removeEventListener("command", this); if (popup.filler != this) popup.removeEventListener("dragstart", this), popup.removeEventListener("popuphidden", this); }, {once: true}); }, openMenu(arg) { var pos; if (this.matches(".widget-overflow-list > :scope")) pos = "after_start"; else var win = this.ownerGlobal, {width, height, top, bottom, left, right} = this.closest("toolbar").getBoundingClientRect(), pos = width > height ? `${win.innerHeight - bottom > top ? "after" : "before"}_start` : `${win.innerWidth - right > left ? "end" : "start"}_before`; this.firstChild.setAttribute("position", pos); delete this.openMenu; this.openMenu(arg); }, mousedown(e) { if (e.button) return; var trg = e.target; if (trg.nodeName.startsWith("t")) { trg.mdTimestamp = Cu.now(); trg.tid = e.view.setTimeout(this.onTimeout, 500); return e.preventDefault(); } e.detail == 2 && trg.nodeName == "menu" && this.boot(trg); }, boot(trg) { var popup = trg.parentNode; var old = popup.querySelector("[boot]"); if (old != trg) old?.removeAttribute("boot"); trg.toggleAttribute("boot"); popup.dblMD = true; }, click() { var win = this.ownerGlobal; if (win.event.target != this) return; win.clearTimeout(this.tid); if (this.mdTimestamp - this.phTimestamp > 50) this.open = true; }, command(e) { var arg, trg = e.target, cmd = trg.value; if (cmd.startsWith("r")) { arg = trg.parentNode.parentNode.label; if (cmd.startsWith("res")) return this[cmd](arg, (trg.label.indexOf("вклад")>0) && e.view); // Восстановить в новых вкладках } this[cmd](arg) || this.save(); }, dragstart(e) { var trg = e.target; if (trg.nodeName != "menu") return; var popup = trg.parentNode; this.dragData = {trg, mouse: true}; trg.menupopup.hidePopup(); var win = trg.ownerGlobal; win.setCursor("grabbing"); var {width} = trg.getBoundingClientRect(); trg.setAttribute("maxwidth", width); win.addEventListener("mouseup", this); popup.addEventListener("mousemove", this); }, mousemove(e) { var trg = e.target, dtrg = this.dragData.trg; if (trg == dtrg || trg.nodeName != "menu") return; e.movementY > 0 ? trg.nextSibling != dtrg && trg.after(dtrg) : trg.previousSibling != dtrg && trg.before(dtrg); }, mouseup(arg) { if (arg.constructor.isInstance?.(arg)) { arg.preventDefault(); var {trg} = this.dragData; this.dragData.mouse = false; } else var trg = arg; trg.removeAttribute("maxwidth"); trg.ownerGlobal.setCursor("auto"); trg.ownerGlobal.removeEventListener("mouseup", this); trg.parentNode.removeEventListener("mousemove", this); }, popuphidden(e) { if (!e.target.id) return; e.view.removeEventListener("keydown", this, true); var popup = e.target; popup.parentNode.phTimestamp = Cu.now(); if (!this.dragData && !popup.dblMD) return; var save; if (this.dragData) { var {trg, mouse} = this.dragData; mouse && this.mouseup(trg); delete this.dragData; var order = Array.from(popup.getElementsByTagName("menu"), m => m.label); if (order.toString() != this.meta.order.toString()) { var hasBoot = this.meta.boot != null; if (hasBoot) var bootName = this.meta.order[this.meta.boot]; this.meta.order = order; if (hasBoot) this.meta.boot = this.meta.order.indexOf(bootName); save = true; } } if (popup.dblMD) { delete popup.dblMD; var {boot} = this.meta; var bootNode = e.target.querySelector("[boot]"); var ind = bootNode && this.meta.order.indexOf(bootNode.label); if (ind != boot) this.meta.boot = ind, save = true; } save && this.save(e.view); }, sku: `#${pid} > menu[maxwidth]`, skd: `#${pid} > menu:is([maxwidth],[_moz-menuactive]):not([open])`, keydown(e) { if (e.repeat && e.key == "Shift" || !e.shiftKey) return; var func = this.keyHandlers[e.key]; if (!func) return; var menu = e.view.windowRoot .ownerGlobal.document.querySelector(this.skd); if (menu) e.stopImmediatePropagation(), func.call(this, menu); }, keyup(e) { if (e.key != "Shift") return; var win = e.view.windowRoot.ownerGlobal; win.removeEventListener("keyup", this, true); win.document.querySelector(this.skd)?.removeAttribute("maxwidth"); }, keyHandlers: { Enter(menu) { this.boot(menu); }, ArrowDown(menu) { var ns = menu.nextSibling; if (ns) ns.after(menu), this.arrow(menu); }, ArrowUp(menu) { var ps = menu.previousSibling; if (ps.nodeName == "menu") ps.before(menu), this.arrow(menu); } }, arrow(menu) { if (menu.hasAttribute("maxwidth")) return; menu.setAttribute("maxwidth", menu.getBoundingClientRect().width); menu.ownerGlobal.addEventListener("keyup", this, true); this.dragData = {trg: menu}; }, fill(e) { var mxe = e.view.MozXULElement; var initFrag = mxe.parseXULToFragment(` <menuitem value="saveSession" class="menuitem-iconic" label="Сохранить сессию"/> <menuitem value="deleteAllSessions" class="menuitem-iconic" label="Удалить все сессии"/> <menuseparator/> `); this.menuFrag = mxe.parseXULToFragment(`<menu class="menu-iconic"><menupopup> <menuitem label="Восстановить" class="menuitem-iconic" value="restoreSession"/> <menuitem label="Восстановить в новых вкладках" class="menuitem-iconic" value="restoreSession"/> <menuitem label="Переименовать" class="menuitem-iconic" value="renameSession"/> <menuitem label="Удалить" class="menuitem-iconic" value="removeSession"/> </menupopup></menu>`); this.regStyle(); var filler = {fill: e => e.target.id ? e.view.addEventListener("keydown", this, true) || e.target.fillFlag || this.fillSessions(e.target) : this.dragData?.mouse && e.preventDefault() }; (this.fill = e => { var trg = e.target; trg.setAttribute("context", ""); trg.append(trg.ownerDocument.importNode(initFrag, true)); (trg.filler = filler).fill(e); trg.addEventListener("dragstart", this); trg.addEventListener("popuphidden", this); })(e); }, fillSessions(popup) { while(popup.lastChild.nodeName == "menu") popup.lastChild.remove(); var ind = 0, {boot} = this.meta; for(var name of this.meta.order) { var df = popup.ownerDocument.importNode(this.menuFrag, true); df.firstChild.setAttribute("label", name); if (ind++ == boot) df.firstChild.toggleAttribute("boot"); popup.append(df); } popup.fillFlag = true; }, regStyle() { delete this.regStyle; var subst = "ucf-ssm-style-resurl"; Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler).setSubstitution( subst, Services.io.newURI("data:text/css;charset=utf-8," + encodeURIComponent(` @-moz-document url-prefix(chrome://browser/content/browser.xhtml) { #${pid} > menu { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEnQAABJ0BfDRroQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGxSURBVDiNnZE/T1NRGMZ/7zn3lmKLkIKpaUxZFINEJZ0YHXRwcnBxMQ6aOJi4+FH8Dm5OOjA4+AEYGCTRook1JlVIVUrbW/rnPg63UtReIr7bOXmf5/ye59jDlanHS3O+wn/Mu+/DF8HFeVe5f+vaPTdfPpF4UNvk6frmhwAvXOEsvrR0IoN47xM4CHCADmDQBkAHbdTrTBRZdgYLs6NTD/MiMC+gC8MO6ke8ffWsXv3S3JpksHouv7Z4/UEeM8z6IwKfEGjYRt0G1d3m1p3n0Y1JBi/vTtfKw1Yec2CHBDFmXYjboAgL4tTc5pXsmcNcDxIDUFQHuqgfYT69OAuE9qqAoX4jIcAL7b9H+0deOYYg3tkYXxx2EAo7dQYEBF/TEULD5oow7KHut18RhGVD3GwxMZ36YWn6IJd37vQCSMSNBpYQCMs43PQMAJXlwtr6k7CGfo9iznN1ebGY7Ak1NSJwYERYJgM+Q+nClVzp/OXc3wWMwdT+jAVKCMwLC2PUeoMrrEI4m94BQq0a6mxjoca/YKFgUCfeqR8jPhoHcIAHe3ST2+UFLv2T8o/5uMvrnx9Wn65p5nMEAAAAAElFTkSuQmCC"); } #${pid} > [value=saveSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKVSURBVHjajFNNTBNREJ6+7na73bLbQn8I0BKNCYWKGr0oYoiJPxeNh6oHozcOxgSVi4le1JNHQRPigRsewURNPKiJMQicSISUACelRVJ2tz/bdktpy9adBzT8xTjJ5L35ezNv5hsLHEAv7noEntguChx7EuV8oTydKRhfno8kCnt9LTuFZ7f87mAz/8rnl86GOoOBBq+LQX1S1ioLs0txWdEmsulS38Phlcy+BwZ6W0L+JsfolcjpsFDnBKNcgQ193bRUwSrwQFgr6Dkd3o9NzilqMdI/FF+sPYCZ245I4zdunw9DtQr6LxlK6bVdpdrcPAiHfGBYLDD69ltUXsmfw0oIGoPNjkHMjMHa3J9asDyRpoyEOrQR0+dq5MxR0c29Rj3Bhvn8YjeWjZmN9cpWcApSkzpkptYg8T1FdWjTfysg1Ang9YtdT+80OogTbJc7OlsD+OftzOqsBrMflqHe6QKXIEL00zLV0UpSBbM/G9DeEQy6OXKJsfPsCbdXYjb0Yu2/nmMS9LSGYGlYpXLPkxCwkq1mR98Gn8Q4XexxYhhgYKf3TPTfRDaPqklkvViaSSpaxSpw/x1v5e0UG8W10k+iW8qfF2ZiccIydFQ7ScsXKO8ep4NiYj4ai6k5+Eoev1F1Wcn8QJDgnAnHbGYRWTh800cZ77Ryzmr6eCGXzYGiZCcQ2vQ32XT5PiIMTJBI4Waw1ZtZzLu7XaSMd1s9b9paKJA+vpuKqols3y4ov7wXaPN67GPXIl1hnDOOansyVicHhGHMzHkzeDKqqPnr/UOJxX3LNNDb5BJd3KC3Uexu7wgEGxq3limRqcxH47FVWRtPreYePBpJagdu4zYhwjx1cMFus59CuVgqTmPDDlrnvwIMAGS8IFCLagHpAAAAAElFTkSuQmCC"); } #${pid} [value=restoreSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAACzElEQVQ4jX2QPWwbZRjHf+/5vfPdObZjO3Ga2pVpGtxCP4QIDKgqDCDUNQwgJCS2qFI3hBCRCvXSCcTAAu0GY0Fi4kuq+IjUCpWAgCTq4IpS3Di2G8c+x/bZ57t7mSJFMfBf/3p+z+95BPvy3pufxqKmcVY3ZFFKmQtFGIReuNnrDze6lv5TqfSyx4EIgA/e+fzkZML6MDmVnD80mz1kxW3DMAxQCs/z6Hb6g3q1Xt1ttdfa7dbFN668vrkHkADJhPntufNnc0LTDi7AjFkkUknzcGF2LvCDuZVvfiwCj+/1GoAmhL3x6x2cZhsVqjFIGIZs15ts/LJOJCLt/Z0EiE3Y9eLpR1ONaoMH9zbHAGiC9FSKkwunWF1Z3RoDABhRg/zRPPmj+XHA/0QDaLectFLj6gcT+AHdTm9mzMC27e766lrWtCwy2Qz2hIUeNVDAaDCku9ujWW/ij3wsO9oaMzCiunf66TMU5gt4wyGbf1Upr5W5u15mq1JDhYqZQo6HIuqtueLw4vLXzwC89NZXeQFw/ePv7zx5buHEf6nf3qgMVipOGE0ko6EKhoQi3NnZ+c51BwsaQLOxM9N1uv86vNtz+aHSDn0pH9S2tl6r/Pn3s/VG/WYunzs/NZ2OSID0dKpRrzZS98v3kYbEsi1004BQcbtc9Q07bdYb229/dvmFL5aWVvVts9mq1Wo/e54vJIAQqGOPzQHgj3zcvos39BAIBshRqJQYjYZ/AFy79tQIeHVx+ctiIDRTA+g43Xud9q4PIHVJPBknk82QzqY5VZg2UUrEYhOX9s5aXL5RnMykb8Rj9kcC4OrSVZ1Hpt+PJ5PPz+SzR5KpyYRpGgRKMei7fHLr7lBmZ1XHcX4LgsCxLPt4JBLRm82Hr4j9DyuVSprdO/ZELGafkXpkXtPA94OK03Vv/R4/csEw5XOGbuieN6y6bv/S9XdfvPkPTgcoDlpQJpwAAAAASUVORK5CYII="); } #${pid} [value=renameSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPFJREFUeNrEU0sOgkAMbc1IIHoQT+KeY7hkBW5ccwLdsOICxI2X8peIGhggI21gggpCwsImM01f+tpOO0WlFIwR0efgeR5nsG0boihizPd91A5UwZDjuq5qwycwUkQYhttSr4Y4l76fDdtBEAQqz3OVZdnPQ09o2sQhrpBSQgnAen/qzLxZzljHcawxy7KAuCJNUyiKAm53SS0FBGQNlUW3lFO2iVCLYRhAXJEkCQPn65NGAswpL/4fWAebt1ZGXB3geHlw9maXsKqjS94CHNxF7xRM0/wKgI7jDBojvbnZAz3Gv/9E7NvGvmXCsev8EmAAWocA9ofpaRIAAAAASUVORK5CYII="); } #${pid} :is([value=removeSession], [value=deleteAllSessions]) { list-style-image: url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAABt0lEQVQ4ja2RT2sTURTFz8tk0nntFAQrVLBQxIUg/tkkMoLyIEVECHZhNrrxI+hOP5Mb6eBCcEipYIjZ2LpvhFasUtBSkwzOve+6mE6YSScuxLt67753fudyLvA/a7T+qCHmiTfrfWCMd3j9diPfq2SHX+uPnzJx71gP33w3bX9avBcE2j+SkK30Di7ffJ71VebMxD1hC2GGEEfH41prpftynIm92A0t2aYQQYgBThrndz/2KwCgf9Z2LNtImFOAtc356ijcCwJdJrZEUWzPfJpMAAAStPWR/h2Ktc10CoIQRUKEabFNvNbKfndcAKSjtrVfHW5YorWTzxDKYAxLtOWM+P7yt51hIYPpsDTNTyB/EwNAtWxdMuV8GCfbgxjxIviUYSV/SQOrbVjitbx4N8alBeXcdZR+3Tl3xS8FlIkt0dbnWH3xlbPgKgUo3HEq+tX7C4EuAAbGeOmqCuLIJt69s3PeQ1epKGfapCQJO6vGmwAWf/C1Wau6td8dV123BaAAUfHw6gSwtP3ugxA/y6X9INszAOQgbwFAIC/MQb9/Kv2vF2/UByejlVVn1Xiby/X6rPd/qj/1ak71UYKuwQAAAABJRU5ErkJggg=="); } #${pid} > menuseparator:last-child, #${pid} > menu[maxwidth] > .menu-right, #${pid} > [value=deleteAllSessions]:nth-last-child(2) { display: none; } #${pid} > menu[boot] { color: red; font-weight: bold; } #${pid} > menu[maxwidth] { color: blue; font-weight: bold; outline-offset: -2px; outline: 2px solid orangered; } } `.replace(/;$/gm, " !important;")))); var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(Services.io.newURI("resource://" + subst), sss.USER_SHEET); }, get gs() { delete this.gs; return this.gs = Cu.import("resource:///modules/sessionstore/SessionStore.jsm", {}); }, getState() { return JSON.parse(this.gs.SessionStore.getBrowserState()); }, splice(name, newName) { var ind = this.meta.order.indexOf(name); if (ind == -1) return; var args = [ind, 1]; if (1 in arguments) args.push(newName); else { if (ind == this.meta.boot) this.meta.boot = null; else if (ind < this.meta.boot) this.meta.boot--; } this.meta.order.splice(...args); }, get meta() { var file = Services.dirsvc.get("UChrm", Ci.nsIFile); file.append("simple_session_manager.json"); this.path = file.path; try { this.data = JSON.parse(Cu.readUTF8File(file)); } catch { this.pp = file.parent.path; this.data = Object.create(null); } var meta = this.data[mp]; if (!meta) { var order = Object.keys(this.data); meta = this.data[mp] = {order, boot: null}; } delete this.meta; return this.meta = meta; }, async save(excWin) { var io = Cu.getGlobalForObject(Cu).IOUtils; if (this.pp) await io.makeDirectory(this.pp), delete this.pp; (this.save = excWin => { this.meta.order.length ? io.writeJSON(this.path, this.data) : io.remove(this.path, {ignoreAbsent: true}); for(var win of CustomizableUI.windows) { if (win == excWin) continue; var popup = win.document.getElementById(pid); if (popup) popup.fillFlag = false; } })(excWin); }, get prompter() { var {prompt} = Services; var p = {}, args = [null, null, "UCF Simple Session Manager"]; p.alert = prompt.alert.bind(...args); p.confirm = prompt.confirm.bind(...args); var pr = prompt.prompt.bind(...args); p.prompt = (msg, value) => { var res = {value}; return pr(msg, res, null, {}) ? res.value : null; } delete this.prompter; return this.prompter = p; }, observe(s, t, data) { Services.obs.removeObserver(this, "quit-application"); if (data.includes("restart")) return; var {boot} = this.meta; if (boot == null) return; var state = this.data[this.meta.order[boot]]; //this.gs.SessionStoreInternal.getCurrentState = () => state; var ssi = this.gs.SessionStoreInternal; ssi.getCurrentState = () => state; Services.obs.removeObserver(ssi, "browser:purge-session-history"); Services.prefs.setBoolPref("browser.sessionstore.resume_session_once", true); }, get bwt() { delete this.bwt; var url = "resource:///modules/BrowserWindowTracker.jsm"; return this.bwt = ChromeUtils.import(url).BrowserWindowTracker; }, getName(state) { var wl = state.windows.length, tl = 0; for(var w of state.windows) tl += w.tabs.length; return `${ this.bwt.getTopWindow().gBrowser.selectedTab.label.slice(0, 70) } ${wl}/${tl} [${ new Date().toLocaleString("mn").replace(" ", "-") }]`; }, exists(name) { this.meta; return (this.exists = name => name in this.data && !this.prompter.alert("Сессия с тем же именем уже существует!"))(name); }, saveSession(state = this.getState(), name = this.getName(state)) { var name = this.prompter.prompt("Сохранить:", name); if (name == null) return true; if (this.exists(name)) return this.saveSession(state, name); this.data[name] = state; this.meta.order.push(name); //this.meta.order.unshift(name); //if (this.meta.boot != null) this.meta.boot++; }, restoreSession(name, win) { var ss = this.gs.SessionStore; var state = JSON.stringify(this.data[name]); win ? ss.setWindowState(win, state) : ss.setBrowserState(state); }, renameSession(name, newName = name) { var newName = this.prompter.prompt(`Переименовать "${name}" в:`, newName); if (newName == null || newName == name) return true; if (this.exists(newName)) return this.renameSession(name, newName); var {data} = this; this.splice(name, newName); data[newName] = data[name]; delete data[name]; }, removeSession(name) { if (!this.prompter.confirm(`Вы уверены, что хотите удалить ${name} ?`)) return true; delete this.data[name]; this.splice(name); }, deleteAllSessions() { if (!this.prompter.confirm(`Вы уверены, что хотите удалить все сессии?`)) return true; delete this.dragData; delete this.bwt.getTopWindow().document.getElementById(pid).dblMD; this.meta = (this.data = Object.create(null))[mp] = {order: [], boot: null}; } }).init()))("ucf-ssm-menupopup", "{07cae4f5-18b0-487b-80eb-973304af9528}");
Отредактировано Dobrov (25-02-2022 01:54:50)
Отсутствует
одна иконка прописана 2 раза. Как сократить код
Например, задать её как свойство объекта, и далее использовать, типа this.image
А вообще для восстановления удобнее сразу кликать по имени сохранённой сесии (и восстанавливать в новых вкладках при клике с нажатым Ctrl), а в подменю оставить только: Переименовать и Удалить.
Там же двойной левый mousedown устанавливает
или снимает загрузочную сессию. С этим что делать?
Ладно, допустим перенесём на клик ПКМ.
(async (pid, mp, self) => CustomizableUI.createWidget((self = { id: "797321", label: "Simple Session Manager", tooltiptext: "Управление сессиями", localized: false, init() { this.handleEvent = e => this[e.type](e); this.onTimeout = () => this.saveSession() || this.save(); Services.obs.addObserver(this, "quit-application"); var {openMenu} = this; this.render = function() { this.openMenu = openMenu; this.constructor.prototype.render.call(this); } delete this.init; return this; }, image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEnQAABJ0BfDRroQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGxSURBVDiNnZE/T1NRGMZ/7zn3lmKLkIKpaUxZFINEJZ0YHXRwcnBxMQ6aOJi4+FH8Dm5OOjA4+AEYGCTRook1JlVIVUrbW/rnPg63UtReIr7bOXmf5/ye59jDlanHS3O+wn/Mu+/DF8HFeVe5f+vaPTdfPpF4UNvk6frmhwAvXOEsvrR0IoN47xM4CHCADmDQBkAHbdTrTBRZdgYLs6NTD/MiMC+gC8MO6ke8ffWsXv3S3JpksHouv7Z4/UEeM8z6IwKfEGjYRt0G1d3m1p3n0Y1JBi/vTtfKw1Yec2CHBDFmXYjboAgL4tTc5pXsmcNcDxIDUFQHuqgfYT69OAuE9qqAoX4jIcAL7b9H+0deOYYg3tkYXxx2EAo7dQYEBF/TEULD5oow7KHut18RhGVD3GwxMZ36YWn6IJd37vQCSMSNBpYQCMs43PQMAJXlwtr6k7CGfo9iznN1ebGY7Ak1NSJwYERYJgM+Q+nClVzp/OXc3wWMwdT+jAVKCMwLC2PUeoMrrEI4m94BQq0a6mxjoca/YKFgUCfeqR8jPhoHcIAHe3ST2+UFLv2T8o/5uMvrnx9Wn65p5nMEAAAAAElFTkSuQmCC", onCreated(btn) { btn.type = "menu"; btn.phTimestamp = 0; btn.render = this.render; btn.onclick = this.click; // btn.setAttribute("image", "chrome://user_chrome_files/content/custom_styles/svg/download-resume.svg"); btn.setAttribute("image", this.image); var popup = btn.ownerDocument.createXULElement("menupopup"); popup.filler = this; popup.id = pid; popup.setAttribute("onpopupshowing", "event.defaultPrevented || filler.fill(event)"); btn.prepend(popup); btn.addEventListener("mousedown", this); popup.addEventListener("command", this); btn.ownerGlobal.addEventListener("unload", () => { btn.removeEventListener("mousedown", this); popup.removeEventListener("command", this); if (popup.filler != this) popup.removeEventListener("dragstart", this), popup.removeEventListener("popuphidden", this); }, {once: true}); }, openMenu(arg) { var pos; if (this.matches(".widget-overflow-list > :scope")) pos = "after_start"; else var win = this.ownerGlobal, {width, height, top, bottom, left, right} = this.closest("toolbar").getBoundingClientRect(), pos = width > height ? `${win.innerHeight - bottom > top ? "after" : "before"}_start` : `${win.innerWidth - right > left ? "end" : "start"}_before`; this.firstChild.setAttribute("position", pos); delete this.openMenu; this.openMenu(arg); }, mousedown(e) { if (e.button) return; var trg = e.target; if (trg.nodeName.startsWith("t")) trg.mdTimestamp = Cu.now(), trg.tid = e.view.setTimeout(this.onTimeout, 500), e.preventDefault(); }, boot(trg) { var popup = trg.parentNode; var old = popup.querySelector("[boot]"); if (old != trg) old?.removeAttribute("boot"); trg.toggleAttribute("boot"); popup.bootChanged = true; }, muTimestamp: 0, click(e) { var trg = e.target; if (trg.nodeName == "menu") { if (e.button > 1) self.boot(trg); else if (Cu.now() - self.muTimestamp > 50) e.view.closeMenus(trg.menupopup), self.restoreSession(trg.label, (e.button || e.ctrlKey) && e.view); } else if (trg != this || e.button) return; e.view.clearTimeout(this.tid); if (this.mdTimestamp - this.phTimestamp > 50) this.open = true; }, command(e) { var arg, trg = e.target, cmd = trg.value; if (cmd.startsWith("r")) arg = trg.parentNode.parentNode.label; this[cmd](arg) || this.save(); }, dragstart(e) { var trg = e.target; if (trg.nodeName != "menu") return; var popup = trg.parentNode; this.dragData = {trg, mouse: true}; trg.menupopup.hidePopup(); var win = trg.ownerGlobal; win.setCursor("grabbing"); var {width} = trg.getBoundingClientRect(); trg.setAttribute("maxwidth", width); win.addEventListener("mouseup", this); popup.addEventListener("mousemove", this); }, mousemove(e) { var trg = e.target, dtrg = this.dragData.trg; if (trg == dtrg || trg.nodeName != "menu") return; e.movementY > 0 ? trg.nextSibling != dtrg && trg.after(dtrg) : trg.previousSibling != dtrg && trg.before(dtrg); }, mouseup(arg) { if (arg.constructor.isInstance?.(arg)) { arg.preventDefault(); var {trg} = this.dragData; this.dragData.mouse = false; this.muTimestamp = Cu.now(); } else var trg = arg; trg.removeAttribute("maxwidth"); trg.ownerGlobal.setCursor("auto"); trg.ownerGlobal.removeEventListener("mouseup", this); trg.parentNode.removeEventListener("mousemove", this); }, popuphidden(e) { if (!e.target.id) return; e.view.removeEventListener("keydown", this, true); var popup = e.target; popup.parentNode.phTimestamp = Cu.now(); var save; if (this.dragData) { var {trg, mouse} = this.dragData; mouse && this.mouseup(trg); delete this.dragData; var order = Array.from(popup.getElementsByTagName("menu"), m => m.label); if (order.toString() != this.meta.order.toString()) { var hasBoot = this.meta.boot != null; if (hasBoot) var bootName = this.meta.order[this.meta.boot]; this.meta.order = order; if (hasBoot) this.meta.boot = this.meta.order.indexOf(bootName); save = true; } } if (popup.bootChanged) { delete popup.bootChanged; var {boot} = this.meta; var bootNode = e.target.querySelector("[boot]"); var ind = bootNode && this.meta.order.indexOf(bootNode.label); if (ind != boot) this.meta.boot = ind, save = true; } save && this.save(e.view); }, sku: `#${pid} > menu[maxwidth]`, skd: `#${pid} > menu:is([maxwidth],[_moz-menuactive]):not([open])`, keydown(e) { if (e.repeat && e.key == "Shift" || !e.shiftKey && e.key != " ") return; var func = this.keyHandlers[e.key]; if (!func) return; var menu = e.view.windowRoot .ownerGlobal.document.querySelector(this.skd); if (menu) e.stopImmediatePropagation(), func.call(this, menu, e); }, keyup(e) { if (e.key != "Shift") return; var win = e.view.windowRoot.ownerGlobal; win.removeEventListener("keyup", this, true); win.document.querySelector(this.skd)?.removeAttribute("maxwidth"); }, keyHandlers: { Enter(menu) { this.boot(menu); }, ArrowDown(menu) { var ns = menu.nextSibling; if (ns) ns.after(menu), this.arrow(menu); }, ArrowUp(menu) { var ps = menu.previousSibling; if (ps.nodeName == "menu") ps.before(menu), this.arrow(menu); }, " "(menu, e) { e.preventDefault(); menu.ownerGlobal.closeMenus(menu.parentNode); this.restoreSession(menu.label, e.ctrlKey && menu.ownerGlobal); } }, arrow(menu) { if (menu.hasAttribute("maxwidth")) return; menu.setAttribute("maxwidth", menu.getBoundingClientRect().width); menu.ownerGlobal.addEventListener("keyup", this, true); this.dragData = {trg: menu}; }, fill(e) { var mxe = e.view.MozXULElement; var initFrag = mxe.parseXULToFragment(` <menuitem value="saveSession" class="menuitem-iconic" label="Сохранить сессию"/> <menuitem value="deleteAllSessions" class="menuitem-iconic" label="Удалить все сессии"/> <menuseparator/> `); this.menuFrag = mxe.parseXULToFragment(`<menu class="menu-iconic"><menupopup> <menuitem label="Переименовать" class="menuitem-iconic" value="renameSession"/> <menuitem label="Удалить" class="menuitem-iconic" value="removeSession"/> </menupopup></menu>`); this.regStyle(); var filler = {fill: e => e.target.id ? e.view.addEventListener("keydown", this, true) || e.target.fillFlag || this.fillSessions(e.target) : this.dragData?.mouse && e.preventDefault() }; (this.fill = e => { var trg = e.target; trg.setAttribute("context", ""); trg.append(trg.ownerDocument.importNode(initFrag, true)); (trg.filler = filler).fill(e); trg.addEventListener("dragstart", this); trg.addEventListener("popuphidden", this); })(e); }, fillSessions(popup) { while(popup.lastChild.nodeName == "menu") popup.lastChild.remove(); var ind = 0, {boot} = this.meta; for(var name of this.meta.order) { var df = popup.ownerDocument.importNode(this.menuFrag, true); df.firstChild.setAttribute("label", name); if (ind++ == boot) df.firstChild.toggleAttribute("boot"); popup.append(df); } popup.fillFlag = true; }, regStyle() { delete this.regStyle; var subst = "ucf-ssm-style-resurl"; Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler).setSubstitution( subst, Services.io.newURI("data:text/css;charset=utf-8," + encodeURIComponent(` @-moz-document url-prefix(chrome://browser/content/browser.xhtml) { #${pid} > menu { list-style-image: url("${this.image}"); } #${pid} > [value=saveSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKVSURBVHjajFNNTBNREJ6+7na73bLbQn8I0BKNCYWKGr0oYoiJPxeNh6oHozcOxgSVi4le1JNHQRPigRsewURNPKiJMQicSISUACelRVJ2tz/bdktpy9adBzT8xTjJ5L35ezNv5hsLHEAv7noEntguChx7EuV8oTydKRhfno8kCnt9LTuFZ7f87mAz/8rnl86GOoOBBq+LQX1S1ioLs0txWdEmsulS38Phlcy+BwZ6W0L+JsfolcjpsFDnBKNcgQ193bRUwSrwQFgr6Dkd3o9NzilqMdI/FF+sPYCZ245I4zdunw9DtQr6LxlK6bVdpdrcPAiHfGBYLDD69ltUXsmfw0oIGoPNjkHMjMHa3J9asDyRpoyEOrQR0+dq5MxR0c29Rj3Bhvn8YjeWjZmN9cpWcApSkzpkptYg8T1FdWjTfysg1Ang9YtdT+80OogTbJc7OlsD+OftzOqsBrMflqHe6QKXIEL00zLV0UpSBbM/G9DeEQy6OXKJsfPsCbdXYjb0Yu2/nmMS9LSGYGlYpXLPkxCwkq1mR98Gn8Q4XexxYhhgYKf3TPTfRDaPqklkvViaSSpaxSpw/x1v5e0UG8W10k+iW8qfF2ZiccIydFQ7ScsXKO8ep4NiYj4ai6k5+Eoev1F1Wcn8QJDgnAnHbGYRWTh800cZ77Ryzmr6eCGXzYGiZCcQ2vQ32XT5PiIMTJBI4Waw1ZtZzLu7XaSMd1s9b9paKJA+vpuKqols3y4ov7wXaPN67GPXIl1hnDOOansyVicHhGHMzHkzeDKqqPnr/UOJxX3LNNDb5BJd3KC3Uexu7wgEGxq3limRqcxH47FVWRtPreYePBpJagdu4zYhwjx1cMFus59CuVgqTmPDDlrnvwIMAGS8IFCLagHpAAAAAElFTkSuQmCC"); } #${pid} [value=restoreSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAACzElEQVQ4jX2QPWwbZRjHf+/5vfPdObZjO3Ga2pVpGtxCP4QIDKgqDCDUNQwgJCS2qFI3hBCRCvXSCcTAAu0GY0Fi4kuq+IjUCpWAgCTq4IpS3Di2G8c+x/bZ57t7mSJFMfBf/3p+z+95BPvy3pufxqKmcVY3ZFFKmQtFGIReuNnrDze6lv5TqfSyx4EIgA/e+fzkZML6MDmVnD80mz1kxW3DMAxQCs/z6Hb6g3q1Xt1ttdfa7dbFN668vrkHkADJhPntufNnc0LTDi7AjFkkUknzcGF2LvCDuZVvfiwCj+/1GoAmhL3x6x2cZhsVqjFIGIZs15ts/LJOJCLt/Z0EiE3Y9eLpR1ONaoMH9zbHAGiC9FSKkwunWF1Z3RoDABhRg/zRPPmj+XHA/0QDaLectFLj6gcT+AHdTm9mzMC27e766lrWtCwy2Qz2hIUeNVDAaDCku9ujWW/ij3wsO9oaMzCiunf66TMU5gt4wyGbf1Upr5W5u15mq1JDhYqZQo6HIuqtueLw4vLXzwC89NZXeQFw/ePv7zx5buHEf6nf3qgMVipOGE0ko6EKhoQi3NnZ+c51BwsaQLOxM9N1uv86vNtz+aHSDn0pH9S2tl6r/Pn3s/VG/WYunzs/NZ2OSID0dKpRrzZS98v3kYbEsi1004BQcbtc9Q07bdYb229/dvmFL5aWVvVts9mq1Wo/e54vJIAQqGOPzQHgj3zcvos39BAIBshRqJQYjYZ/AFy79tQIeHVx+ctiIDRTA+g43Xud9q4PIHVJPBknk82QzqY5VZg2UUrEYhOX9s5aXL5RnMykb8Rj9kcC4OrSVZ1Hpt+PJ5PPz+SzR5KpyYRpGgRKMei7fHLr7lBmZ1XHcX4LgsCxLPt4JBLRm82Hr4j9DyuVSprdO/ZELGafkXpkXtPA94OK03Vv/R4/csEw5XOGbuieN6y6bv/S9XdfvPkPTgcoDlpQJpwAAAAASUVORK5CYII="); } #${pid} [value=renameSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPFJREFUeNrEU0sOgkAMbc1IIHoQT+KeY7hkBW5ccwLdsOICxI2X8peIGhggI21gggpCwsImM01f+tpOO0WlFIwR0efgeR5nsG0boihizPd91A5UwZDjuq5qwycwUkQYhttSr4Y4l76fDdtBEAQqz3OVZdnPQ09o2sQhrpBSQgnAen/qzLxZzljHcawxy7KAuCJNUyiKAm53SS0FBGQNlUW3lFO2iVCLYRhAXJEkCQPn65NGAswpL/4fWAebt1ZGXB3geHlw9maXsKqjS94CHNxF7xRM0/wKgI7jDBojvbnZAz3Gv/9E7NvGvmXCsev8EmAAWocA9ofpaRIAAAAASUVORK5CYII="); } #${pid} :is([value=removeSession], [value=deleteAllSessions]) { list-style-image: url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAABt0lEQVQ4ja2RT2sTURTFz8tk0nntFAQrVLBQxIUg/tkkMoLyIEVECHZhNrrxI+hOP5Mb6eBCcEipYIjZ2LpvhFasUtBSkwzOve+6mE6YSScuxLt67753fudyLvA/a7T+qCHmiTfrfWCMd3j9diPfq2SHX+uPnzJx71gP33w3bX9avBcE2j+SkK30Di7ffJ71VebMxD1hC2GGEEfH41prpftynIm92A0t2aYQQYgBThrndz/2KwCgf9Z2LNtImFOAtc356ijcCwJdJrZEUWzPfJpMAAAStPWR/h2Ktc10CoIQRUKEabFNvNbKfndcAKSjtrVfHW5YorWTzxDKYAxLtOWM+P7yt51hIYPpsDTNTyB/EwNAtWxdMuV8GCfbgxjxIviUYSV/SQOrbVjitbx4N8alBeXcdZR+3Tl3xS8FlIkt0dbnWH3xlbPgKgUo3HEq+tX7C4EuAAbGeOmqCuLIJt69s3PeQ1epKGfapCQJO6vGmwAWf/C1Wau6td8dV123BaAAUfHw6gSwtP3ugxA/y6X9INszAOQgbwFAIC/MQb9/Kv2vF2/UByejlVVn1Xiby/X6rPd/qj/1ak71UYKuwQAAAABJRU5ErkJggg=="); } #${pid} > menuseparator:last-child, #${pid} > menu[maxwidth] > .menu-right, #${pid} > [value=deleteAllSessions]:nth-last-child(2) { display: none; } #${pid} > menu[boot] { color: red; font-weight: bold; } #${pid} > menu[maxwidth] { color: blue; font-weight: bold; outline-offset: -2px; outline: 2px solid orangered; } } `.replace(/;$/gm, " !important;")))); var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(Services.io.newURI("resource://" + subst), sss.USER_SHEET); }, get gs() { delete this.gs; return this.gs = Cu.import("resource:///modules/sessionstore/SessionStore.jsm", {}); }, getState() { return JSON.parse(this.gs.SessionStore.getBrowserState()); }, splice(name, newName) { var ind = this.meta.order.indexOf(name); if (ind == -1) return; var args = [ind, 1]; if (1 in arguments) args.push(newName); else { if (ind == this.meta.boot) this.meta.boot = null; else if (ind < this.meta.boot) this.meta.boot--; } this.meta.order.splice(...args); }, get meta() { var file = Services.dirsvc.get("UChrm", Ci.nsIFile); file.append("simple_session_manager.json"); this.path = file.path; try { this.data = JSON.parse(Cu.readUTF8File(file)); } catch { this.pp = file.parent.path; this.data = Object.create(null); } var meta = this.data[mp]; if (!meta) { var order = Object.keys(this.data); meta = this.data[mp] = {order, boot: null}; } delete this.meta; return this.meta = meta; }, async save(excWin) { var io = Cu.getGlobalForObject(Cu).IOUtils; if (this.pp) await io.makeDirectory(this.pp), delete this.pp; (this.save = excWin => { this.meta.order.length ? io.writeJSON(this.path, this.data) : io.remove(this.path, {ignoreAbsent: true}); for(var win of CustomizableUI.windows) { if (win == excWin) continue; var popup = win.document.getElementById(pid); if (popup) popup.fillFlag = false; } })(excWin); }, get prompter() { var {prompt} = Services; var p = {}, args = [null, null, "UCF Simple Session Manager"]; p.alert = prompt.alert.bind(...args); p.confirm = prompt.confirm.bind(...args); var pr = prompt.prompt.bind(...args); p.prompt = (msg, value) => { var res = {value}; return pr(msg, res, null, {}) ? res.value : null; } delete this.prompter; return this.prompter = p; }, observe(s, t, data) { Services.obs.removeObserver(this, "quit-application"); if (data.includes("restart")) return; var {boot} = this.meta; if (boot == null) return; var state = this.data[this.meta.order[boot]]; //this.gs.SessionStoreInternal.getCurrentState = () => state; var ssi = this.gs.SessionStoreInternal; ssi.getCurrentState = () => state; Services.obs.removeObserver(ssi, "browser:purge-session-history"); Services.prefs.setBoolPref("browser.sessionstore.resume_session_once", true); }, get bwt() { delete this.bwt; var url = "resource:///modules/BrowserWindowTracker.jsm"; return this.bwt = ChromeUtils.import(url).BrowserWindowTracker; }, getName(state) { var wl = state.windows.length, tl = 0; for(var w of state.windows) tl += w.tabs.length; return `${ this.bwt.getTopWindow().gBrowser.selectedTab.label.slice(0, 70) } ${wl}/${tl} [${ new Date().toLocaleString("mn").replace(" ", "-") }]`; }, exists(name) { this.meta; return (this.exists = name => name in this.data && !this.prompter.alert("Сессия с тем же именем уже существует!"))(name); }, saveSession(state = this.getState(), name = this.getName(state)) { var name = this.prompter.prompt("Сохранить:", name); if (name == null) return true; if (this.exists(name)) return this.saveSession(state, name); this.data[name] = state; this.meta.order.push(name); //this.meta.order.unshift(name); //if (this.meta.boot != null) this.meta.boot++; }, restoreSession(name, win) { var ss = this.gs.SessionStore; var state = JSON.stringify(this.data[name]); win ? ss.setWindowState(win, state) : ss.setBrowserState(state); }, renameSession(name, newName = name) { var newName = this.prompter.prompt(`Переименовать "${name}" в:`, newName); if (newName == null || newName == name) return true; if (this.exists(newName)) return this.renameSession(name, newName); var {data} = this; this.splice(name, newName); data[newName] = data[name]; delete data[name]; }, removeSession(name) { if (!this.prompter.confirm(`Вы уверены, что хотите удалить ${name} ?`)) return true; delete this.data[name]; this.splice(name); }, deleteAllSessions() { if (!this.prompter.confirm(`Вы уверены, что хотите удалить все сессии?`)) return true; delete this.dragData; delete this.bwt.getTopWindow().document.getElementById(pid).bootChanged; this.meta = (this.data = Object.create(null))[mp] = {order: [], boot: null}; } }).init()))("ucf-ssm-menupopup", "{07cae4f5-18b0-487b-80eb-973304af9528}");
Отсутствует
Там же двойной левый mousedown устанавливает или снимает загрузочную сессию.
Вот этого в предыдущем коде не понял. Желательно в подсказку добавлять справку по действиям, как в большинстве примеров:
Долгое нажатие Сохранить сессию, Колёсико или Клик + Ctrl Открыть сессию в новых вкладках, Правый клик Выделить и Открывать при запуске???
Ещё проблема - сохраняю пару сессий по две или три вкладки. При клике по имени сохранённой сессии (не boot) восстанавливается только последняя вкладка, первые пустые. (Firefox 97.0.1)
А что должно происходить, если имя сессии правым кликом выделено Красным? Оставляю одну пустую вкладку, при перезапуске браузера выделенная сессия не загружается…
Раскомментировал эту строку - тоже ничего не автозагружается: this.gs.SessionStoreInternal.getCurrentState = () => state;
Отсутствует
О, а скажите, можно ли посредством сабжа организовать такую штуку?
В доквантумном фоксе было расширение itsalltext. Становишься в textarea, жмёшь хоткей или кликаешь иконку (всплывала в уголке textarea) — и содержимое оной сохранялось в файле на диске и открывалось в текстовом редакторе, в каком настроено. А когда в редакторе сохранялся файл, содержимое textarea обновлялось. Можно было закрыть огнелиса, закрыть текстовый редактор, потом запустить их обратно и продолжить редактировать текст.
В квантуме же расширение больше не работает. Альтернативы требуют предварительно запустить текстовый редактор вручную, а в нём запустить плагин-сервер (есть для вима, для саблайма, ещё чего-то), и только тогда textarea обменивается текстом с редактором. Схема не намного удобней, чем просто запустить редактор и копипастить. Я б даже сказал, вообще шило на мыло.
А вот через UCF можно запускать сторонние приложения и значит — можно теоретически реализовать поведение старого аддона.
Отсутствует
Становишься в textarea, жмёшь хоткей или кликаешь иконку (всплывала в уголке textarea) — и содержимое оной сохранялось в файле на диске и открывалось в текстовом редакторе
В шапке темы скрипт hookClicks сохраняет выделенный текст или всю страницу в текстовый файл – правый клик по кнопке Загрузки. К имени файла добавляется заголовок вкладки и дата, но имя можно фиксированное прописать…
Отсутствует
Wave пишетСтановишься в textarea, жмёшь хоткей или кликаешь иконку (всплывала в уголке textarea) — и содержимое оной сохранялось в файле на диске и открывалось в текстовом редакторе
В шапке темы скрипт hookClicks сохраняет выделенный текст или всю страницу в текстовый файл – правый клик по кнопке Загрузки. К имени файла добавляется заголовок вкладки и дата, но имя можно фиксированное прописать…
Остаётся чтобы этот скрипт а) автоматически запускал текстовый редактор с этим файлом, б) по сохранению файла «снаружи» загружал его и обновлял содержимое страницы.
Отсутствует
Wave
С внешним редактором не знаю, а вот для ucf в есть такая кнопка. Что она делает - смотрите там мою просьбу выше.
Для Вашего пожелания можно было бы сделать следующее:
1. По ПКМ в textarea в меню появляется строчка, например, "Открыть Notepad". Текст выделяется, копируется в буфер, в открывается вкладка "Notepad" и текст вставляется.
2. При закрытии вкладки текст выделяется, копируется в буфер и во вкладке, из которой был открыт в textarea вставляется.
Дело за малым - устраивает это Вас? И если устраивает найти того, кто это напишет. Кнопку сделал Dumby.
UPD: можно и без строки меню, хоткеем. Невнимательно прочитал Ваш пост.
Добавлено 27-02-2022 14:54:56
UPD2: Можно поставить расширение "Управление историей форм". Будет сохраняться история редактирования.
Отредактировано xrun1 (27-02-2022 14:54:56)
Отсутствует
xrun1
Вы распакуйте 52 версию, какую нить портативку, да и установите расширение, что б понимать о чем речь. Расширение шикарное, тоже его очень не хватает. То что вы предлагаете не совсем то... я через буфер обмена быстрее и проще все сделаю.
Отсутствует
_zt
Если длинный пост всегда сначала пишу в редакторе, чтобы проверить орфографию. Поэтому расширением никогда не пользовался по причине ненужности лично для меня.
У меня портабельная есть 56-я, но ставить расширение лень. Предложил исходя из формулировки вопроса, что можно придумать на сей день. Нет так нет.
Отсутствует
UPD2: Можно поставить расширение "Управление историей форм". Будет сохраняться история редактирования.
У меня аналогичное расширение стоит, Textarea Cache. Оно, конечно, спасает от случайного перехода на другую страницу, закрытия вкладки и прочих неприятностей (на самом деле нет, потому что за всё время, что оно у меня стоит, так ни разу и не пригодилось).
Если длинный пост всегда сначала пишу в редакторе, чтобы проверить орфографию. Поэтому расширением никогда не пользовался по причине ненужности лично для меня.
Ну вот как поступаете вы. Придя куда-то, где нужно написать длинный пост, вы, вероятно, копируете в буфер обмена содержимое textarea (например, если там уже есть цитаты), запускаете редактор, вставляете из буфера обмена текст, пишете пост, копируете в буфер обмена текст, закрываете редактор, предварительно сказав «не сохранять» или введя имя файла и выбрав путь, и вставляете текст туда, куда писали.
.
Как поступал я, когда сидел на фф56-. Придя куда-то, где нужно писать длинный пост, нажимал хоткей, автоматом запускался редактор, где уже было то, что до этого было в textarea, писал пост, жал Ctrl-S, Alt-F4, переключался в браузер (если он не на переднем плане после закрытия редактора) и жал кнопку «отправить», т.к. в textarea текст уже тот, что я редактировал. Всё. Меньше действий — отсутствует ручной запуск редактора, два копирования-вставки в буфер, вопрос про то, что текст несохранён, с каким именем вы хотите его сохранить или вообще не хотите. Удобней (по крайней мере, мне).
.
Зы. Сами файлы расширение чистило по прошествии какого-то времени.
Отредактировано Wave (27-02-2022 19:50:19)
Отсутствует
Что необходимо изменить или добавить в этом скрипте, что бы всплывающее окно автоматически закрывалось после перемещения курсора за пределы окна ?
Да уж, мягко говоря, не слишком понятный вопрос.
Может попробуй добавить это, только удалить
затем не забудь, если Виталий что-то предложит.
(async bmrk => { await delayedStartupPromise; var popupshown = e => { var trg = e.target; if (trg.nodeName.startsWith("t")) return; var {curid, curbut} = autopopup; if (curid && trg.id == curid || curbut && ( curbut.className == "bookmark-item" && trg.matches(bmrk) || curbut.open && curbut.contains(trg.anchorNode || trg) && (curbut.type != "menu" || curbut.menupopup) )) trg.addEventListener("mouseleave", mouseleave), trg.addEventListener("popuphidden", popuphidden); } var popuphidden = function(e) { if (e.target == this) this.removeEventListener("mouseleave", mouseleave), this.removeEventListener("popuphidden", popuphidden); } var tid; var mouseleave = e => { tid && clearTimeout(tid); tid = setTimeout(check, 350, e.target); } var check = popup => { tid = null; popup.closest(":is(menupopup,panel):hover") || autopopup.curbut?.matches(":hover") || (popup.nodeName.startsWith("m") ? closeMenus(popup) : popup.hidePopup()); } var autopopup = ucf_custom_script_win.mouseoveropentoolbarbutton; var {destructor} = autopopup; autopopup.destructor = () => { destructor.call(autopopup); removeEventListener("popupshown", popupshown); } addEventListener("popupshown", popupshown); })("toolbarbutton.bookmark-item :scope");
Вот этого в предыдущем коде не понял.
История у него есть, не вдруг появился, а из даденого,
и обсуждалось, и хотелки добавлялись.
А если выдернуть из контекста, и смотреть по коду,
то конечно трудно понять, он же довольно большой.
Желательно в подсказку добавлять
Вот и займись этим. Если туда еще добавить про двиганье мышью,
и все клавиатурные аналоги мышиных действий, будет капитально.
при перезапуске браузера выделенная сессия не загружается
И не должна, перезапуск есть перезапуск, это действие определённого характера.
А вот если закрыть Firefox, то затем, при запуске, должна загружаться.
восстанавливается только последняя вкладка, первые пустые
Прямо в реальном времени это не работает.
Нужно подождать, а не сохранять сразу после открытия вкладок.
Если очень надо, то можно попробовать так:
задать небольшое значение настройки browser.sessionstore.interval
подождать секунду, вернуть настройку, и тогда сохранять.
Вроде работает, на первый взгляд.
(async (pid, mp, self) => CustomizableUI.createWidget((self = { id: "797321", label: "Simple Session Manager", tooltiptext: "Управление сессиями", localized: false, init() { this.handleEvent = e => this[e.type](e); this.onTimeout = async () => await this.saveSession() || this.save(); Services.obs.addObserver(this, "quit-application"); var {openMenu} = this; this.render = function() { this.openMenu = openMenu; this.constructor.prototype.render.call(this); } delete this.init; return this; }, image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEnQAABJ0BfDRroQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGxSURBVDiNnZE/T1NRGMZ/7zn3lmKLkIKpaUxZFINEJZ0YHXRwcnBxMQ6aOJi4+FH8Dm5OOjA4+AEYGCTRook1JlVIVUrbW/rnPg63UtReIr7bOXmf5/ye59jDlanHS3O+wn/Mu+/DF8HFeVe5f+vaPTdfPpF4UNvk6frmhwAvXOEsvrR0IoN47xM4CHCADmDQBkAHbdTrTBRZdgYLs6NTD/MiMC+gC8MO6ke8ffWsXv3S3JpksHouv7Z4/UEeM8z6IwKfEGjYRt0G1d3m1p3n0Y1JBi/vTtfKw1Yec2CHBDFmXYjboAgL4tTc5pXsmcNcDxIDUFQHuqgfYT69OAuE9qqAoX4jIcAL7b9H+0deOYYg3tkYXxx2EAo7dQYEBF/TEULD5oow7KHut18RhGVD3GwxMZ36YWn6IJd37vQCSMSNBpYQCMs43PQMAJXlwtr6k7CGfo9iznN1ebGY7Ak1NSJwYERYJgM+Q+nClVzp/OXc3wWMwdT+jAVKCMwLC2PUeoMrrEI4m94BQq0a6mxjoca/YKFgUCfeqR8jPhoHcIAHe3ST2+UFLv2T8o/5uMvrnx9Wn65p5nMEAAAAAElFTkSuQmCC", onCreated(btn) { btn.type = "menu"; btn.phTimestamp = 0; btn.render = this.render; btn.onclick = this.click; // btn.setAttribute("image", "chrome://user_chrome_files/content/custom_styles/svg/download-resume.svg"); btn.setAttribute("image", this.image); var popup = btn.ownerDocument.createXULElement("menupopup"); popup.filler = this; popup.id = pid; popup.setAttribute("onpopupshowing", "event.defaultPrevented || filler.fill(event)"); btn.prepend(popup); btn.addEventListener("mousedown", this); popup.addEventListener("command", this); btn.ownerGlobal.addEventListener("unload", () => { btn.removeEventListener("mousedown", this); popup.removeEventListener("command", this); if (popup.filler != this) popup.removeEventListener("dragstart", this), popup.removeEventListener("popuphidden", this); }, {once: true}); }, openMenu(arg) { var pos; if (this.matches(".widget-overflow-list > :scope")) pos = "after_start"; else var win = this.ownerGlobal, {width, height, top, bottom, left, right} = this.closest("toolbar").getBoundingClientRect(), pos = width > height ? `${win.innerHeight - bottom > top ? "after" : "before"}_start` : `${win.innerWidth - right > left ? "end" : "start"}_before`; this.firstChild.setAttribute("position", pos); delete this.openMenu; this.openMenu(arg); }, mousedown(e) { if (e.button) return; var trg = e.target; if (trg.nodeName.startsWith("t")) trg.mdTimestamp = Cu.now(), trg.tid = e.view.setTimeout(this.onTimeout, 500), e.preventDefault(); }, boot(trg) { var popup = trg.parentNode; var old = popup.querySelector("[boot]"); if (old != trg) old?.removeAttribute("boot"); trg.toggleAttribute("boot"); popup.bootChanged = true; }, muTimestamp: 0, click(e) { var trg = e.target; if (trg.nodeName == "menu") { if (e.button > 1) self.boot(trg); else if (Cu.now() - self.muTimestamp > 50) e.view.closeMenus(trg.menupopup), self.restoreSession(trg.label, (e.button || e.ctrlKey) && e.view); } else if (trg != this || e.button) return; e.view.clearTimeout(this.tid); if (this.mdTimestamp - this.phTimestamp > 50) this.open = true; }, async command(e) { var arg, trg = e.target, cmd = trg.value; if (cmd.startsWith("r")) arg = trg.parentNode.parentNode.label; await this[cmd](arg) || this.save(); }, dragstart(e) { var trg = e.target; if (trg.nodeName != "menu") return; var popup = trg.parentNode; this.dragData = {trg, mouse: true}; trg.menupopup.hidePopup(); var win = trg.ownerGlobal; win.setCursor("grabbing"); var {width} = trg.getBoundingClientRect(); trg.setAttribute("maxwidth", width); win.addEventListener("mouseup", this); popup.addEventListener("mousemove", this); }, mousemove(e) { var trg = e.target, dtrg = this.dragData.trg; if (trg == dtrg || trg.nodeName != "menu") return; e.movementY > 0 ? trg.nextSibling != dtrg && trg.after(dtrg) : trg.previousSibling != dtrg && trg.before(dtrg); }, mouseup(arg) { if (arg.constructor.isInstance?.(arg)) { arg.preventDefault(); var {trg} = this.dragData; this.dragData.mouse = false; this.muTimestamp = Cu.now(); } else var trg = arg; trg.removeAttribute("maxwidth"); trg.ownerGlobal.setCursor("auto"); trg.ownerGlobal.removeEventListener("mouseup", this); trg.parentNode.removeEventListener("mousemove", this); }, popuphidden(e) { if (!e.target.id) return; e.view.removeEventListener("keydown", this, true); var popup = e.target; popup.parentNode.phTimestamp = Cu.now(); var save; if (this.dragData) { var {trg, mouse} = this.dragData; mouse && this.mouseup(trg); delete this.dragData; var order = Array.from(popup.getElementsByTagName("menu"), m => m.label); if (order.toString() != this.meta.order.toString()) { var hasBoot = this.meta.boot != null; if (hasBoot) var bootName = this.meta.order[this.meta.boot]; this.meta.order = order; if (hasBoot) this.meta.boot = this.meta.order.indexOf(bootName); save = true; } } if (popup.bootChanged) { delete popup.bootChanged; var {boot} = this.meta; var bootNode = e.target.querySelector("[boot]"); var ind = bootNode && this.meta.order.indexOf(bootNode.label); if (ind != boot) this.meta.boot = ind, save = true; } save && this.save(e.view); }, sku: `#${pid} > menu[maxwidth]`, skd: `#${pid} > menu:is([maxwidth],[_moz-menuactive]):not([open])`, keydown(e) { if (e.repeat && e.key == "Shift" || !e.shiftKey && e.key != " ") return; var func = this.keyHandlers[e.key]; if (!func) return; var menu = e.view.windowRoot .ownerGlobal.document.querySelector(this.skd); if (menu) e.stopImmediatePropagation(), func.call(this, menu, e); }, keyup(e) { if (e.key != "Shift") return; var win = e.view.windowRoot.ownerGlobal; win.removeEventListener("keyup", this, true); win.document.querySelector(this.skd)?.removeAttribute("maxwidth"); }, keyHandlers: { Enter(menu) { this.boot(menu); }, ArrowDown(menu) { var ns = menu.nextSibling; if (ns) ns.after(menu), this.arrow(menu); }, ArrowUp(menu) { var ps = menu.previousSibling; if (ps.nodeName == "menu") ps.before(menu), this.arrow(menu); }, " "(menu, e) { e.preventDefault(); menu.ownerGlobal.closeMenus(menu.parentNode); this.restoreSession(menu.label, e.ctrlKey && menu.ownerGlobal); } }, arrow(menu) { if (menu.hasAttribute("maxwidth")) return; menu.setAttribute("maxwidth", menu.getBoundingClientRect().width); menu.ownerGlobal.addEventListener("keyup", this, true); this.dragData = {trg: menu}; }, fill(e) { var mxe = e.view.MozXULElement; var initFrag = mxe.parseXULToFragment(` <menuitem value="saveSession" class="menuitem-iconic" label="Сохранить сессию"/> <menuitem value="deleteAllSessions" class="menuitem-iconic" label="Удалить все сессии"/> <menuseparator/> `); this.menuFrag = mxe.parseXULToFragment(`<menu class="menu-iconic"><menupopup> <menuitem label="Переименовать" class="menuitem-iconic" value="renameSession"/> <menuitem label="Удалить" class="menuitem-iconic" value="removeSession"/> </menupopup></menu>`); this.regStyle(); var filler = {fill: e => e.target.id ? e.view.addEventListener("keydown", this, true) || e.target.fillFlag || this.fillSessions(e.target) : this.dragData?.mouse && e.preventDefault() }; (this.fill = e => { var trg = e.target; trg.setAttribute("context", ""); trg.append(trg.ownerDocument.importNode(initFrag, true)); (trg.filler = filler).fill(e); trg.addEventListener("dragstart", this); trg.addEventListener("popuphidden", this); })(e); }, fillSessions(popup) { while(popup.lastChild.nodeName == "menu") popup.lastChild.remove(); var ind = 0, {boot} = this.meta; for(var name of this.meta.order) { var df = popup.ownerDocument.importNode(this.menuFrag, true); df.firstChild.setAttribute("label", name); if (ind++ == boot) df.firstChild.toggleAttribute("boot"); popup.append(df); } popup.fillFlag = true; }, regStyle() { delete this.regStyle; var subst = "ucf-ssm-style-resurl"; Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler).setSubstitution( subst, Services.io.newURI("data:text/css;charset=utf-8," + encodeURIComponent(` @-moz-document url-prefix(chrome://browser/content/browser.xhtml) { #${pid} > menu { list-style-image: url("${this.image}"); } #${pid} > [value=saveSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKVSURBVHjajFNNTBNREJ6+7na73bLbQn8I0BKNCYWKGr0oYoiJPxeNh6oHozcOxgSVi4le1JNHQRPigRsewURNPKiJMQicSISUACelRVJ2tz/bdktpy9adBzT8xTjJ5L35ezNv5hsLHEAv7noEntguChx7EuV8oTydKRhfno8kCnt9LTuFZ7f87mAz/8rnl86GOoOBBq+LQX1S1ioLs0txWdEmsulS38Phlcy+BwZ6W0L+JsfolcjpsFDnBKNcgQ193bRUwSrwQFgr6Dkd3o9NzilqMdI/FF+sPYCZ245I4zdunw9DtQr6LxlK6bVdpdrcPAiHfGBYLDD69ltUXsmfw0oIGoPNjkHMjMHa3J9asDyRpoyEOrQR0+dq5MxR0c29Rj3Bhvn8YjeWjZmN9cpWcApSkzpkptYg8T1FdWjTfysg1Ang9YtdT+80OogTbJc7OlsD+OftzOqsBrMflqHe6QKXIEL00zLV0UpSBbM/G9DeEQy6OXKJsfPsCbdXYjb0Yu2/nmMS9LSGYGlYpXLPkxCwkq1mR98Gn8Q4XexxYhhgYKf3TPTfRDaPqklkvViaSSpaxSpw/x1v5e0UG8W10k+iW8qfF2ZiccIydFQ7ScsXKO8ep4NiYj4ai6k5+Eoev1F1Wcn8QJDgnAnHbGYRWTh800cZ77Ryzmr6eCGXzYGiZCcQ2vQ32XT5PiIMTJBI4Waw1ZtZzLu7XaSMd1s9b9paKJA+vpuKqols3y4ov7wXaPN67GPXIl1hnDOOansyVicHhGHMzHkzeDKqqPnr/UOJxX3LNNDb5BJd3KC3Uexu7wgEGxq3limRqcxH47FVWRtPreYePBpJagdu4zYhwjx1cMFus59CuVgqTmPDDlrnvwIMAGS8IFCLagHpAAAAAElFTkSuQmCC"); } #${pid} [value=restoreSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAACzElEQVQ4jX2QPWwbZRjHf+/5vfPdObZjO3Ga2pVpGtxCP4QIDKgqDCDUNQwgJCS2qFI3hBCRCvXSCcTAAu0GY0Fi4kuq+IjUCpWAgCTq4IpS3Di2G8c+x/bZ57t7mSJFMfBf/3p+z+95BPvy3pufxqKmcVY3ZFFKmQtFGIReuNnrDze6lv5TqfSyx4EIgA/e+fzkZML6MDmVnD80mz1kxW3DMAxQCs/z6Hb6g3q1Xt1ttdfa7dbFN668vrkHkADJhPntufNnc0LTDi7AjFkkUknzcGF2LvCDuZVvfiwCj+/1GoAmhL3x6x2cZhsVqjFIGIZs15ts/LJOJCLt/Z0EiE3Y9eLpR1ONaoMH9zbHAGiC9FSKkwunWF1Z3RoDABhRg/zRPPmj+XHA/0QDaLectFLj6gcT+AHdTm9mzMC27e766lrWtCwy2Qz2hIUeNVDAaDCku9ujWW/ij3wsO9oaMzCiunf66TMU5gt4wyGbf1Upr5W5u15mq1JDhYqZQo6HIuqtueLw4vLXzwC89NZXeQFw/ePv7zx5buHEf6nf3qgMVipOGE0ko6EKhoQi3NnZ+c51BwsaQLOxM9N1uv86vNtz+aHSDn0pH9S2tl6r/Pn3s/VG/WYunzs/NZ2OSID0dKpRrzZS98v3kYbEsi1004BQcbtc9Q07bdYb229/dvmFL5aWVvVts9mq1Wo/e54vJIAQqGOPzQHgj3zcvos39BAIBshRqJQYjYZ/AFy79tQIeHVx+ctiIDRTA+g43Xud9q4PIHVJPBknk82QzqY5VZg2UUrEYhOX9s5aXL5RnMykb8Rj9kcC4OrSVZ1Hpt+PJ5PPz+SzR5KpyYRpGgRKMei7fHLr7lBmZ1XHcX4LgsCxLPt4JBLRm82Hr4j9DyuVSprdO/ZELGafkXpkXtPA94OK03Vv/R4/csEw5XOGbuieN6y6bv/S9XdfvPkPTgcoDlpQJpwAAAAASUVORK5CYII="); } #${pid} [value=renameSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPFJREFUeNrEU0sOgkAMbc1IIHoQT+KeY7hkBW5ccwLdsOICxI2X8peIGhggI21gggpCwsImM01f+tpOO0WlFIwR0efgeR5nsG0boihizPd91A5UwZDjuq5qwycwUkQYhttSr4Y4l76fDdtBEAQqz3OVZdnPQ09o2sQhrpBSQgnAen/qzLxZzljHcawxy7KAuCJNUyiKAm53SS0FBGQNlUW3lFO2iVCLYRhAXJEkCQPn65NGAswpL/4fWAebt1ZGXB3geHlw9maXsKqjS94CHNxF7xRM0/wKgI7jDBojvbnZAz3Gv/9E7NvGvmXCsev8EmAAWocA9ofpaRIAAAAASUVORK5CYII="); } #${pid} :is([value=removeSession], [value=deleteAllSessions]) { list-style-image: url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAABt0lEQVQ4ja2RT2sTURTFz8tk0nntFAQrVLBQxIUg/tkkMoLyIEVECHZhNrrxI+hOP5Mb6eBCcEipYIjZ2LpvhFasUtBSkwzOve+6mE6YSScuxLt67753fudyLvA/a7T+qCHmiTfrfWCMd3j9diPfq2SHX+uPnzJx71gP33w3bX9avBcE2j+SkK30Di7ffJ71VebMxD1hC2GGEEfH41prpftynIm92A0t2aYQQYgBThrndz/2KwCgf9Z2LNtImFOAtc356ijcCwJdJrZEUWzPfJpMAAAStPWR/h2Ktc10CoIQRUKEabFNvNbKfndcAKSjtrVfHW5YorWTzxDKYAxLtOWM+P7yt51hIYPpsDTNTyB/EwNAtWxdMuV8GCfbgxjxIviUYSV/SQOrbVjitbx4N8alBeXcdZR+3Tl3xS8FlIkt0dbnWH3xlbPgKgUo3HEq+tX7C4EuAAbGeOmqCuLIJt69s3PeQ1epKGfapCQJO6vGmwAWf/C1Wau6td8dV123BaAAUfHw6gSwtP3ugxA/y6X9INszAOQgbwFAIC/MQb9/Kv2vF2/UByejlVVn1Xiby/X6rPd/qj/1ak71UYKuwQAAAABJRU5ErkJggg=="); } #${pid} > menuseparator:last-child, #${pid} > menu[maxwidth] > .menu-right, #${pid} > [value=deleteAllSessions]:nth-last-child(2) { display: none; } #${pid} > menu[boot] { color: red; font-weight: bold; } #${pid} > menu[maxwidth] { color: blue; font-weight: bold; outline-offset: -2px; outline: 2px solid orangered; } } `.replace(/;$/gm, " !important;")))); var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(Services.io.newURI("resource://" + subst), sss.USER_SHEET); }, get gs() { delete this.gs; return this.gs = Cu.import("resource:///modules/sessionstore/SessionStore.jsm", {}); }, splice(name, newName) { var ind = this.meta.order.indexOf(name); if (ind == -1) return; var args = [ind, 1]; if (1 in arguments) args.push(newName); else { if (ind == this.meta.boot) this.meta.boot = null; else if (ind < this.meta.boot) this.meta.boot--; } this.meta.order.splice(...args); }, get meta() { var file = Services.dirsvc.get("UChrm", Ci.nsIFile); file.append("simple_session_manager.json"); this.path = file.path; try { this.data = JSON.parse(Cu.readUTF8File(file)); } catch { this.pp = file.parent.path; this.data = Object.create(null); } var meta = this.data[mp]; if (!meta) { var order = Object.keys(this.data); meta = this.data[mp] = {order, boot: null}; } delete this.meta; return this.meta = meta; }, async save(excWin) { var io = Cu.getGlobalForObject(Cu).IOUtils; if (this.pp) await io.makeDirectory(this.pp), delete this.pp; (this.save = excWin => { this.meta.order.length ? io.writeJSON(this.path, this.data) : io.remove(this.path, {ignoreAbsent: true}); for(var win of CustomizableUI.windows) { if (win == excWin) continue; var popup = win.document.getElementById(pid); if (popup) popup.fillFlag = false; } })(excWin); }, get prompter() { var {prompt} = Services; var p = {}, args = [null, null, "UCF Simple Session Manager"]; p.alert = prompt.alert.bind(...args); p.confirm = prompt.confirm.bind(...args); var pr = prompt.prompt.bind(...args); p.prompt = (msg, value) => { var res = {value}; return pr(msg, res, null, {}) ? res.value : null; } delete this.prompter; return this.prompter = p; }, observe(s, t, data) { Services.obs.removeObserver(this, "quit-application"); if (data.includes("restart")) return; var {boot} = this.meta; if (boot == null) return; var state = this.data[this.meta.order[boot]]; var ssi = this.gs.SessionStoreInternal; ssi.getCurrentState = () => state; Services.obs.removeObserver(ssi, "browser:purge-session-history"); Services.prefs.setBoolPref("browser.sessionstore.resume_session_once", true); }, get bwt() { delete this.bwt; var url = "resource:///modules/BrowserWindowTracker.jsm"; return this.bwt = ChromeUtils.import(url).BrowserWindowTracker; }, getName(state) { var wl = state.windows.length, tl = 0; for(var w of state.windows) tl += w.tabs.length; return `${ this.bwt.getTopWindow().gBrowser.selectedTab.label.slice(0, 70) } ${wl}/${tl} [${ new Date().toLocaleString("mn").replace(" ", "-") }]`; }, exists(name) { this.meta; return (this.exists = name => name in this.data && !this.prompter.alert("Сессия с тем же именем уже существует!"))(name); }, getState() { return JSON.parse(this.gs.SessionStore.getBrowserState()); }, get spref() { var pref = "browser.sessionstore.interval"; var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); var wait = cb => timer.initWithCallback(cb, 1e3, timer.TYPE_ONE_SHOT); delete this.spref; return this.spref = async cb => { var val = Services.prefs.getIntPref(pref); Services.prefs.setIntPref(pref, 100); await new Promise(wait); Services.prefs.setIntPref(pref, val); } }, async saveSession(name = this.getName(this.getState())) { var name = this.prompter.prompt("Сохранить:", name); if (name == null) return true; if (this.exists(name)) return this.saveSession(name); await this.spref(); this.data[name] = this.getState(); this.meta.order.push(name); //this.meta.order.unshift(name); //if (this.meta.boot != null) this.meta.boot++; }, restoreSession(name, win) { var ss = this.gs.SessionStore; var state = JSON.stringify(this.data[name]); win ? ss.setWindowState(win, state) : ss.setBrowserState(state); }, renameSession(name, newName = name) { var newName = this.prompter.prompt(`Переименовать "${name}" в:`, newName); if (newName == null || newName == name) return true; if (this.exists(newName)) return this.renameSession(name, newName); var {data} = this; this.splice(name, newName); data[newName] = data[name]; delete data[name]; }, removeSession(name) { if (!this.prompter.confirm(`Вы уверены, что хотите удалить ${name} ?`)) return true; delete this.data[name]; this.splice(name); }, deleteAllSessions() { if (!this.prompter.confirm(`Вы уверены, что хотите удалить все сессии?`)) return true; delete this.dragData; delete this.bwt.getTopWindow().document.getElementById(pid).bootChanged; this.meta = (this.data = Object.create(null))[mp] = {order: [], boot: null}; } }).init()))("ucf-ssm-menupopup", "{07cae4f5-18b0-487b-80eb-973304af9528}");
Отсутствует