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

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

№1630103-04-2022 21:33:15

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

Re: Custom Buttons

Dumby пишет

Custom Buttons 0.0.7.0.0.24

Спасибо!


Add, и Большое спасибо за обновлённый код

Отредактировано kokoss (06-04-2022 22:32:35)


Win7

Отсутствует

 

№1630204-04-2022 11:28:05

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 472
UA: Firefox 95.0

Re: Custom Buttons

Dumby просьба доработать код: авто-обновление вкладки


при клике правой кнопкой по строке с чекбоксом «Обновлять каждые ххх секунд» открыть диалог: «Введите число секунд авто-обновления»
или вместо «Обновлять каждые ххх секунд» сделать подменю, в котором будет несколько вариантов, например строки:
Обновлять каждые 30 секунд, Обновлять каждые 60 секунд, Обновлять каждые 300 секунд, Задать свой период обновления

Отсутствует

 

№1630305-04-2022 20:14:20

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

Re: Custom Buttons

Dumby
В 99 не работает это

скрытый текст

Выделить код

Код:

(async repl => {
	var obj = `{\n  ${
		(await (await fetch("chrome://browser/content/places/controller.js")).text())
			.match(/async _removeRange\(.+?\n\ +}(?=,\n)/s)[0]
			.replace("// This is a common bookmark item.", repl)
	}\n}`
	var ps = await ChromeUtils.compileScript("data:,(" + encodeURIComponent(`${obj => {
		var patch = async ctor => {
			var proto = ctor.prototype, meth = proto?._removeRange;
			meth && Object.assign(proto, obj);
		}
		var key = "PlacesController";
		var desc = Object.getOwnPropertyDescriptor(window, key);
		if (!desc) return;

		var {get} = desc;
		if (get)
			desc.get = () => {
				var val = get();
				patch(val);
				return val;
			},
			Object.defineProperty(window, key, desc);
		else
			patch(desc.value);
	}})(${obj});`));

	var obs = doc => "PlacesController" in doc.ownerGlobal && ps.executeInGlobal(doc);
	var topic = "chrome-document-loaded";
	Services.obs.addObserver(obs, topic);
	Services.obs.addObserver(function quit(s, t) {
		Services.obs.removeObserver(quit, t);
		Services.obs.removeObserver(obs, topic);
	}, "quit-application-granted");
})(
		`$&
        if (!removedFolders.ignore) {
          let info = await PlacesUtils.bookmarks.fetch(node.bookmarkGuid);
          if (
            info?.parentGuid == "${PlacesUtils.bookmarks.toolbarGuid}" &&
            !(removedFolders.ignore ??= Services.prompt.confirm(
              null, null, "       Удалить с панели закладок?"
            ))
          ) {
            totalItems--;
            continue;
          }
        }`
);

Выделить код

Код:

data:image/jpeg;charset=utf-8;base64,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HJI4biEFmy6zkJEmQdww7Ec8/Ic1HPoNjp9i12tpY3clxfzxRxXl+tskUMTlcDMiMzE45yQAORzzxtp461O20vS7BBbtFp1yl1GzBtzlGLKjndygLHjio/8AhMLiW3uLbULOyv7WW5a7WGfzAIZGzu2FHVgDnoSRwD15oA7S88O6XInif+yZrSdbcWslpK16gSLzG+dC5YISORyT0Hc1C3hwR2Hhgw6fHfXlx9qkukhvVMcixsMZkDFFUA8kEemQa4g+JZ/smr2sdvaRQakYzIkcZURiNsqE54HY5yT3OcmrmleONR0yHS4reO1aOwWeNVdCRKsxBdX55HHGMUAdJ4m07TE8JxanY/YBcx35s5TYSzPCw2Fh/recjHVSQQfy4vz6tan4slvdAj0aKwsLOwjuPtSrbq+7ftKnLMzE8Hvk8DsMVg+f70AYXxDff/Z/t5n/ALLXHV0/jV9/2P23/wDstcxQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQB12lXiSWMKqwyiBSO4wMVc8/3rhaKAO68/3o8/3rhaKAO68/3o8/3rhaKAO68/3o8/3rhaKAO68/3o8/3rhaKAO68/3o8/3rhaKAO68/3rnfElyk8sKIwYxg5x74/wAKx6KACiiigArrtKvEksYVVhlECkdxgYrkaKAO68/3o8/3rhaKAO68/wB6PP8AeuFooA7rz/ejz/euFooA7rz/AHo8/wB64WigDuvP96PP964WigDuvP8Aejz/AHrhaKANjxJcpPLCiMGMYOce+P8ACseiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/Z

Отредактировано ВВП (06-04-2022 19:44:29)

Отсутствует

 

№1630406-04-2022 09:08:13

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

Re: Custom Buttons

ВВП, почему в личку не отвечаешь? Может все же поделишься 98 сборкой, или она тоже не очень получилась?

Отредактировано ALEX_45_ORP (06-04-2022 10:44:53)


Win 10х64

Отсутствует

 

№1630506-04-2022 10:45:53

questman
Участник
 
Группа: Members
Зарегистрирован: 05-11-2011
Сообщений: 241
UA: Firefox 93.0

Re: Custom Buttons

Всем добра!
Много лет пользуюсь этой сборкой FF.
http://www1.plala.or.jp/tete009/en-US/software.html
Начиная с 94-ой версии после установки Сustom Buttons интерфейс FF частично становится на английском языке.
Может кто знает как это побороть?

Dumby пишет

Custom Buttons 0.0.7.0.0.24

Спасибо!
После установки этой версии весь интерфейс FF стал на руском языке.

Отсутствует

 

№1630607-04-2022 12:01:32

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

Re: Custom Buttons

Dumby
еще одна шняга с toolpit ? так attributes inspector нажал и все зависло...Как  background: задать :

скрытый текст

Выделить код

Код:

