Полезная информация

В мире Mozilla происходит много интересных событий. Но вам не нужно постоянно посещать новостные сайты, чтобы быть в курсе всех изменений. Зайдите на ленту новостей Mozilla Россия.

№1667624-01-2023 16:18:12

choir
Участник
 
Группа: Members
Зарегистрирован: 24-01-2023
Сообщений: 4
UA: Firefox 109.0

Re: Custom Buttons

Сработало, спасибо.

Отсутствует

 

№1667725-01-2023 15:36:18

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 592
UA: Firefox 109.0

Re: Custom Buttons

Dumby, если не трудно, переделайте пожалуйста под UCF.
Для [firefox] 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»

Отсутствует

 

№1667825-01-2023 19:13:28

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2226
UA: Firefox 78.0

Re: Custom Buttons

unter_officer пишет

переделайте пожалуйста под UCF

А какой смысл? Даже если атрибут "crop" будет проставляться,
толку от этого не будет никакого, label испорчен откуда-то отсюда.


Может замени, для начала, в этом стиле
-moz-box-flex: 1 на max-width: 100%

Отсутствует

 

№1667925-01-2023 19:23:16

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1734
UA: Firefox 109.0

Re: Custom Buttons

Dumby пишет

-moz-box-flex: 1 на max-width: 100%

Благодарю!


Win7

Отсутствует

 

№1668025-01-2023 19:34:20

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 592
UA: Firefox 109.0

Re: Custom Buttons

Dumby пишет

Может замени, для начала, в этом стиле
-moz-box-flex: 1 на max-width: 100%

Большое спасибо, то что надо.


«The Truth Is Out There»

Отсутствует

 

№1668126-01-2023 12:32:51

ВВП
Участник
 
Группа: Members
Зарегистрирован: 13-03-2021
Сообщений: 333
UA: Firefox 109.0

Re: Custom Buttons

Dumby
Показать индикатор загрузки DownloadsIndicatorView.onCommand(event);
А ,вот убрать быстро ,как-то не очень... Типа, gCustomizeMode.onDownloadsAutoHideChange(event);

Отсутствует

 

№1668226-01-2023 20:13:01

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2226
UA: Firefox 78.0

Re: Custom Buttons

ВВП пишет

убрать

В смысле с глаз долой?
Если включено browser.download.autohideButton
то просто DownloadsButton.hide();

Отсутствует

 

№1668326-01-2023 22:18:38

ВВП
Участник
 
Группа: Members
Зарегистрирован: 13-03-2021
Сообщений: 333
UA: Firefox 109.0

Re: Custom Buttons

Dumby

Dumby пишет

просто DownloadsButton.hide();

Зер гуд, геноссе !

Отсутствует

 

№1668428-01-2023 00:22:10

ALEX_45_ORP
Участник
 
Группа: Members
Зарегистрирован: 18-01-2018
Сообщений: 162
UA: Firefox 99.0

Re: Custom Buttons

Геноссе ВВП, нихт зер гуд, бог велел делиться )))

Отредактировано ALEX_45_ORP (30-01-2023 21:37:00)


Win 10х64

Отсутствует

 

№1668530-01-2023 21:47:30

ВВП
Участник
 
Группа: Members
Зарегистрирован: 13-03-2021
Сообщений: 333
UA: Firefox 107.0

Re: Custom Buttons

Dumby
А это никак не обойти ? Как прокси, так это SSL_ERROR_BAD_CERT_DOMAIN

Отсутствует

 

№1668630-01-2023 22:24:18

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2226
UA: Firefox 78.0

Re: Custom Buttons

ВВП пишет

А это никак не обойти ? Как прокси, так это SSL_ERROR_BAD_CERT_DOMAIN

Без понятия.
Сколько раз уже говорил,
что я контентским и сетевым делам посторонен,
спрашивать меня про них бесполезно.

Отсутствует

 

№1668730-01-2023 23:48:54

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 592
UA: Firefox 109.0

Re: Custom Buttons

Dumby
Подскажите пожалуйста по кнопочке.


У меня в СВ есть такая кнопка:

CB

Выделить код

Код:

// Очистить историю закрытых вкладок .....
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;
	}
}

Пробую переделать в UCF, как-то так:
UCF

Выделить код

Код:

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); }

Но консоль ругается на эту строчку: SessionStore.canRestoreLastSession = false;
Пишет: ReferenceError: SessionStore is not defined


Пытался подтянуть что-то вроде этого:

SessionStore.sys.mjs

Выделить код

Код:

var SessionStore = ChromeUtils.importESModule("resource:///modules/sessionstore/SessionStore.sys.mjs");

Но ничего не выходит.


«The Truth Is Out There»

Отсутствует

 

№1668831-01-2023 02:04:55

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2226
UA: Firefox 78.0

Re: Custom Buttons

unter_officer пишет

Пишет: 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;

Отсутствует

 

№1668931-01-2023 15:34:21

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 592
UA: Firefox 109.0

Re: Custom Buttons

Dumby
Большое спасибо за помощь!
Теперь всё работает как надо.


«The Truth Is Out There»

Отсутствует

 

№1669002-02-2023 17:06:04

LGS
Участник
 
Группа: Members
Зарегистрирован: 17-09-2022
Сообщений: 101
UA: Firefox 78.0

Re: Custom Buttons

