Dumby, если не трудно, переделайте пожалуйста под UCF.
Для 109+
/*Initialization Code*/ // Вернуть многоточие в названии вкладок .......... // Dumby: https://forum.mozilla-russia.org/viewtopic.php?pid=793054#p793054 ..... (function tlcrop(ctor) { var mod = (prop, repls) => { var desc = Object.getOwnPropertyDescriptor(ctor, prop); var {get, value} = desc, newDesc = {...desc}; var txt = get ? `(${get})`.replace("get", "function") : value; for(var repl of repls) txt = txt.replace(...repl); get ? newDesc.get = eval(txt) : newDesc.value = txt; Object.defineProperty(ctor, prop, newDesc); return desc; } var n = document.createElement("n"), s = new XMLSerializer(); var enc = attr => { n.setAttribute("a", attr); return s.serializeToString(n).slice(43, -6); } var formatter = new Localization(["browser/browser.ftl"], true); var markup = mod("markup", [ [/<label /g, '$&crop="end" flex="1" '], [ /data-l10n-id="(browser-tab-audio-[^"]+)"/g, (s, id) => `value="${enc(formatter.formatValueSync(id))}"` ] ]); var attrs = mod("inheritedAttributes", [[/text=label/g, "$&,value=label"]]); var reInitTabs = () => { delete ctor._fragment; delete ctor._flippedInheritedAttributes; for(var tab of gBrowser.tabs) delete tab._initialized, tab.initialize(); } reInitTabs(); var proto = ctor.prototype, key = "setSecondaryTabTooltipLabel", func = proto[key]; var setVal = lab => lab.setAttribute("value", lab.textContent); proto[key] = function() { func.apply(this, arguments); setTimeout(setVal, 50, this.querySelector(".tab-icon-sound-tooltip-label")); } var topic = "intl:app-locales-changed"; var obs = () => { var ind = self._destructors.findIndex(d => d.destructor == destructor); self._destructors.splice(ind, 1); destructor(); tlcrop(ctor); } var destructor = () => { proto[key] = func; Services.obs.removeObserver(obs, topic); Object.defineProperty(ctor, "markup", markup); Object.defineProperty(ctor, "inheritedAttributes", attrs); reInitTabs(); } addDestructor(destructor); Services.obs.addObserver(obs, topic); })(gBrowser.selectedTab.constructor);
«The Truth Is Out There»
Отсутствует
Отсутствует
Может замени, для начала, в этом стиле
-moz-box-flex: 1 на max-width: 100%
Большое спасибо, то что надо.
«The Truth Is Out There»
Отсутствует
Геноссе ВВП, нихт зер гуд, бог велел делиться )))
Отредактировано ALEX_45_ORP (30-01-2023 21:37:00)
Win 10х64
Отсутствует
А это никак не обойти ? Как прокси, так это SSL_ERROR_BAD_CERT_DOMAIN
Без понятия.
Сколько раз уже говорил,
что я контентским и сетевым делам посторонен,
спрашивать меня про них бесполезно.
Отсутствует
Dumby
Подскажите пожалуйста по кнопочке.
У меня в СВ есть такая кнопка:
// Очистить историю закрытых вкладок ..... function myClearHistoryUndoTab() { try { PlacesUtils.history.clear(); var closedTabCount = SessionStore.getClosedTabCount(window); while(closedTabCount--) SessionStore.forgetClosedTab(window, 0); } catch(e) { } } // END this.onclick = function(event) { if(event.button == 0 && Services.prompt.confirm(null, "Удалить историю закрытых вкладок и сессий", "Удалить список вкладок и сессий?")) { myClearHistoryUndoTab(); SessionStore.canRestoreLastSession = false; } }
try { CustomizableUI.createWidget({ id: "ucf_Remove_List_Tabs_Sessions", type: "custom", tooltiptext: "Удалить список вкладок и сесий", // defaultArea: CustomizableUI.AREA_NAVBAR, onBuild: function(document) { var toolbarbutton_0 = document.createXULElement("toolbarbutton"); toolbarbutton_0.id = this.id; toolbarbutton_0.tooltipText = this.tooltiptext; toolbarbutton_0.label = "Удалить список вкладок и сесий"; toolbarbutton_0.setAttribute("context", false); toolbarbutton_0.setAttribute("image", "data:image/png;base64,.........."); toolbarbutton_0.addEventListener("click", function(event) { var win = event.target.ownerDocument.defaultView; // Очистить историю закрытых вкладок ..... function myClearHistoryUndoTab() { try { PlacesUtils.history.clear(); var closedTabCount = SessionStore.getClosedTabCount(window); while(closedTabCount--) SessionStore.forgetClosedTab(window, 0); } catch(e) { } } // END if (event.button == 0 && Services.prompt.confirm(null, "Удалить историю закрытых вкладок и сесий", "Удалить список вкладок и сесий?")) { myClearHistoryUndoTab(); SessionStore.canRestoreLastSession = false; } }, false); toolbarbutton_0.classList.add("toolbarbutton-1"); toolbarbutton_0.classList.add("chromeclass-toolbar-additional"); return toolbarbutton_0; } }); } catch(ex) { Cu.reportError(ex); }
Пытался подтянуть что-то вроде этого:
var SessionStore = ChromeUtils.importESModule("resource:///modules/sessionstore/SessionStore.sys.mjs");
«The Truth Is Out There»
Отсутствует
Пишет: ReferenceError: SessionStore is not defined
Правильно пишет,
среди предустановленных в UCF модулей — этого нет
(вот PlacesUtils, например, есть).
Но имеется в окне. Можно обратиться win.SessionStore
Ну и ещё все (два) window заменить на win
а то там, зачем-то, в try-catch завёрнуто, в консоли не увидишь ничего.
Пытался подтянуть что-то вроде этого
ChromeUtils.importESModule() возвращает экспортный объект,
SessionStore — это будет его свойство.
Обычно используют деструктурирующее присваивание:
var {SessionStore} = ChromeUtils.importESModule("resource:///modules/sessionstore/SessionStore.sys.mjs");
а, если брать с окна, то, соответственно,
var {SessionStore} = win;
Отсутствует
Dumby
Большое спасибо за помощь!
Теперь всё работает как надо.
«The Truth Is Out There»
Отсутствует
Dumby, можно эту кнопку, которая клонирует кнопки Отключить, Включить, Настройки, Удалить адаптировать под 78+ и UCF..?
На 68esr она сработала:
,
правда с небольшими глюками - в "Персонализации" не отображается, соответственно на панель перетаскивать нечего, но, как видно, работает. На 78 кнопка в "Персонализации присутствует, но не пашет. Стиль для отображения дополнений в несколько столбцов использую этот, а в вашем коде поправил
span.cb-cloned-buttons-container {
display: vertical;
}
чтобы кнопки вертикально отображались, а то горизонтально как-то не очень смотрится когда "в несколько столбцов".
Отсутствует
display: vertical;
Что-то я сомневаюсь, что это валидное значение для свойства display
можно эту кнопку, которая клонирует кнопки Отключить, Включить, Настройки, Удалить адаптировать под 78+ и UCF..?
Набросок для custom_script.js
(async css => ({ vertical: true, btnActions: ["preferences", "toggle-disabled", "remove", "install-update"], cn: "ucf-cloned-button", init(topic, quit) { Services.obs.addObserver(this, topic); Services.obs.addObserver(quit = (s, t) => { Services.obs.removeObserver(quit, t); Services.obs.removeObserver(this, topic); }, "quit-application-granted"); }, isTargetDoc: doc => doc.ownerGlobal.docShell .currentDocumentChannel.name.endsWith("/aboutaddons.html"), observe(doc) { if (!this.isTargetDoc(doc)) return; var vers = parseInt(Services.appinfo.platformVersion); this.ts = `${vers >= 111 ? "moz-toggle" : "input"}[action="toggle-disabled"]`; css = css.replace("%TS%", this.ts) .replace(/%CN%/g, this.cn) .replace(/;$/gm, " !important;") .replace("%FD%", this.vertical ? "column" : "row"); var url = "data:text/css;charset=utf-8," + encodeURIComponent(css); var sss = Cc["@mozilla.org/content/style-sheet-service;1"] .getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(Services.io.newURI(url), sss.USER_SHEET); var unload = e => e.target.removeEventListener("update", this, true); var load = doc => { doc.addEventListener("update", this, true); doc.ownerGlobal.addEventListener("unload", unload, {once: true}); } this.observe = doc => this.isTargetDoc(doc) && load(doc); this.ccn = this.cn + "s-container"; this.tInd = this.btnActions.findIndex(s => s == "toggle-disabled"); this.btnActions = this.btnActions.map( action => `panel-list > panel-item[action="${action}"]` ); this.createPanelItem = vers == 110 ? doc => new (doc.ownerGlobal.customElements.get("panel-item")) : doc => doc.createElement("panel-item"); if (vers >= 89) this.clone = item => item.cloneNode(true); else { var cf = function(e) { var win = e.view; win.InspectorUtils.removeContentState(this, 4, true); Services.focus.clearFocus(win); } this.clone = item => { var clone = item.cloneNode(true); clone.onclick = cf; return clone; } } load(doc); }, handleEvent(e) { var trg = e.target; trg.nodeName == "ADDON-CARD" && trg.addon.type != "theme" && this.onCard(trg); }, onCard(card, again) { var btnsParent = card.querySelector("addon-options"); if (!btnsParent) return again || card.ownerGlobal .requestAnimationFrame(() => this.onCard(card, true)); var doc = card.ownerDocument; var [span] = card.getElementsByClassName(this.ccn); if (span) span.textContent = ""; else card.querySelector("button.more-options-button") .before(span = doc.createElement("span")), span.className = this.ccn; var item, num = 0; for(var sel of this.btnActions) { if (num++ == this.tInd) { if (!card.querySelector(this.ts)) continue; item = this.createPanelItem(doc); item.setAttribute("action", "toggle-disabled"); doc.l10n.setAttributes(item, `${ btnsParent.parentNode.getAttribute("active") == "true" ? "dis" : "en" }able-addon-button`); } else { item = btnsParent.querySelector(sel); if (!item) continue; item = this.clone(item); } span.append(item); item.shadowRoot.querySelector("button").classList.add(this.cn); } } }).init("chrome-document-loaded"))(`@-moz-document url(about:addons), url(chrome://mozapps/content/extensions/aboutaddons.html) { span.%CN%s-container { display: flex; flex-direction: %FD%; row-gap: 1px; } addon-card[expanded] span.%CN%s-container { flex-direction: row; } button.%CN% { -moz-appearance: none; margin: 0 1px; padding: 1px 6px 3px 6px; background-image: none; border-radius: 0; border: 1px solid #bbb; font-size: 13px; white-space: nowrap; font-family: Segoe UI; } button.%CN%:hover { background-color: gold; } button.%CN%:after, %TS% { display: none; } }`);
Отредактировано Dumby (08-02-2023 10:03:12)
Отсутствует
Что-то я сомневаюсь, что это валидное значение для свойства display
У меня, без академических знаний, лишь легкая тень сомнения мелькнула, потому-что в справочнике CSS такого значения нет. Наугад воткнул vertical (вспомнилось из какого-то старого стиля
-moz-box-orient: vertical) - сработало. А как на это браузер реагирует в плане ошибок я не знаю как посмотреть, консолью пользоваться не особо умею. Получается, что я случайно новое значение для display открыл))
Набросок для custom_script.js
Это уже можно "законченным произведением" назвать... с претензией на совершенство:
Премного благодарен!
То, что на скрине красным выделено, вылечил самостоятельно: в манифесте расширения сократил название - теперь отображается нормально, не "двоит". Не знаю, с точки зрения науки, это правильно или нет, но помогло.
Отредактировано LGS (04-02-2023 12:42:26)
Отсутствует
gBrowser.removeAllTabsBut(gBrowser.selectedTab); Как заменить ? Не работает...
А что не работает?
Сделал простенькую кнопку:
this.onclick = function(event) { if (event.button == 0) { gBrowser.removeAllTabsBut(gBrowser.selectedTab); } }
При нажатии закрываются все вкладки, кроме активной.
«The Truth Is Out There»
Отсутствует
А что не работает?
Видимо, имеется в виду, что не работает на сборке, а не на обычном Firefox.
Как заменить ?
Никак. Разве что полное цитирование с поправкой на ситуацию.
Можно добавить в SessionStore.jsm
недостающий метод resetLastClosedTabCount(), тогда будет работать.
После строки var SessionStore = {
Вот так:
var SessionStore = { resetLastClosedTabCount(aWindow) { if ("__SSi" in aWindow) { SessionStoreInternal._windows[aWindow.__SSi]._lastClosedTabGroupCount = -1; } else { throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG); } },
Отсутствует
Dumby, еще одна просьба. Возможно пропустил, но, вроде не попадалось... "приспособить"эту кнопку под 91+ и UCF.
Отсутствует
LGS
Давай попробую объединить со скриптом
добавления кнопок на аддонские карточки,
чтобы общий код не повторять для каждого отдельно.
(async (css, self) => ({ //===[ Buttons ]=================================================================== vertical: true, btnActions: ["preferences", "toggle-disabled", "remove", "install-update"], cn: "ucf-cloned-button", update(e) { var trg = e.target; trg.nodeName == "ADDON-CARD" && trg.addon.type != "theme" && this.onCard(trg); }, onCard(card, again) { var btnsParent = card.querySelector("addon-options"); if (!btnsParent) return again || card.ownerGlobal .requestAnimationFrame(() => this.onCard(card, true)); var doc = card.ownerDocument; var [span] = card.getElementsByClassName(this.ccn); if (span) span.textContent = ""; else card.querySelector("button.more-options-button") .before(span = doc.createElement("span")), span.className = this.ccn; var item, num = 0; for(var sel of this.btnActions) { if (num++ == this.tInd) { if (!card.querySelector(this.ts)) continue; item = this.createPanelItem(doc); item.setAttribute("action", "toggle-disabled"); doc.l10n.setAttributes(item, `${ btnsParent.parentNode.getAttribute("active") == "true" ? "dis" : "en" }able-addon-button`); } else { item = btnsParent.querySelector(sel); if (!item) continue; item = this.clone(item); } span.append(item); item.shadowRoot.querySelector("button").classList.add(this.cn); } }, //===[ Popup ]===================================================================== items: { "Копировать имя": [ addon => self.copy(addon.name), "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAByUlEQVQ4jY2TTUhUURiGn5tD0Sp00iAwXM1iFu4kWkUZg/9MoZQhdoUCV7ooItq4atFORRGkuLMwoc0kNBGKDLSwFpEIQgspqGUUNsjI3HvPX4s7I3Nn7oW+1fn5vvd8z3vOsYiIgXuPneFMr21ZVmh9+m7GisoPxcTsM2d46on5c1gy9bHgvDVR+afqJzNzy870xIgNUJGGkqf4XVEAuJ4XeWCiNpibX3MGr/XYPd0pADxlOK0MQgf7Xw++sfJq0zRiJQAWcgWndHRkr28UWcrlAfCVwa8KrK4XOPxbYqz/MsnWcyfFi7lCIPD9x0/70YNRykKz+eELQkny74sIJbnQmqQ71UVhe+cES2hoP9uC63mBgO/7dF7s4NexZPRmBqlBaMPHnc+kL7UTh1VxqwKuGxjkaUP+zRZCSVqwKJeP2dvdj8SqGZuod9hXhr6hGwgNL5ZfEoc1PnaL2sFNAlvvthFKxmJJbfCUqXbghhHSyTOkJwcBmHr4vAnLVwKhJEPZbLgDXwh678yG7rfjfLIJS2qD0IEP9R6kiq8XrzS+sOz9p5+asKodXB0YCQkcNBbHYUXlxP6u67dnIj9PY8QJpIC2/6iX/wDxeTOAfNDrywAAAABJRU5ErkJggg==", ], "Копировать ID": [ addon => self.copy(addon.id), "Копировать имя" ], "Копировать версию": [ addon => self.copy(addon.version), "Копировать имя", addon => !addon.version ], "Копировать имя и версию": [ addon => self.copy(addon.name + " " + addon.version), "Копировать имя", addon => !addon.version ], "Копировать URL кнопки": [ (addon, win) => { var btn = Object.assign({ parameters: {}, get initcode() {return this.initCode;}, setText(doc, name, t, cds) { win.custombutton.buttonSetText(doc, name, this[name], cds); } }, win.custombuttons.cbService.getButtonParameters(addon.buttonLink)); self.copy(win.custombutton.buttonGetURI(btn)); }, "Копировать имя", addon => addon.type != "custombuttons" ], "Домашняя страница": [ (addon, win) => win.openURL(addon.homepageURL || addon.reviewURL.replace(/\/reviews\/.*$/, "/")), "data:image/png;base64,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", addon => !addon.homepageURL && !addon.reviewURL ], "Поиск на АМО": [ (addon, win) => win.openURL( addon.homepageURL || ("https://addons.mozilla.org/search/?q=" + encodeURIComponent(addon.name)) ), "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJGSURBVDjLjdJLSNRBHMDx78yqLZaKS75DPdgDDaFDbdJmde5QlhCJGxgpRJfqEEKnIsJLB7skQYQKZaSmdLaopPCgEvSCShCMzR5a7oq7/3l12RVtjfzBMA/4fWZ+MyOccwBM3g8HEbIdfCEhfAFnLVapOa28Uevpjrqz/WOsERJgsu9Uq5CZQzgqrJfo9BajNd5irEYn4p3OUiFExtCLmw2tawFi4l5zUMjMIau9u7K+qxeoAcoAA0wDb2OPwmfA16LiiaOHLj1edRLpkO3WmIis7+oBDgJbgQ2AH6gC6jY19N62RkcctKeVIJAhp9QgUA3kJXdONZVcq9JxPSgQoXRAyIDRth8oAXQyKdWnoCKrTD9CBv4GMqx1WGNZkeRWJKbG2hiD1Cb9FbTnzWFdY/LCdLKlgNQ84gyNKqHm0gDjqVHnxDHgA/B9RQkpaB6YklkZl62np9KBhOqwjpKFgeY2YAz4BESBWHI8Hhs6PVVSvc3v98ye4fP7T676B845nt040ip98qpWJmI9PWiU6bfWgXGN2YHcKwU7tsuc4kpUPMbU0+f8+vKt+Pitl7PLAMDI9cNBoB0hQwICzjqUp6MZvsy8yvp95BRuQUjJ75mPvH4wYo1NlJ64Mza7DPwrhi8cCOeXl/aUB4P4c/NJxKLMvpngycCrzxVFG2v/CwAMnguF80oLe8p27cQh+fnpPV/fTc95S6piXQDAw7a9YbWkezZXFbAwMx/xPFXb1D3+Y90AQF/L7kAsri9mZ4lrTd0TcYA/Kakr+x2JSPUAAAAASUVORK5CYII=", ["custombuttons", "theme", "plugin"] ], "Папка установки": [ addon => self.getFile(addon).reveal(), "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABAklEQVR42mNkoBAwAjEXEAcCMTsW+U9AvB6I/+I0gJ2Noe3QJoZKASEgjwkq+h+C795lYPCKZMgC8mZg0fsfbICIIMOcF6cZkrGZ/v8fA0PndIa/7z8BXfAPqgVKv//A8GPeZoYERmE+hjmP1+AwAOgiTjOIP7HZLyjLMJNRmB/ogjMMyYzsUC8wIhQwsgCFWHAHoKAy0AARIYY5r69idwEhIKgBMgAYBq8vkGmALsyAU2QaYAwz4CiZBliADBAAGnCATANsYQbsJtMAJ5ABwGh8uZE8A4R9gAYwMzHkT8hl6Bfgxp5ecIH3Xxj+F05hyIdpUmXAnpnwge9AfJckW7EBAC/gSzisxsnmAAAAAElFTkSuQmCC", ["custombuttons", "theme", "plugin"] ], "Файл установки": [ addon => self.getFile(addon).launch(), "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA51AAAOdQG5Y1EyAAAAhklEQVQ4y6WT0QnAIAxE78Bt2v1cod3PznP9kVLTRKUGBD+Sd5eQUBJWggCWCAkAJPGXOqlUPyVKkrSPQIoCQJGE6AF4HFyGuBmrR3cGQX8Wmp2cL8Cqv5JPD5Zm1D0nFZjTjHpQ7DuI1L3iBjBS9/pvhtjr21OukVkXiX/ug6SWj4mr53wDMz1vldHlLJkAAAAASUVORK5CYII=", ["custombuttons", "theme", "plugin"] ], }, listContainerId: "ucf-aa-extra-items-container", showing(e) { var card = e.target.closest("addon-card"); if (!card) return; this.labs = []; var imgs = new Map(); var set = (key, val) => imgs.set(key, imgs.has(key) ? imgs.get(key).concat(val) : [val]); var entries = Object.entries(this.items); entries.forEach(([lab, [func, img, hideOn]], ind) => { this.labs.push(lab); (this[lab] = func).hideOn = hideOn; img && set(this.items[img]?.[1] ? entries.findIndex(a => a[0] == img): ind, ind); }); if (imgs.size) { var cspRe = /^(?:chrome|file|jar|resource|moz-extension|https?):/; var [a, b, t, s, p, o, f] = this.vers >= 110 ? ["", "addon-options > panel-list > ", "", "::part(button)", "background-image", "AUTHO", ""] : ["\n", "\t", "\t", "", "--icon", "USE", "\n}"]; var reg = [], push = (ind, icon) => { var chromeImg = "chrome://user_chrome_files/content/aaepiimg_" + ind; reg.push(["override", chromeImg, icon]); return chromeImg; } var rules = []; for(var [ind, nums] of imgs) { var sel = [], img = entries[ind][1][1]; for(var num of nums) sel.push( `${b}#${this.listContainerId} > panel-item:nth-child(${num + 1})${s}` ); rules.push(`${sel.join(`,${t}\n`)} {\n${t}\t${p}: url(${ cspRe.test(img) ? img : push(ind, img) }) !important;\n${t}}`); } if (reg.length) { var ams = Cc["@mozilla.org/addons/addon-manager-startup;1"] .getService(Ci.amIAddonManagerStartup); var mUri = Services.io.newFileURI(Services.dirsvc.get("ProfD", Ci.nsIFile)); this.chromeReg = ams.registerChrome(mUri, reg); } this.regSheet(`${a}${rules.join("\n")}${f}`, o + "R_SHEET"); } delete this.items; self = this; this.sym = Symbol.for(this.listContainerId); (this.showing = e => { var card = e.target.closest("addon-card"); card && this.onListShowind(card.addon, e.target); })(e); this.onListShowind(card.addon, e.target); }, onListShowind(addon, list) { var doc = list.ownerDocument, win = doc.ownerGlobal; var container = doc[this.sym]; if (!container) { container = doc[this.sym] = doc.createElement("div"); container.onclick = this.cclick; container.id = this.listContainerId; for(var lab of this.labs) container.appendChild(this.createPanelItem(doc)).append(lab); var mo = new win.MutationObserver(this.mut); (container.mo = mo).container = container; } for(var item of container.children) { var h = this[item.textContent].hideOn; item.hidden = h && (h.call ? h(addon) : h.includes(addon.type)); } var {mo} = container; mo.disconnect(); list.contains(container) || list.prepend(container); mo.count = 0; mo.ts = Date.now(); mo.observe(list, {childList: true}); }, mut(muts, mo) { if (++mo.count > 10 || Date.now() - mo.ts > 100) return mo.disconnect(); var list = muts[0].target, {container} = mo; if (list.firstElementChild != container) mo.disconnect(), list.prepend(container), mo.observe(list, {childList: true}); }, cclick(e) { e.stopImmediatePropagation(); this.parentNode.hide(); self[e.target.textContent]( e.target.closest("addon-card").addon, e.view.windowRoot.ownerGlobal ); }, copy: str => (self.copy = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper).copyString )(str), getFile(addon) { var file, uri = addon.getResourceURI(); if (uri instanceof Ci.nsIJARURI) uri = uri.JARFile; if (uri instanceof Ci.nsIFileURL) file = uri.file; return file; }, //================================================================================ init(topic, quit) { Services.obs.addObserver(this, topic); Services.obs.addObserver(quit = (s, t) => { Services.obs.removeObserver(quit, t); Services.obs.removeObserver(this, topic); }, "quit-application-granted"); }, isTargetDoc: doc => doc.ownerGlobal.docShell .currentDocumentChannel.name.endsWith("/aboutaddons.html"), observe(doc) { if (!this.isTargetDoc(doc)) return; var vers = this.vers = parseInt(Services.appinfo.platformVersion); this.ts = `${vers >= 111 ? "moz-toggle" : "input"}[action="toggle-disabled"]`; css = css.replace("%TS%", this.ts) .replace(/%CN%/g, this.cn) .replace(/;$/gm, " !important;") .replace("%FD%", this.vertical ? "column" : "row"); this.regSheet(css, "USER_SHEET"); var unload = e => { e.target.removeEventListener("update", this, true); e.target.removeEventListener("showing", this, true); } var load = doc => { doc.addEventListener("update", this, true); doc.addEventListener("showing", this, true); doc.ownerGlobal.addEventListener("unload", unload, {once: true}); } this.handleEvent = e => this[e.type](e); this.observe = doc => this.isTargetDoc(doc) && load(doc); this.ccn = this.cn + "s-container"; this.tInd = this.btnActions.findIndex(s => s == "toggle-disabled"); this.btnActions = this.btnActions.map( action => `panel-list > panel-item[action="${action}"]` ); this.createPanelItem = vers == 110 ? doc => new (doc.ownerGlobal.customElements.get("panel-item")) : doc => doc.createElement("panel-item"); if (vers >= 89) this.clone = item => item.cloneNode(true); else { var cf = function(e) { var win = e.view; win.InspectorUtils.removeContentState(this, 4, true); Services.focus.clearFocus(win); } this.clone = item => { var clone = item.cloneNode(true); clone.onclick = cf; return clone; } } load(doc); }, regSheet(...args) { var d = "data:text/css;charset=utf8,"; var md = d + "@-moz-document url(about:addons),%0A" + "url(chrome://mozapps/content/extensions/aboutaddons.html) {"; var sss = Cc["@mozilla.org/content/style-sheet-service;1"] .getService(Ci.nsIStyleSheetService); (this.regSheet = (code, origin) => sss.loadAndRegisterSheet( Services.io.newURI((origin[1] == "U" ? d : md) + encodeURIComponent(code)), sss[origin] ))(...args); } }).init("chrome-document-loaded"))(`\ span.%CN%s-container { display: flex; flex-direction: %FD%; row-gap: 1px; } addon-card[expanded] span.%CN%s-container { flex-direction: row; } button.%CN% { -moz-appearance: none; margin: 0 1px; padding: 1px 6px 3px 6px; background-image: none; border-radius: 0; border: 1px solid #bbb; font-size: 13px; white-space: nowrap; font-family: Segoe UI; } button.%CN%:hover { background-color: gold; } button.%CN%:after, %TS% { display: none; } }`);
Отредактировано Dumby (02-03-2023 09:29:29)
Отсутствует
Давай попробую объединить со скриптом
добавления кнопок на аддонские карточки,
чтобы общий код не повторять для каждого отдельно.
Так еще лучше. Я не стал изначально озвучивать, чтобы скрипты объединить, думал усложнит задачу:
Благодарю!
И, не сочтите за наглость: в контекстное (popup) аддонов можно добавить пункт "Проверить обновления"..? Типа как здесь и с вашим решением..? Кнопку на аддоновскую карточку не надо, ее пихать некуда, а в список было бы самое то.
Отсутствует