tooltip {
  -moz-appearance: auto;
 
  border-radius: 3px !important;
  border: 1px solid #AEAEAE;
  padding: 2px 3px;
  font-family: system !important;
  font-size: 17px !important;
  max-width: 40em !important;
  font-widht: 900 !important;
   
  background: linear-gradient(#FFFFDB, yellow) !important; 
  color: #000 !important;
  font-style: italic !important;
  font: message-box;
}


Ладно, с этим можно так filter: brightness(70%) contrast(240%) invert(10%) sepia(70%) saturate(250%); И будет желтый.Но "удалить закладку с панели" не работает предупреждение...

Отредактировано ВВП (08-04-2022 10:42:08)

Отсутствует

 

№1630708-04-2022 21:12:25

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

Re: Custom Buttons

Dobrov пишет

или вместо «Обновлять каждые ххх секунд» сделать подменю, в котором будет несколько вариантов, например строки:
Обновлять каждые 30 секунд, Обновлять каждые 60 секунд, Обновлять каждые 300 секунд, Задать свой период обновления

Как-то это всё заморочно.
И непонятно какие менюшки закрывать по кликам.
Ладно, допустим, пока так, сумбурно

скрытый текст

Выделить код

Код:

(async (id, popup, self) => (self = {

	clickInterval: 5*60,
	intervals: [
		10, 15, 30, 60, 3*60, 5*60, 15*60, 30*60, 60*60,
	],
	async init() {
		this.addStyle();
		var dsp = e => this[e.type](e);
		var tc = document.getElementById("tabbrowser-tabs");

		var trgs = [popup, tc, tc, document.getElementById("tabbrowser-tabpanels")];
		var types = ["popupshowing", "TabClose", "SSTabRestored", "EndSwapDocShells"];

		(this.destructor = (meth = "removeEventListener") => types.forEach(
			(type, ind) => trgs[ind][meth](type, dsp, ind == 3)
		))("addEventListener");

		ucf_custom_script_win[id] = this;
		ucf_custom_script_win.unloadlisteners.push(id);

		await SessionStore.promiseAllWindowsRestored;
		for(var tab of gBrowser.tabs)
			tab.linkedPanel || this.maybeInitTab(tab);
	},
	maybeInitTab(tab) {
		var sec = this.sec(tab);
		sec && this.initTab(tab, sec, true);
	},
	mousedown(e) {
		if (e.button) return;
		e.stopImmediatePropagation();
		self.destroyTab(this.closest("tab"));
	},
	initTab(tab, sec, skipSet) {
		skipSet || SessionStore.setCustomTabValue(tab, id, sec);
		var img = document.createXULElement("hbox");
		img.className = id;
		img.onmousedown = this.mousedown;

		tab.throbber.before(img);
		tab.setAttribute(id, setInterval(this.reload, sec * 1e3, tab));
	},
	destroyTab(tab) {
		clearInterval(tab.getAttribute(id));
		SessionStore.deleteCustomTabValue(tab, id);
		tab.removeAttribute(id);
		tab.querySelector("." + id).remove();
	},
	addStyle() {
		var css = `
			tab.tabbrowser-tab[${id}] .${id} {
				width: 16px;
				height: 16px;
				position: relative;
				margin-top: -1px;
				margin-inline-start: -2px;
				margin-inline-end: -14px;
				background-position: top right;
				background-repeat: no-repeat;
				background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAEHSURBVHjaYmQAArWgflEglQrEgUCsAsR3gHg9EM++ta7wNSNIASMjQx/rr7fhEd6WrAbaygy3Hr1l2Hjw+u8Xbz+v/P+foYgFZIKEMG94foARKxfTDwZ3G3UGb6Cgj406a2rrhvDnbz5fZwJZ4W+vyRroacdw4MB+hjt37jA8e/aMYd/2NQzOxrKsIHmQIhU1OWGQ0xiSk5MZVFVVGdasWcPg4eHBYKglDxJWAVl3B+gGE5AV8vLyDLdv3wbTrKysDOuOHgMpugMyaT3IkbeBjgVJqKiogOnbUMeD5JmFNT1ufP3+S2b/mfua7z//YH778RvD1iO3GLoXHwH7DqionZGYcAIIMADkw2lofXkQ/wAAAABJRU5ErkJggg==");
				z-index: 1000;
			}
			tab.tabbrowser-tab[${id}]:-moz-locale-dir(rtl) .${id} {
				background-position: top right;
			}
			tab.tabbrowser-tab[${id}] .tab-icon-image {
				display: -moz-box;
			}
			tab.tabbrowser-tab[${id}][pendingicon] .tab-icon-image {
				visibility: hidden;
			}
			#context_autoreloadTab[checked] > menupopup > :nth-child(2),
			#context_autoreloadTab:not([checked]) > menupopup > :first-child {
				display: none;
			}
			#context_autoreloadTab[checked] > .menu-iconic-left > image {
				fill: currentColor;
				-moz-context-properties: fill;
				list-style-image: url("chrome://global/skin/icons/check.svg");
			}
			/*
			tab.tabbrowser-tab[${id}] .tab-throbber,
			tab.tabbrowser-tab[${id}] .tab-icon-pending,
			tab.tabbrowser-tab[${id}]:not([pendingicon]) .tab-icon-image:not([src],[busy],[pinned],[crashed],[sharing]) {
				display: none;
			}
			*/
		`.replace(/;\s*\n/g, " !important;\n");
		windowUtils.loadSheetUsingURIString(
			"data:text/css," + encodeURIComponent(css), windowUtils.USER_SHEET
		);
	},
	get tab() {
		return TabContextMenu.contextTab;
	},
	sec(tab) {
		return SessionStore.getCustomTabValue(tab, id);
	},
	click(menu) {
		var {tab} = this;
		var has = menu.toggleAttribute("checked");
		has
			? this.initTab(tab, this.clickInterval)
			: this.destroyTab(tab);

		var w = menu.clientWidth;
		this.setLabel(has && self.clickInterval);

		if (this.menupopup.state == "open")
			this.updMenupopup(),
			menu.clientWidth != w && setTimeout(this.move, 50);
	},
	changeInterval(tab, sec) {
		clearInterval(tab.getAttribute(id)),
		SessionStore.setCustomTabValue(tab, id, sec),
		tab.setAttribute(id, setInterval(this.reload, sec * 1e3, tab));
	},
	cmd(e) {
		var {value} = e.target;
		if (value == this.currSec) return;

		var {tab} = this;
		this.setLabel(value);

		if (this.menu.hasAttribute("checked"))
			this.changeInterval(tab, value);
		else
			this.menu.toggleAttribute("checked"),
			this.initTab(tab, value);
	},
	reload(tab) {
		gBrowser.reloadTab(tab);
	},
	get shouldHide() {
		return !this.tab.linkedBrowser.currentURI.scheme.startsWith("http");
	},
	format(sec) {
		var map = new Map();
		// resource://gre/modules/PluralForm.jsm
		var f = n => n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
		var hh = ["", "а", "ов"], ms = ["а", "ы", ""];
		return (this.format = sec => {
			var res = map.get(sec = +sec);
			if (!res) {
				var num, arr = [];
				if ((num = Math.floor(sec / 3600)) > 0)
					sec -= num * 3600,
					arr.push(`${num} час${hh[f(num)]}`);
				if ((num = Math.floor(sec / 60)) > 0)
					sec -= num * 60,
					arr.push(`${num} минут${ms[f(num)]}`);
				sec > 0 && arr.push(`${sec} секунд${ms[f(sec)]}`);
				map.set(sec, res = arr.join(" "));
			}
			return res;
		})(sec);
	},
	async prompt(val) {
		var {tab} = this, sec = this.sec(tab);
		var res = await Services.prompt.asyncPrompt(
			null, Services.prompt.MODAL_TYPE_WINDOW,
			val ? "ЕЩЁ РАЗ:" : "Задать интервал обновления",
			"Введите число секунд авто-обновления",
			val || sec || this.clickInterval, null, null
		);
		if (!res.get("ok")) return;

		var val = res.get("value");
		if (!val) return;
		if (!isFinite(val)) return this.prompt(val);

		var val = String(Math.round(val) || 1);
		sec ? this.changeInterval(tab, val) : this.initTab(tab, val);
	},
	initShadowDOM() {
		delete this.initShadowDOM;
		this.initShadowDOM();

		var df = MozXULElement.parseXULToFragment(
			`<menuitem closemenu="single" label="Не перезагружать"
				oncommand="event.stopPropagation(); parentNode.parentNode.click();"/>
			<menuitem closemenu="single" value="${self.clickInterval}"
				label="${self.format(self.clickInterval)}" type="radio"/>
			<menuitem label="Другой…"
				oncommand="event.stopPropagation(); parentNode.parentNode.linkedObject.prompt();"/>
			<menuseparator/>`
		);
		var menuitem = df.children[1];

		for(var sec of self.intervals) {
			if (sec == self.clickInterval) continue;
			menuitem = menuitem.cloneNode(false);
			menuitem.setAttribute("value", sec);
			menuitem.setAttribute("label", self.format(sec));
			df.append(menuitem);
		}
		this.append(df);
	},
	setLabel(sec) {
		this.menu.setAttribute("label", (this.currSec = sec)
			? `Интервал перезагрузки:   ${this.format(sec)}`
			: "Задать интервал перезагрузки"
		);
	},
	popupshowing(e) {
		if (this.shouldHide) return;
		var df = MozXULElement.parseXULToFragment(
			`<menu id="context_autoreloadTab"
				class="menu-iconic"
				onclick="if (event.target == this) linkedObject.click(this)"
			>
				<menupopup oncommand="parentNode.linkedObject.cmd(event)"/>
			</menu>`
		);
		var menu = this.menu = df.firstChild;
		menu.linkedObject = this;
		var menupopup = this.menupopup = menu.firstChild;
		menupopup.initShadowDOM = this.initShadowDOM;
		popup.querySelector("#context_duplicateTab").after(menu);

		this.clickInterval = String(this.clickInterval);
		this.move = () => menupopup.moveToAnchor(menu, "end_before");

		this.updMenupopup = () => {
			var old = menupopup.querySelector("[checked=true]");
			var cur = this.currSec && menupopup.querySelector(`[value="${this.currSec}"]`);
			if (old != cur)
				old?.removeAttribute("checked"),
				cur && cur.setAttribute("checked", true);
		}
		(this.popupshowing = e => {
			if (e.target == popup) {
				if (menu.hidden = this.shouldHide) return;

				var sec = this.sec(this.tab);
				var has = menu.hasAttribute("checked");
				if (Boolean(sec) ^ has)
					has = !has,
					menu.toggleAttribute("checked");

				var curr = has && sec;
				curr !== this.currSec && this.setLabel(curr);
			}
			else if (e.target == menupopup) this.updMenupopup();
		})(e);
	},
	TabClose(e) {
		var intervalId = e.target.getAttribute(id);
		if (!intervalId) return;
		clearInterval(intervalId);

		var tab = e.detail.adoptedBy;
		tab?.ownerGlobal.ucf_custom_script_win[id].initTab(tab, this.sec(e.target));
	},
	SSTabRestored(e) {
		var tab = e.target;
		tab.hasAttribute(id) || this.maybeInitTab(tab);
	},
	async EndSwapDocShells(e) {
		var br = e.detail, trg = e.target;
		await new Promise(requestAnimationFrame);

		var win = br.ownerGlobal;
		if (!win.closed) return;
		var tab = win.gBrowser.getTabForBrowser(br);
		if (!tab) return;

		var sec = this.sec(tab);
		if (sec)
			tab = gBrowser.getTabForBrowser(trg),
			tab.hasAttribute(id) || this.initTab(tab, sec);
	}
}).init())("ucf-tab-auto-reload", document.getElementById("tabContextMenu"));

ВВП пишет

Как  background: задать

Какой же background, если appearance: auto?
Вот, например, так уже жёлтый

скрытый текст

Выделить код

Код:

tooltip[hasbeenopened]:not(#__attrsInspectorTooltip) {

	appearance: none !important;

	border-radius: 3px !important;
	border-color: #AEAEAE !important;

	font: italic 900 17px system-ui !important;

	color: black !important;
	background-image: linear-gradient(#FFFFDB, yellow) !important; 
}

"удалить закладку с панели" не работает предупреждение

Работает. Проверил на 99.0 и 100.0b3.
Подтверждение появляется, и своё дело делает.

Отсутствует

 

№1630808-04-2022 21:26:14

sonyas75
Участник
 
Группа: Members
Откуда: Ставрополь
Зарегистрирован: 22-03-2011
Сообщений: 557
UA: Firefox 91.0

Re: Custom Buttons

Dumby
спасибо, работает :) а в какой строке отрегулировать отступ слева?
2022-04-08-212459.png

Отсутствует

 

№1630908-04-2022 22:17:53

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

Re: Custom Buttons

Dumby пишет

Работает. Проверил на 99.0 и 100.0b3.

Не работает. чкерт его знает. на чистую ставлю . скрипты- true / ни хера не понимаю...Какой скрипт? Так в 98 работает же..
Может config.js не того ?

Отредактировано ВВП (08-04-2022 22:32:35)

Отсутствует

 

№1631008-04-2022 23:44:30

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

Re: Custom Buttons

sonyas75 пишет

в какой строке отрегулировать отступ слева?

Это, я так понимаю, у них для Win10 такая нескладёха без отступов.
У пункта там место под галку, то есть он такой же, как два нижних на скриншоте.


Если галка не нужна, то можно удалить class="menu-iconic"
и (необязательно) соответствующие строки в стиле.


А если галка нужна, то перед (или после)
#context_autoreloadTab[checked] > menupopup > :nth-child(2),
добавить
#context_autoreloadTab:not([checked]) > .menu-iconic-left,


ВВП пишет

на чистую ставлю . скрипты- true / ни хера не понимаю...Какой скрипт?

Этот скрипт.
Если хочешь, выложи на upload.ee папку user_chrome_files + config.js
тогда скормлю их чистой портабельной и посмотрю.

Отсутствует

 

№1631108-04-2022 23:48:56

sonyas75
Участник
 
Группа: Members
Откуда: Ставрополь
Зарегистрирован: 22-03-2011
Сообщений: 557
UA: Firefox 91.0

Re: Custom Buttons

Dumby
еще раз спасибо, всё фунциклирует как надо :)