Dumby, можно эту кнопку, которая клонирует кнопки Отключить, Включить, Настройки, Удалить адаптировать под 78+ и UCF..?
На 68esr она сработала:
Aboutaddons.1675341589.png,
правда с небольшими глюками - в "Персонализации" не отображается, соответственно на панель перетаскивать нечего, но, как видно, работает. На 78 кнопка в "Персонализации присутствует, но не пашет. Стиль для отображения дополнений в несколько столбцов использую этот, а в вашем коде поправил
span.cb-cloned-buttons-container {
        display: vertical;
    }
чтобы кнопки вертикально отображались, а то горизонтально как-то не очень смотрится когда "в несколько столбцов".

Отсутствует

 

№1669104-02-2023 08:37:33

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2226
UA: Firefox 78.0

Re: Custom Buttons

LGS пишет

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)

Отсутствует

 

№1669204-02-2023 11:23:45

LGS
Участник
 
Группа: Members
Зарегистрирован: 17-09-2022
Сообщений: 101
UA: Firefox 78.0

Re: Custom Buttons

Dumby пишет

Что-то я сомневаюсь, что это валидное значение для свойства display

У меня, без академических знаний, лишь легкая тень сомнения мелькнула, потому-что в справочнике CSS такого значения нет. Наугад воткнул vertical (вспомнилось из какого-то старого стиля
  -moz-box-orient: vertical) - сработало. А как на это браузер реагирует в плане ошибок я не знаю как посмотреть, консолью пользоваться не особо умею. Получается, что я случайно новое значение для display открыл))

Dumby пишет

Набросок для custom_script.js

Это уже можно "законченным произведением" назвать... с претензией на совершенство:
Aboutaddons78.1675495522.png
Премного благодарен!

То, что на скрине красным выделено, вылечил самостоятельно: в манифесте расширения сократил название - теперь отображается нормально, не "двоит". Не знаю, с точки зрения науки, это правильно или нет, но помогло.

Отредактировано LGS (04-02-2023 12:42:26)

Отсутствует

 

№1669304-02-2023 18:39:39

ВВП
Участник
 
Группа: Members
Зарегистрирован: 13-03-2021
Сообщений: 333
UA: Firefox 107.0

Re: Custom Buttons

Dumby
gBrowser.removeAllTabsBut(gBrowser.selectedTab); Как заменить ? Не работает...

Отсутствует

 

№1669405-02-2023 01:45:08

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 592
UA: Firefox 109.0

Re: Custom Buttons

ВВП пишет

gBrowser.removeAllTabsBut(gBrowser.selectedTab); Как заменить ? Не работает...

А что не работает?
Сделал простенькую кнопку:

Выделить код

Код:

this.onclick = function(event) {
	if (event.button == 0) {
		gBrowser.removeAllTabsBut(gBrowser.selectedTab);
	}
}

При нажатии закрываются все вкладки, кроме активной.


«The Truth Is Out There»

Отсутствует

 

№1669505-02-2023 08:56:36

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2226
UA: Firefox 78.0

Re: Custom Buttons

unter_officer пишет

А что не работает?

Видимо, имеется в виду, что не работает на сборке, а не на обычном 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);
    }
  },


Это в app omni (не gre), то есть в omni.ja, который в папке browser
Но, ещё раз, — лучше держать модули в актуальном состоянии.

Отсутствует

 

№1669605-02-2023 10:36:44

ВВП
Участник
 
Группа: Members
Зарегистрирован: 13-03-2021
Сообщений: 333
UA: Firefox 106.0

Re: Custom Buttons

Dumby
Да,заработало, но id="wrapper-personal-bookmarks" - пропал....Короче, хватит экспериментов, завязываю...

Отсутствует

 

№1669705-02-2023 14:32:53

LGS
Участник
 
Группа: Members
Зарегистрирован: 17-09-2022
Сообщений: 101
UA: Firefox 78.0

Re: Custom Buttons

Dumby, еще одна просьба. Возможно пропустил, но, вроде не попадалось... "приспособить"эту кнопку под 91+ и UCF.

Отсутствует

 

№1669807-02-2023 09:01:27

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2226
UA: Firefox 78.0

Re: Custom Buttons

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)

Отсутствует

 

№1669907-02-2023 10:35:59

LGS
Участник
 
Группа: Members
Зарегистрирован: 17-09-2022
Сообщений: 101
UA: Firefox 78.0

Re: Custom Buttons

Dumby пишет

Давай попробую объединить со скриптом
добавления кнопок на аддонские карточки,
чтобы общий код не повторять для каждого отдельно.

Так еще лучше. Я не стал изначально озвучивать, чтобы скрипты объединить, думал усложнит задачу:
Aboutaddons91.1675754630.png
Благодарю!
И, не сочтите за наглость: в контекстное (popup) аддонов можно добавить пункт "Проверить обновления"..? Типа как здесь и с вашим решением..? Кнопку на аддоновскую карточку не надо, ее пихать некуда, а в список было бы самое то.

Отсутствует

 

№1670007-02-2023 12:56:58

LGS
Участник
 
Группа: Members
Зарегистрирован: 17-09-2022
Сообщений: 101
UA: Firefox 78.0

Re: Custom Buttons

Половину задуманного осилил - пункт меню "Проверить обновления" добавил:
AboutaddonsContext.1675763564.png
Теперь осталось функцию (или как правильно) на него повесить, чтобы заработал. Здесь я бессилен.

Отсутствует

 

Board footer

Powered by PunBB
Modified by Mozilla Russia
Copyright © 2004–2020 Mozilla Russia GitHub mark
Язык отображения форума: [Русский] [English]