скрытый текст
2022-04-08-234942.png
2022-04-08-234745.png

Отредактировано sonyas75 (08-04-2022 23:50:28)

Отсутствует

 

№1631209-04-2022 00:03:14

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

Отсутствует

 

№1631309-04-2022 07:33:17

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

Re: Custom Buttons

ВВП пишет

rar.html

Помилосердствуй!
Я предложил выложить всю папку user_chrome_files целиком,
а у тебя в архиве только папка custom_scripts.
Без остального добра ничего же вообще работать не будет.


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

Отсутствует

 

№1631409-04-2022 08:21:09

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

Re: Custom Buttons

Отсутствует

 

№1631509-04-2022 17:45:40

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

Re: Custom Buttons

ВВП
Да, теперь вижу. UCF обкромсаный и старый.
В новом, загрузку custom_script.js инициирует событие "DOMDocElementInserted",
а в этом старом — "DOMContentLoaded", это позже, поэтому код не успевает
сфетчить controller.js и скомпилировать скрипт до загрузки документа окна браузера.


Непонятно даже как, говоришь, это работало на 98, в таких условиях.
Можно попробовать поискать уже загруженные:
после
var obs = doc => "PlacesController" in doc.ownerGlobal && ps.executeInGlobal(doc);
добавить
for(var {document: d} of Services.wm.getEnumerator(null)) d?.readyState == "complete" && obs(d);

Отсутствует

 

№1631609-04-2022 17:59:21

Okralis
Участник
 
Группа: Members
Зарегистрирован: 11-10-2021
Сообщений: 7
UA: Firefox 99.0

Re: Custom Buttons

Подскажите, после обновления до 99 версии браузера, - отключились все дополнения. Переустановка дополнений помогла, а вот Custom buttons не могу установить, пишет - по видимому повреждено...
2 файла config я добавляю также, и код пробовал что выше писали, все равно не устанавливается и пишет это. Как установить?

Установил, запуская custom_buttons-0.0.7.0.0.24-fx-paxmod. А если custom_buttons-0.0.7.0.0.24-fx-bootstrap запускать, то не устанавливалось.

Отредактировано Okralis (09-04-2022 18:30:52)

Отсутствует

 

№1631709-04-2022 18:36:52

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

Re: Custom Buttons

Dumby
Заработало. А где DOMContentLoaded поменять ? Файлов с этим валом....

Отсутствует

 

№1631809-04-2022 21:17:14

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1644
UA: Firefox 91.0

Re: Custom Buttons

Dumby пишет

Ладно, допустим, пока так, сумбурно

А это подменю в контекстное меню вкладок TST можете добавить?
   
Okralis
https://forum.mozilla-russia.org/viewto … 21#p798621

Отредактировано _zt (09-04-2022 21:20:26)

Отсутствует

 

№1631911-04-2022 09:17:07

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

Re: Custom Buttons

Dumby
Рано радовался. Похожая лажа с Attribute inspector . при левом клике -зависает ...
По-ходу, нет, похоже это Dom Inspector при ср.клике. Нет новой версии ?
Короче, это опять тормоза с JS и это в attributes , пауза большая при вызове DOm Inspector...(СКМ)

Отредактировано ВВП (11-04-2022 13:36:07)

Отсутствует

 

№1632012-04-2022 21:44:07

Andrey_Krropotkin
Участник
 
Группа: Members
Зарегистрирован: 11-11-2011
Сообщений: 484
UA: Firefox 99.0

Re: Custom Buttons

Dumby приветствую, давно не заходил, у тебя по случаю, на 99 нет ли кнопки "Консоль браузера" для боковой панели. В ошибках пишет:

скрытый текст

Выделить код

Код:

Uncaught (in promise) TypeError: this.loader is undefined
    get console/this.console< chrome://custombuttons-context/content/button.js?windowId=Firefox&id=custombuttons-button25@init line 1 > Function:165
    handleEvent chrome://custombuttons-context/content/button.js?windowId=Firefox&id=custombuttons-button25@init line 1 > Function:153
    handleEvent chrome://custombuttons/content/contextBuilder.js:74


В обоих случаях код - (new Function (argNames, code)). apply (oButton, args); не найден и указывает на "var key = "CBBrowserConsolePromise", {wins} = this.loader;"
Вот старый код
скрытый текст

Выделить код

Код:

/*Initialization Code*/
({
	title: "Консоль браузера",
  url: "chrome://devtools/content/webconsole/index.html",

	icon: "chrome://devtools/skin/images/tool-webconsole.svg",
	init() {
		var trg = document.getElementById("browser");
		trg && addEventListener("DOMContentLoaded", this, false, trg);
		var id = "viewBrowserConsoleSidebar";

		var menuitem = this.element("menuitem", {
			type: "checkbox",
			label: this.title,
			id: "menu_browserConsoleSidebar",
			oncommand: `SidebarUI.toggle("${id}");`
		}, document.getElementById("viewSidebarMenu"));

		var btn = this.element("toolbarbutton", {
			type: "checkbox",
			label: this.title,
			id: "sidebar-switcher-browserConsole",
			oncommand: `SidebarUI.show("${id}");`,
			class: "subviewbutton subviewbutton-iconic"
		});
		document.querySelector(
			'toolbarbutton[id^="sidebar-switcher-"] + toolbarseparator'
		).before(btn);

		SidebarUI.sidebars.set(id, {
			url: this.url,
			buttonId: btn.id,
			title: this.title,
			menuId: menuitem.id
		});
		SidebarUI.isOpen && SidebarUI.currentID == id && SidebarUI.selectMenuItem(id);

		var popupset = this.popupset = this.element("popupset", {
			id: `CB${_id.slice(20)}-browserConsole-popupset`
		}, document.documentElement);

		var css = `\
			#${btn.id} > .toolbarbutton-icon,
			#sidebar-box[sidebarcommand="${id}"] > #sidebar-header > #sidebar-switcher-target > #sidebar-icon {
				list-style-image: url(${this.icon});
			}`;
		var str = (cbu.cb || "") + "data:text/css," + encodeURIComponent(css), type = windowUtils.USER_SHEET;
		windowUtils.loadSheetUsingURIString(str, type);

		addDestructor(() => {
			SidebarUI.sidebars.delete(id);
			btn.remove(); menuitem.remove(); popupset.remove();
			windowUtils.removeSheetUsingURIString(str, type);
		});
		parseInt(Services.appinfo.platformVersion) < 73 
			&& "insertFTLIfNeeded" in MozXULElement
			&& MozXULElement.insertFTLIfNeeded("toolkit/main-window/editmenu.ftl");

		self.onclick = e => {
			if (e.button == 2) return;
			if (!e.button && !e.shiftKey) return SidebarUI.toggle(id);
			var st = gBrowser.selectedTab, tab;
			if (!e.ctrlKey) tab = gBrowser.visibleTabs.find(tab => {
				var br = gBrowser.getBrowserForTab(tab);
				return br.currentURI.spec == this.url || (
					"_cachedCurrentURI" in br
					&& br._cachedCurrentURI.spec == this.url
				)
			});
			if (tab == st) return;
			if (!tab) tab = gBrowser.addTrustedTab(this.url);
			gBrowser.moveTabTo(tab, st._tPos + 1);
			gBrowser.selectedTab = tab;
		}
		for(var br of gBrowser.browsers) {
			if (br.currentURI.spec != this.url) continue;
			var doc = br.contentDocument;
			if (doc && (
				doc.readyState == "complete" ||
				doc.readyState == "interactive"
			))
				doc.querySelector(
					"main#app-wrapper,div#output-container"
				).childElementCount
					? this.defineDocPopupset(doc)
					: this.handleEvent({target: doc});
		}
		if (!btn.hasAttribute("checked")) return;
		var doc = SidebarUI.browser.contentDocument;
		if (doc.documentURI != this.url) btn.doCommand();
		else if (doc.readyState == "complete") this.defineDocPopupset(doc);
	},
	defineDocPopupset(doc) {
		this.definePopupset(
			doc.querySelector("popupset") ||
			doc.documentElement.appendChild(doc.createXULElement("popupset"))
		);
	},
	get definePopupset() {
		var append = customElements.get("menuitem")
			? popup => {
				this.popupset.appendChild(popup);
				popup.setAttribute("oncommand", "event.target.cmd()");
				for(var node of [...popup.querySelectorAll("menuitem")]) {
					var menuitem = document.importNode(node, true);
					menuitem.cmd = Services.els.getListenerInfoFor(node)
						.find(inf => inf.type == "command").listenerObject;
					popup.replaceChild(menuitem, node);
				}
				return popup;
			}
			: this.popupset.appendChild.bind(this.popupset);

		delete this.definePopupset;
		return this.definePopupset = popupset => popupset.appendChild = append;
	},
	lss: Services.scriptloader.loadSubScript,
	async handleEvent({target: doc}) {
		if (!doc || doc.documentURI != this.url) return;

		var win = doc.defaultView;
		if (
			win.docShell.name == "toolbox-panel-iframe-webconsole" ||
			doc.DOMContentLoadedEventHandled
		)
			return;
		doc.DOMContentLoadedEventHandled = true;
		"custombuttonsConsole" in win || this.lss(
			"chrome://custombuttons/content/consoleOverlay.js", win
		);
		var cw = win.isChromeWindow, bc;
		if (!cw) {
			if (doc.visibilityState == "hidden") {
				var {focus} = win;
				win.focus = () => win.focus = focus;
			}
			doc.title = this.title;
			var link = doc.createElement("link");
			link.setAttribute("rel", "shortcut icon");
			link.setAttribute("href", this.icon);
			doc.head.prepend(link);

			var br = win.docShell.chromeEventHandler;
			var cmAttr = br.getAttribute("contextmenu");
			cmAttr && br.removeAttribute("contextmenu");
			win.onbeforeunload = () => {
				if (bc) bc.chromeWindow = {close() {}};
				cmAttr && br.setAttribute("contextmenu", cmAttr);
			}
		}
		bc = await this.console(win);
	},
	get console() {
		// Bug 1579090 - WebConsole should handle ObjectFront when needed (for non-primitive Console API args + Evaluation results) (Firefox 73+)
		https://bugzilla.mozilla.org/show_bug.cgi?id=1579090
		var vers = parseInt(Services.appinfo.platformVersion);
		this.bug1579090 = vers > 73 || (vers == 73 && !(
			"_setCurrentURI" in gBrowser.selectedBrowser // https://bugzil.la/1431214
		));
		delete this.console;
		return this.console = this.bug1579090 ? async win => {
			//await this.loader.bcm._browserConsoleInitializing;
			var key = "CBBrowserConsolePromise", {wins} = this.loader;
			win[key] = win.Object.create(null);
			win[key].promise = new win.Promise(resolve => win[key].resolve = resolve);
			win[key].destroy = () => {
				win[key].resolve();
				delete win[key];
				wins.splice(wins.indexOf(win), 1);
			}
			wins.unshift(win);
			wins.length > 1 && await wins[1][key].promise;

			var bc = await new this.loader.console(win).toggleBrowserConsole();
			win[key].destroy();
			return bc;

		} : async win => {
			this.loader.Services.ww.wins.push(win);
			return await new this.loader.HUDService().toggleBrowserConsole();
		}
	},
	get loader() {
		delete this.loader;
		var url = "resource://devtools/shared/Loader.jsm";
		if (this.bug1579090) {
			var g = Cu.import(url, {}), key = "CBBrowserConsoleLoader";
			addDestructor(reason => reason[5] == e && key in g && g[key].destroy());
			if (key in g) return this.loader = g[key];
			var {BrowserConsoleManager} = g.require(
				"devtools/client/webconsole/browser-console-manager"
			);
			return this.loader = g[key] = {
				wins: [],
				bcm: BrowserConsoleManager,
				console: class extends BrowserConsoleManager.constructor {
					constructor(win) {
						super();
						this.win = win;
					}
					openWindow() {
						var {win} = this;
						win.addEventListener("unload", () => {
							win.CBBrowserConsolePromise &&
								win.CBBrowserConsolePromise.destroy();
							this.closeBrowserConsole.call(this);
						}, {once: true});
						delete this.win;
						return win;
					}
				},
				destroy() {
					this.wins = null;
					delete g[key];
				}
			};
		}
		var id = _id + "-browser-console";
		url += "?" + id;
		var loader = {exports: {}}, nsvo = Cu.import(url, loader);
		addDestructor(reason => reason[5] == "e" && Cu.unload(url));

		if (id in nsvo) return this.loader = nsvo[id];

		var dir = "resource://devtools/client/webconsole/";
		try {
			this.lss(dir + "hudservice.js", loader);
		} catch(ex) {
			// Bug 1570320 - Rename hudservice.js into browser-console-manager.js (Firefox 70+)
			// https://bugzilla.mozilla.org/show_bug.cgi?id=1570320
			this.lss(dir + "browser-console-manager.js", loader);
			this.lss("data:,this.HUDService=BrowserConsoleManager", loader);
		}
		var e = new CustomEvent("DOMContentLoaded", {bubbles: false}), ww = loader.Services.ww;
		loader.Services.ww = Cu.getGlobalForObject(nsvo).Object.create(ww, {
			wins: {value: []},
			openWindow: {value: function() {
				var win = this.wins.shift();
				win.setTimeout(() => win.dispatchEvent(e), 0);
				return win;
			}}
		});
		return this.loader = nsvo[id] = loader;
	},
	element(name, attrs, parent) {
		var node = document.createXULElement(name);
		for(var attr in attrs) node.setAttribute(attr, attrs[attr]);
		parent && parent.append(node);
		return node;
	}
}).init();
this.tooltipText = "Консоль браузера" +"\n"+"\n"+
                   "ЛКМ: В боковой панели" +"\n"+
                   "СКМ: В новой вкладке" +"\n"+
                   "ПКМ: Стандартное меню "

Отредактировано Andrey_Krropotkin (12-04-2022 21:47:20)

Отсутствует

 

№1632113-04-2022 09:52:14

Farby
Участник
 
Группа: Members
Зарегистрирован: 21-11-2012
Сообщений: 305
UA: Google 2.1

Re: Custom Buttons

в 99 [firefox] Loader переместили, а может и раньше

Войдите или зарегистрируйтесь, чтобы увидеть скрытый текст.

можно так попробовать, пока Dumby не пришёл.

Выделить код

Код:

..
		// var url = "resource://devtools/shared/Loader.jsm";
		var url, pver = parseInt(Services.appinfo.platformVersion);
		if  (pver < 98)
			url = "resource://devtools/shared/Loader.jsm";
		else
			url=  "resource://devtools/shared/loader/Loader.jsm";

Жизнь иногда такое выкидывает, что хочется подобрать...

Отсутствует

 

№1632213-04-2022 21:26:30

Andrey_Krropotkin
Участник
 
Группа: Members
Зарегистрирован: 11-11-2011
Сообщений: 484
UA: Firefox 99.0

Re: Custom Buttons

Farby большое спасибо, все заработало

Отсутствует

 

№1632314-04-2022 19:54:04

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

Re: Custom Buttons

del

Отредактировано ВВП (15-04-2022 10:49:17)

Отсутствует

 

№1632415-04-2022 21:34:53

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

Re: Custom Buttons

_zt пишет

А это подменю в контекстное меню вкладок TST можете добавить?

Довольно сомнительно.
Вкладки и это контекстное меню в разных окнах, а TST-добро вообще в другом процессе.
Хорошо, попробую. Только для TST, не стыкуется с тем кодом. JSM'ка.

скрытый текст

Выделить код

Код:

var clickInterval = 5*60;
var intervals = [
	10, 15, 30, 60, 3*60,/* 5*60,*/ 15*60, 30*60, 60*60,
];
var name = "TreeStyleTabAutoReloader";
var addonId = "treestyletab@piro.sakura.ne.jp";
var sfx = "ucf-tst-tab-autoreload", id = `extension:${addonId}:${sfx}`;
var sheets = {
	def(name, css) {
		Object.defineProperty(this, name, {configurable: true, get() {
			delete this[name]; return this[name] = this.pre(name, css);
		}});
	},
	pre(name, css) {
		var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
		var rph = ios.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
		var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
		var type = "USER_SHEET";
		return (this.pre = (name, css) => {
			var subst = "tst-autoreload-stylesheet-" + name;
			rph.setSubstitution(subst, ios.newURI("data:text/css," + encodeURIComponent(css)));
			return [sss.preloadSheet(ios.newURI(`resource://${subst}/`), sss[type]), Ci.nsIDOMWindowUtils[type]];
		})(name, css);
	}
};
if (!ChromeUtils.domProcessChild.childID) {
	var EXPORTED_SYMBOLS = [name + "Parent"];

	var ep = "resource://gre/modules/ExtensionParent.jsm";
	var manager = ChromeUtils.import(ep).ExtensionParent.apiManager;
	var tt = manager.global.tabTracker;
	var ss = "resource:///modules/sessionstore/SessionStore.jsm";
	ss = ChromeUtils.import(ss).SessionStore;
	var gsec = tab => ss.getCustomTabValue(tab, id);

	var webExt, addonUUID;
	
	var waitAddon = (e, isAppShutdown) => isAppShutdown || (
		webExt = null, manager.on("ready", onReady)
	);
	var onReady = (e, addon) => {
		if (addon.id != addonId) return;
		manager.off("ready", onReady);
		addon.once("shutdown", waitAddon);
		onAddon(addon);				
	}
	var onAddon = addon => {
		webExt = addon;
		if (addonUUID == addon.uuid) return;

		addonUUID && ChromeUtils.unregisterWindowActor(name);
		ChromeUtils.registerWindowActor(name, {
			remoteTypes: ["extension"],
			parent: {moduleURI: __URI__},
			messageManagerGroups: ["webext-browsers"],
			child: {moduleURI: __URI__, events: {pageshow: {}}},
			matches: [`moz-extension://${addonUUID = addon.uuid}/sidebar/sidebar.html?*`]
		});
	}
	var format = sec => {
		var map = new Map();
		// resource://gre/modules/PluralForm.jsm
		var f = n => n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
		var hh = ["", "а", "ов"], ms = ["а", "ы", ""];
		return (format = sec => {
			var res = map.get(sec = +sec);
			if (!res) {
				var num, arr = [];
				if ((num = Math.floor(sec / 3600)) > 0)
					sec -= num * 3600,
					arr.push(`${num} час${hh[f(num)]}`);
				if ((num = Math.floor(sec / 60)) > 0)
					sec -= num * 60,
					arr.push(`${num} минут${ms[f(num)]}`);
				sec > 0 && arr.push(`${sec} секунд${
					sec > Math.floor(sec) ? "ы" : ms[f(sec)]
				}`);
				map.set(sec, res = arr.join(" "));
			}
			return res;
		})(sec);
	}
	var hasDef = intervals.includes(clickInterval);
	hasDef || intervals.push(clickInterval);
	sheets.def("sb", `
		#context_autoreloadTab:not([checked]) > .menu-iconic-left,${
			hasDef ? "" : "\n\t\t#context_autoreloadTab[checked][def=true] > menupopup > :nth-child(2),"
		}
		#context_autoreloadTab:not([checked]) > menupopup > :first-child {
			display: none !important;
		}
		#context_autoreloadTab[checked] > .menu-iconic-left > image {
			fill: currentColor !important;
			-moz-context-properties: fill !important;
			list-style-image: url("chrome://global/skin/icons/check.svg") !important;
		}
	`);
	clickInterval = String(clickInterval);

	var sym = Symbol(name);
	var TreeStyleTabAutoReloaderParent = class extends JSWindowActorParent {
		actorCreated() {
			var win = this.browsingContext.embedderElement.ownerGlobal;
			var mo = win[sym];
			if (!mo) {
				win.windowUtils.addSheet(...sheets.sb);
				mo = win[sym] = new win.MutationObserver(this.handleMutations);
				var popup = win.document.getElementById("contentAreaContextMenu");
				mo.obs = mo.observe.bind(mo, popup, {childList: true});
				mo.win = win;
			}
			((mo.actor = this).mo = mo).obs();
		}
		didDestroy() {
			this.mo.disconnect();
		}
		get menu() {
			var value = this.mo.menu;
			if (!value) {
				value = this.mo.win.MozXULElement.parseXULToFragment(
					`<menu id="context_autoreloadTab"
						class="menu-iconic"
						onclick="if (event.target == this) linkedObject.click(this);"
					>
						<menupopup oncommand="parentNode.linkedObject.cmd(event);"/>
					</menu>`
				);
				(value = this.mo.menu = value.firstChild).remove();
				value.linkedObject = this;
				(value.popup = value.firstChild).initShadowDOM = this.initShadowDOM;
			}
			return Object.defineProperty(this, "menu", {value}).menu;
		}
		initShadowDOM() {
			delete this.initShadowDOM;
			this.initShadowDOM();

			var df = this.ownerGlobal.MozXULElement.parseXULToFragment(
				`<menuitem closemenu="single" label="Не перезагружать"
					oncommand="event.stopPropagation(); parentNode.parentNode.click();"/>
				<menuitem label="Другой…"
					oncommand="event.stopPropagation(); parentNode.parentNode.linkedObject.prompt();"/>
				<menuseparator/>`
			);
			var doc = this.ownerDocument;

			for(var sec of intervals) {
				var menuitem = doc.createXULElement("menuitem");
				menuitem.setAttribute("type", "radio");
				menuitem.setAttribute("closemenu", "single");
				menuitem.setAttribute("value", sec);
				menuitem.setAttribute("label", format(sec));
				df.append(menuitem);
			}
			hasDef || df.firstChild.after(df.lastChild);
			this.append(df);
			this.parentNode.linkedObject.updMenupopup(this);
			this.setAttribute("onpopupshowing", "parentNode.linkedObject.updMenupopup(this);");
		}
		handleMutations(muts) {
			var cm = this.win.gContextMenu;
			if (cm) for(var mut of muts) for(var node of mut.addedNodes)
				if (node.id == "treestyletab_piro_sakura_ne_jp-menuitem-_context_duplicateTab") {
					var {tabId} = cm.contentData.webExtContextData;
					var tab = tt.getTab(tabId);
					//if (tab?.linkedBrowser.currentURI.scheme.startsWith("http")) {
					if (tab) {
						var {menu} = this.actor;
						menu.tabId = tabId;
						node.after(menu);
						this.actor.maybeSetLabel(tab);
						webExt.apiManager.global.gMenuBuilder.itemsToCleanUp.add(menu);
					}
					break;
				}
		}
		maybeSetLabel(tab) {
			var sec = gsec(tab);
			var has = this.menu.hasAttribute("checked");
			if (Boolean(sec) ^ has)
				has = !has, this.menu.toggleAttribute("checked");

			var curr = has && sec;
			curr !== this.menu.sec && this.setLabel(curr);
		}
		setLabel(sec) {
			this.menu.setAttribute("label", (this.menu.sec = sec)
				? `Интервал перезагрузки:   ${format(sec)}`
				: "Задать интервал перезагрузки"
			);
			hasDef || this.menu.setAttribute("def", sec == clickInterval);
		}
		click(menu) {
			var {tabId} = menu;
			var has = menu.toggleAttribute("checked");
			has
				? this.initTab(tabId, clickInterval)
				: this.destroyTab(tabId);

			var w = menu.clientWidth;
			this.setLabel(has && clickInterval);

			if (menu.popup.state == "open")
				this.updMenupopup(menu.popup),
				menu.clientWidth != w && menu.ownerGlobal.setTimeout(this.move, 50, menu);
		}
		cmd(e) {
			var {value} = e.target;
			if (value == this.menu.sec) return;

			var {tabId} = this.menu;
			this.setLabel(value);

			if (this.menu.hasAttribute("checked"))
				this.changeInterval(tt.getTab(tabId), value);
			else
				this.menu.toggleAttribute("checked"),
				this.initTab(tabId, value);
		}
		changeInterval(tab, sec) {
			var win = tab.ownerGlobal;
			win.clearInterval(tab.getAttribute(sfx));
			ss.setCustomTabValue(tab, id, sec);
			tab.setAttribute(sfx, win.setInterval(bro.reload, sec * 1e3, tab));
		}
		async prompt(val) {
			var {menu} = this, {sec} = menu;
			var {prompt} = menu.ownerGlobal.Services;
			var res = await prompt.asyncPrompt(
				null, prompt.MODAL_TYPE_WINDOW,
				val ? "ЕЩЁ РАЗ:" : "Задать интервал обновления",
				"Введите число секунд авто-обновления",
				val || sec || clickInterval, null, null
			);
			if (!res.get("ok")) return;

			var val = res.get("value");
			if (!val) return;
			if (!isFinite(val)) return this.prompt(val);

			var {tabId} = menu, val = String(Math.round(val) || 1);
			sec ? this.changeInterval(tt.getTab(tabId), val) : this.initTab(tabId, val);
		}
		move(menu) {
			menu.popup.moveToAnchor(menu, "end_before");
		}
		updMenupopup(popup) {
			var old = popup.querySelector("[checked=true]");
			var {sec} = this.menu;
			var cur = sec && popup.querySelector(`[value="${sec}"]`);
			if (old != cur)
				old?.removeAttribute("checked"),
				cur && cur.setAttribute("checked", true);
		}
		initTab(tabId, sec, skipSet) {
			bro.initTab(tt.getTab(tabId), sec);
			this.sendAsyncMessage(tabId, true);
		}
		destroyTab(tabId) {
			bro.destroyTab(tt.getTab(tabId));
			this.sendAsyncMessage(tabId);
		}
		receiveMessage(msg) {
			msg.name && bro.destroyTab(tt.getTab(+msg.name));
		}
	}
	var bro = {
		async observe(win) {
			var tc = win.document.getElementById("tabbrowser-tabs");
			var tp = win.document.getElementById("tabbrowser-tabpanels")
			var types = ["EndSwapDocShells", "TabClose", "SSTabRestored"];

			var destructor = (meth = "removeEventListener") => types.forEach(
				(type, ind) => (ind ? tc : tp)[meth](type, this, ind == 0)
			);
			destructor("addEventListener");

			win.ucf_custom_script_win[id] = {destructor};
			win.ucf_custom_script_win.unloadlisteners.push(id);

			await ss.promiseAllWindowsRestored;
			for(var tab of win.gBrowser.tabs)
				tab.linkedPanel || this.maybeInitTab(tab);
		},
		maybeInitTab(tab) {
			var sec = gsec(tab);
			sec && this.initTab(tab, sec, true);
		},
		handleEvent(e) {
			this[e.type](e);
		},
		reload(tab) {
			tab.ownerGlobal.gBrowser.reloadTab(tab);
		},
		initTab(tab, sec, skipSet) {
			skipSet || ss.setCustomTabValue(tab, id, sec);
			tab.setAttribute(sfx, tab.ownerGlobal.setInterval(this.reload, sec * 1e3, tab));
		},
		destroyTab(tab) {
			tab.ownerGlobal.clearInterval(tab.getAttribute(sfx));
			ss.deleteCustomTabValue(tab, id);
			tab.removeAttribute(sfx);
		},
		TabClose(e) {
			var intervalId = e.target.getAttribute(sfx);
			if (!intervalId) return;
			e.target.ownerGlobal.clearInterval(intervalId);

			var tab = e.detail.adoptedBy;
			tab && this.initTab(tab, gsec(e.target));
		},
		SSTabRestored(e) {
			var tab = e.target;
			tab.hasAttribute(sfx) || this.maybeInitTab(tab);
		},
		async EndSwapDocShells(e) {
			var br = e.detail, trg = e.target, win = br.ownerGlobal;
			await new Promise(win.requestAnimationFrame);

			if (!win.closed) return;
			var tab = win.gBrowser.getTabForBrowser(br);
			if (!tab) return;

			var sec = gsec(tab);
			if (sec)
				tab = trg.ownerGlobal.gBrowser.getTabForBrowser(trg),
				tab.hasAttribute(sfx) || this.initTab(tab, sec);
		}
		
	};
	var topic = "browser-delayed-startup-finished";
	var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);

	obs.addObserver(bro, topic);
	obs.addObserver(function quit(s, t) {
		obs.removeObserver(quit, t);
		obs.removeObserver(bro, topic);
	}, "quit-application-granted");

	var policy = WebExtensionPolicy.getByID(addonId);
	if (policy)
		onAddon(policy.extension),
		policy.extension.once("shutdown", waitAddon);
	else
		waitAddon();

} else {
	var EXPORTED_SYMBOLS = [name + "Child"];

	sheets.def("tst", `
		:root {
			--ar-ind-width: 22px;
		}
		.autoreload-indicator {
			opacity: .6 !important;
			height: 100% !important;
			fill: currentColor !important;
			-moz-context-properties: fill !important;
			min-width: var(--ar-ind-width) !important;
			background: no-repeat center/60% url("chrome://browser/skin/reload.svg") !important;
		}
		.autoreload-indicator:hover {
			opacity: 1 !important;
		}
		tab-item-substance[autoreload] > .extra-items-container.front {
			right: calc(var(--tab-label-end-offset) + var(--ar-ind-width)) !important;
		}
		tab-item.faviconized .autoreload-indicator {
			min-width: 12px !important;
			background-size: 100% !important;
		}
		tab-item.faviconized > tab-item-substance[autoreload] {
			padding-inline-start: 0 !important;
		}
	`);
	var TreeStyleTabAutoReloaderChild = class extends JSWindowActorChild {
		async handleEvent(e) {
			this.sendAsyncMessage("");
			this.stopReload = this.stopReload.bind(this);

			var win = e.target.ownerGlobal;
			win.windowUtils.addSheet(...sheets.tst);

			var opts = {childList: true};
			var allTabs = e.target.getElementById("all-tabs");

			await new Promise(resolve => {
				var mo = new win.MutationObserver(
					() => allTabs.firstElementChild && resolve(mo.disconnect())
				);
				mo.observe(allTabs, opts);
			});
			this.mo = new win.MutationObserver(muts => {
				for(var mut of muts) for(var node of mut.addedNodes) this.check(node);
			});
			var trg = allTabs.firstElementChild;
			this.mo.observe(trg, opts);
			for(var node of trg.children) this.check(node);
		}
		check(node) {
			node.nodeName == "TAB-ITEM" && this.onTab(node);
		}
		async onTab(tab, tabId) {
			var subs = tab.querySelector("tab-item-substance");
			var win = tab.ownerDocument.defaultView.wrappedJSObject;
			if (!tabId) {
				if (subs.hasAttribute("autoreload"))
					subs.removeAttribute("autoreload"),
					subs.querySelector(".autoreload-indicator")?.remove();

				var {tabId} = subs.dataset;
				var sec = await win.browser.sessions.getTabValue(+tabId, sfx);
				if (!sec) return;
			}
			subs.toggleAttribute("autoreload", true);
			var ind = win.document.createElement("span");
			ind.className = "autoreload-indicator";
			ind.title = "Остановить перезагузку";
			ind.tabId = tabId;
			ind.onmousedown = this.stopReload;
			subs.querySelector("tab-closebox").before(ind);
		}
		stopReload(e) {
			if (e.button) return;
			e.stopImmediatePropagation();
			var trg = e.target.wrappedJSObject;
			this.sendAsyncMessage(trg.tabId);
			this.removeIndicator(trg);
		}
		removeIndicator(ind) {
			ind.parentNode.removeAttribute("autoreload");
			ind.remove();
		}
		receiveMessage(msg) {
			var tab = this.contentWindow.document.getElementById("tab-" + msg.name);
			if (tab) msg.data
				? this.onTab(tab, msg.name)
				: this.removeIndicator(tab.querySelector(".autoreload-indicator"));
		}
		didDestroy() {
			this.mo?.disconnect();
		}
	}
}

Farby пишет

в 99 [firefox] Loader переместили, а может и раньше

Да, раньше, в Firefox 96.
Bug 1741369 - Move all loader files under devtools/shared/loader

Отсутствует

 

№1632520-04-2022 02:52:08

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 472
UA: Firefox 97.0

Re: Custom Buttons

Подскажите способ (можно через UCF), чтобы открывать только определённые сайты, то есть чтобы Firefox открывал сайты только из «белого» списка.
Нужно, чтобы блокировка была только в текущем профиле, поэтому не подходят способы блокировки через расширение Block Site или /etc/hosts.


То есть, чтобы при открытии любого сайта (кроме белого списка) показывалось уведомление, что данный сайт запрещён и браузер оставался на текущей странице. Это нужно для машин под Астра Линукс, где браузер -  Firefox 84 и ниже.


P.S. вопрос наверное снят… нашёл тему: Белый список для прокси

Отредактировано Dobrov (20-04-2022 14:30:03)

Отсутствует

 

Board footer

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