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

Общайтесь со знакомыми и друзьями в нашей группе в Контакте.

№32621-05-2022 13:20:13

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

папку для сохранения иконок и ярлыков сайтов привязать к папке загрузок браузера, иначе - рабочий стол

Набросок: три фрагмента (если оседание фавиконов в загрузках не ценность).
Первый и второй удалить, третий добавить.

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

Выделить код

Код:

if (typeof window.saveImageURL != "function") var saveImageURL = internalSave.length == 15
    ? (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
        internalSave(url, null, name, a9, type, a4, a3, null, a6, null, a7, a5, null, priv, prin)
    : (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
        internalSave(url, null, name, a9, type, a4, a3, null, a6, a7, a5, null, priv, prin);

// Сохранить иконку текущего сайта с диалогом сохранения .............
function saveFavicon() {
       var uri = gBrowser.currentURI;
       function getSiteName() {
                  try { var domain = uri.host.split('.') } catch(e) { return "" };
                   domain = (domain.length == 2) ? domain[0] : domain[1]
                   return domain.charAt(0).toUpperCase() + domain.slice(1).split('.')[0] + " ";  
            };
    var url = gBrowser.selectedTab.image;
    url && saveImageURL(
        url, getSiteName(), null, false, false, null, null,
        /^data:(image\/[^;,]+)/i.test(url) ? RegExp.$1.toLowerCase() : Cc["@mozilla.org/mime;1"]
            .getService(Ci.nsIMIMEService).getTypeFromURI(Services.io.newURI(url)),
        null, PrivateBrowsingUtils.isContentWindowPrivate(content || window), document.nodePrincipal
    );
};
Выделить код

Код:

function saveShortcuts() {
var file = Components.classes["@mozilla.org/file/local;1"].
           createInstance(Components.interfaces.nsIFile);
file.initWithPath(folderpath);

if( !file.exists() || !file.isDirectory() ) {   file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0x1B6);}

var savetodir=folderpath+"\\"; 
var urllink=gBrowser.currentURI.spec;
var out=getTabLabel();
var filename=savetodir+out+'.url';
var data="[InternetShortcut]\r\nURL="+urllink+"\r\n";

saveToFile(data, filename);
 // стиль для изображения во всплывающей подсказке ....
      var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
      var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }'));
      sss.loadAndRegisterSheet(uri, 0);
   // подсказка
   var notific = 'Сохранил в: ' + folderpath;
   var image = gBrowser.selectedBrowser.mIconURL;
   Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(image, filename, notific);
};
Выделить код

Код:

async function pick(fileName) {
	try {
		var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);
		await IOUtils.makeDirectory(file.path);
	} catch {
		file = Services.dirsvc.get("Desk", Ci.nsIFile);
	}
	var fp = makeFilePicker();
	fp.init(window, "", fp.modeSave);
	fp.displayDirectory = file;
	fp.defaultString = fileName;
	return await new Promise(fp.open) != fp.returnCancel && fp.file;
}
function saveFavicon() {
	var dn = "favicon";
	var re = /^data:(image\/[^;,]+)/i;
	var ms = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
	(saveFavicon = async () => {
		var url = gBrowser.selectedTab.image;
		if (!url) return;
		if (re.test(url)) {
			try {var name = gBrowser.currentURI.host || dn;} catch {name = dn;}
			name += "." + ms.getPrimaryExtension(RegExp.$1, "ico");
		} else
			var name = Services.io.newURI(url).QueryInterface(Ci.nsIURL).fileName;

		var file = await pick(name);
		file && IOUtils.write(file.path, new Uint8Array(await (await fetch(url)).arrayBuffer()));
	})();
}
function saveShortcuts() {
	var img = self.getAttribute("image");
	var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
	(saveShortcuts = async () => {
		var file = await pick(getTabLabel() + ".url");
		if (file)
			await IOUtils.writeUTF8(file.path, `[InternetShortcut]\r\nURL=${gBrowser.currentURI.spec}\r\n`),
			as.showAlertNotification(
				gBrowser.selectedTab.image || img, file.leafName, "Сохранил в: " + file.parent.path
			);
	})();
}

voqabuhe пишет

Если возможно

Говорят что нет.

Отредактировано Dumby (21-05-2022 13:24:24)

Отсутствует

 

№32721-05-2022 13:39:57

voqabuhe
Участник
 
Группа: Members
Зарегистрирован: 06-12-2011
Сообщений: 3231
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
А сохранение скриптом в .pdf без разбивки на страницы тоже никак?

Отсутствует

 

№32821-05-2022 21:22:00

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Фавиконки не ценность, даже отключены в about:config.
Спасибо, все работает как надо.
   
А для открытия списков URL и сохранения списка URL - адресов выбранных или всех текущих вкладок, есть скрипт? Из буфера обмена / файла, в буфер обмена / файл. А то приходится сохранять папку закладок, потом копировать ее и вставлять в файл, для восстановления делать все в обратном порядке. И хотелось бы еще заголовок видеть перед каждым адресом.

Отредактировано _zt (21-05-2022 21:22:43)

Отсутствует

 

№32925-05-2022 19:34:31

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

voqabuhe пишет

А сохранение скриптом в .pdf без разбивки на страницы тоже никак?

У меня не получилось какой-нибудь browser.js или about:license.
Поднимаешь paperHeight — сначала качество съезжает, а ещё больше — вообще пустота.


Кстати, imgIEncoder способен собрать PNG большего размера чем canvas,
настолько, что даже сам браузер не сможет его отобразить, только подходящий вьювер.
Так что, для любителей экстремальных вещей, можно его попробовать.
Вот, например, автономный код для запуска в окне браузера, типа с консоли, или вкладка Код в CB.
Следует понимать, что на больши́х страницах может случиться ошибка (или даже краш) out of memory.

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

Выделить код

Код:

(async cid => {
	var fp = makeFilePicker();
	fp.init(window, "Сохранить как…", fp.modeSave);
	fp.appendFilter("", "*.png");
	var lab = DownloadPaths.sanitize(gBrowser.selectedTab.label);
	fp.defaultString = lab.slice(0, 50).trimRight() + ".png";
	var res = await new Promise(fp.open);
	if (res == fp.returnCancel || !fp.file) return;
	var {file} = fp;

	var br = gBrowser.selectedBrowser;
	var name = "extrem-encoder:de-xy-dpr-info";
	var url = "data:,(" + encodeURIComponent((de, name) => sendAsyncMessage(
		name, [de.scrollWidth, de.scrollHeight, content.devicePixelRatio]
	)) + `)(content.document.documentElement, "${name}")`;

	var mm = br.messageManager;
	mm.loadFrameScript(url, false);
	var res = await new Promise(r => {
		var lst = msg => mm.removeMessageListener(name, lst, r(msg.data));
		mm.addMessageListener(name, lst);
	});
	var [width, height, k] = res;
	var rectWidth = width;

	width = Math.floor(width * k);
	height = Math.floor(height * k);

	var step = 2000;
	var rectHeight = step / k;

	var canvas = document.createElement("canvas");
	canvas.width = width;
	canvas.height = step;
	var ctx = canvas.getContext("2d");

	var stride = width * 4;
	var encoder = Cc[cid].createInstance(Ci.imgIEncoder);
	var RGBA = encoder.INPUT_FORMAT_RGBA;
	encoder.startImageEncode(width, height, RGBA, "");

	var cwg = br.browsingContext.currentWindowGlobal;
	for(var y = 0; y < height; y += step) {

		var rect = new DOMRect(0, y / k, rectWidth, rectHeight);
		ctx.drawImage(await cwg.drawSnapshot(rect, k, "white"), 0, 0);

		var {data} = ctx.getImageData(0, 0, width, step);
		encoder.addImageFrame(data, data.length, width, step, stride, RGBA, "");
	}
	encoder.endImageEncode();

 	var stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
 	stream.setInputStream(encoder.QueryInterface(Ci.nsIInputStream));
 	var bytes = stream.readByteArray(stream.available());

	await IOUtils.write(file.path, new Uint8Array(bytes));
 	file.reveal();

})("@mozilla.org/image/encoder;2?type=image/png");

_zt пишет

есть скрипт?

Увы, я не знаток существования скриптов.

открытия списков URL и сохранения списка URL

Если формат списка внутренний (только для этого скрипта),
то можно тяп-ляп что-нибудь набросать, например виджет

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

Выделить код

Код:

(async () => CustomizableUI.createWidget({
	id: "799775",
	label: "799775",
	tooltiptext: "799775",

	localized: false,
	marker: "[ucf_tabs_linkset]\n\n",
	onCreated(btn) {
		btn.setAttribute("image", "resource://usercontext-content/pet.svg");
		btn.setAttribute("type", "menu");
		btn.prepend(btn.ownerGlobal.MozXULElement.parseXULToFragment(
			`<menupopup oncommand="creator.cmd(event);">
				<menuitem label="Сохранить адреса вкладок" value="1"/>
				<menuitem label="Сохранить адреса всех вкладок" value="2"/>
				<menuseparator/>
				<menuitem label="Копировать адреса вкладок" value="3"/>
				<menuitem label="Копировать адреса всех вкладок" value="4"/>
				<menuseparator/>
				<menuitem label="Открыть из файла" value="5"/>
				<menuitem label="Открыть из буфера" value="6"/>
			</menupopup>`
		));
		btn.firstChild.creator = this;
	},
	async cmd(e) {
		var win = e.view, num = e.target.value;
		if (num < 5) {
			var tabs = num % 2 ? win.gBrowser.selectedTabs : win.gBrowser.visibleTabs;
			if (num > 2) return this.copy(this.text(tabs));
			var file = await this.pick(
				win, `Linkset ${new Date().toLocaleString("mn").replace(/:/g, "\ua789")} [${tabs.length}] .txt`
			);
			return file && win.IOUtils.writeUTF8(file.path, this.text(tabs));
		}
		if (num == 6) var text = win.readFromClipboard();
		else {
			var file = await this.pick(win);
			if (!file) return;
			var text = await win.IOUtils.readUTF8(file.path);
		}
		if (!text?.startsWith(this.marker)) return;

		var gb = win.gBrowser;
		var arg = {
			index: gb.selectedTab._tPos + 1,
			triggeringPrincipal: win.document.nodePrincipal
		};
		var arr = text.split("\n");
		for(var ind = arr.length - 1; ind > 2; ind -= 3)
			var tab = gb.addTab(arr[ind], arg);
		if (!e.button && !e.shiftKey) gb.selectedTab = tab;
	},
	text(tabs) {
		var res = [];
		for(var tab of tabs) {
			var br = tab.linkedBrowser;
			var url = br.currentURI.spec, beg = url.slice(0, 40);
			var title = br.contentTitle || "untitled";
			if (title.startsWith(beg)) title = beg;
			res.push(title + "\n" + url);
		}
		return this.marker + res.join("\n\n");
	},
	copy(text) {
		var cb = Services.clipboard.kGlobalClipboard;
		var ch = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
		(this.copy = text => ch.copyStringToClipboard(text, cb))(text);
	},
	async pick(win, fileName) {
		try {
			var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);
			await IOUtils.makeDirectory(file.path);
		} catch {
			file = Services.dirsvc.get("Desk", Ci.nsIFile);
		}
		var fp = win.makeFilePicker();
		fp.init(win, "", fileName ? fp.modeSave : fp.modeOpen);
		fp.displayDirectory = file;
		fp.appendFilter("", "*.txt");
		fp.appendFilters(fp.filterAll);
		if (fileName) fp.defaultString = fileName;
		return await new Promise(fp.open) != fp.returnCancel && fp.file;
	}
}))();

Отсутствует

 

№33025-05-2022 21:00:00

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Ну может уже делал.
   
Почти то что нужно.
Только вот список URL для открытия может быть создан не скриптом или скопирован откуда угодно и может быть в любом формате, и с любым текстовым мусором помимо адресов.
А вот формат сохранения идеален.
И еще, вот с этой строкой - `await IOUtils.makeDirectory(file.path);` скрипт упорно лезет в папку загрузок пользователя, без этой строки, как и положено, в папку загрузок назначенную в браузере.

Отсутствует

 

№33126-05-2022 09:28:53

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

откуда угодно … в любом …  с любым

Я же совершенно не разбираюсь в урлах и их списках.
Конкретного бы чего-нибудь дал, лекцию прочёл.
Ладно, написал какую-то лажу, просто чтобы не ничего.

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

Выделить код

Код:

/*
		if (!text?.startsWith(this.marker)) return;

		var gb = win.gBrowser;
		var arg = {
			index: gb.selectedTab._tPos + 1,
			triggeringPrincipal: win.document.nodePrincipal
		};
		var arr = text.split("\n");
		for(var ind = arr.length - 1; ind > 2; ind -= 3)
			var tab = gb.addTab(arr[ind], arg);
		if (!e.button && !e.shiftKey) gb.selectedTab = tab;
	},
*/
		if (!text) return;
		var own = text.startsWith(this.marker);
		if (own) var arr = text.split("\n");
		else {
			var urls = this.parse(text);
			if (!urls?.length) return;
		}
		var gb = win.gBrowser;
		var arg = {
			index: gb.selectedTab._tPos + 1,
			triggeringPrincipal: win.document.nodePrincipal
		};
		if (own)
			for(var ind = arr.length - 1; ind > 2; ind -= 3)
				var tab = gb.addTab(arr[ind], arg);
		else 
			for(var url of urls)
				var tab = gb.addTab(url, arg);
		if (!e.button && !e.shiftKey) gb.selectedTab = tab;
	},
	parse(text) {
		var result = new Set();

		var candidates = new Set(
			text.split(this.space).filter(this.colon)
		);
		for(var str of candidates) {
			var url = this.url(str);
			if (url) result.add(str);
			else {
				for(var splitter of this.splitters) {
					var arr = str.split(splitter).filter(Boolean);
					for(var sub of arr)
						url = this.url(sub),
						url && result.add(url);
				}
			}
		}
		var {size} = result;
		if (size) {
			result = Array.from(result);
			if (size > 1) result.reverse();
			return result;
		}
	},
	space: /\s+/,
	colon: str => str.includes(":"),
	splitters: [",", ";", '"', "'", /[\[\]]/, /()/],
	url(str) {
		try {
			var scheme = Services.io.extractScheme(str);
			if (scheme.length + 1 == str.length || scheme == "default") return;
			var ph = Services.io.getProtocolHandler(scheme);
			if (ph.scheme == scheme)
				return Services.io.newURI(str).spec;
		} catch {}
	},

с этой строкой - `await IOUtils.makeDirectory(file.path);` скрипт упорно лезет в папку загрузок пользователя, без этой строки, как и положено, в папку загрузок назначенную в браузере

Да, мой косяк. Конечно же await win.IOUtils.makeDirectory(file.path);
Это на тот случай, что в настройке путь до несуществующей папки,
что маловероятно, может и правильно, что удалил эту строку.

Отсутствует

 

№33226-05-2022 18:30:43

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Да вроде нормально. Только вот что заметил:
1. место открытия списков - надо бы что бы всегда открывались после последней вкладки
2. ссылку с запятой в конце адреса открывает вместе с запятой
3. markdown не открывает
4. BB-code с заголовком не открывает
   
5. очень желательно вывести в меню опцию "заменять одиночные пробелы процентами" - "%20", но если после пробела идет любой спецсимвол, то обрезать ссылку до этого пробела.
Так как, многие поисковики отдают ссылки на страницы с поисковыми запросами с пробелами, да и вообще пробелы частенько встречаются, в ссылках на файлы, на самодельных сайтах и т.п.
Это не часто нужно и как правило будет мешать получению правильных ссылок, поэтому лучше сделать это как опцию, если такое возможно.
   

Пример списка с перечисленными проблемами

Выделить код

Код:

Создание гиперссылок - Изучение веб-разработки | MDN
https://developer.mozilla.org/ru/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks // afgaga

Управление дополнениями
about:addons

Ресурс
resource://usercontext-content/pet.svg


HTML
<a href="https://en.wikipedia.org/wiki/Percent-encoding">Percent-encoding - Wikipedia</a>

BB-code без заголовка
[url]https://forum.mozilla-russia.org/index.php[/url]


/* Проблемные ссылки */

Ссылка с запятой в конце адреса (открывает вместе с запятой)
https://github.com/Aris-t2/CustomCSSforFx/blob/master/classic/css/tabs/tabs_multiple_lines.css,

BB-code с заголовком (не открывает)
[url=https://forum.mozilla-russia.org/viewtopic.php?id=76642&p=14]UCF-скрипты на этом форуме | Форум Mozilla Россия[/url]

markdown 1 (не открывает)
[Ссылка на корень сайта](https://planshet-info.ru/kompjutery/ssylka-na-koren-sajta)

markdown 2 (не открывает)
![Image and Preview Themes on the toolbar](https://markdownmonster.west-wind.com/docs/images/EditorPreviewThemeUi.png) 

Ссылка с пробелами (обрезает по первому пробелу)
https://yandex.ru/yandsearch?text=команда на копирование файлов и папок в bat&lr=213


ps^ Исправил пост, сам пытался парсер править и сломал BB-code без заголовка.

Отредактировано _zt (26-05-2022 18:53:23)

Отсутствует

 

№33327-05-2022 09:02:28

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt
Хорошо, попробую учесть.

если после пробела идет любой спецсимвол

А что за спецсимволы? Написал так: singleSpace: / (?![\s"])/g,
то есть только «\s» и «"», не знаю что ещё.

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

Выделить код

Код:

//.......
	onCreated(btn) {
		btn.setAttribute("image", "resource://usercontext-content/pet.svg");
		btn.setAttribute("type", "menu");
		btn.prepend(btn.ownerGlobal.MozXULElement.parseXULToFragment(
			`<menupopup oncommand="creator.cmd(event);" onpopupshowing="creator.check(this.lastChild);">
				<menuitem label="Сохранить адреса вкладок" value="1"/>
				<menuitem label="Сохранить адреса всех вкладок" value="2"/>
				<menuseparator/>
				<menuitem label="Копировать адреса вкладок" value="3"/>
				<menuitem label="Копировать адреса всех вкладок" value="4"/>
				<menuseparator/>
				<menuitem label="Открыть из файла" value="5"/>
				<menuitem label="Открыть из буфера" value="6"/>
				<menuitem label="Заменять одиночные пробелы процентами" closemenu="none" type="checkbox" value="7"/>
			</menupopup>`
		));
		btn.firstChild.creator = this;
	},
	check(item) {
		var pref = "ucf.linkset-widget.replspace";
		this.checked = Services.prefs.getBoolPref(pref, false);
		this.setPref = Services.prefs.setBoolPref.bind(null, pref);
		(this.check = item => {
			this.checked ? item.setAttribute("checked", true) : item.removeAttribute("checked");
		})(item);
	},
	singleSpace: / (?![\s"])/g,
	async cmd(e) {
		var num = e.target.value;
		if (num == 7)
			return this.setPref(this.checked = e.target.hasAttribute("checked"));
		var win = e.view;
		if (num < 5) {
			var tabs = num % 2 ? win.gBrowser.selectedTabs : win.gBrowser.visibleTabs;
			if (num > 2) return this.copy(this.text(tabs));
			var file = await this.pick(
				win, `Linkset ${new Date().toLocaleString("mn").replace(/:/g, "\ua789")} [${tabs.length}] .txt`
			);
			return file && win.IOUtils.writeUTF8(file.path, this.text(tabs));
		}
		if (num == 6) var text = win.readFromClipboard();
		else {
			var file = await this.pick(win);
			if (!file) return;
			var text = await win.IOUtils.readUTF8(file.path);
		}
		if (!text) return;
		// if (!text || text.length > 500_000) return; // limit?

		var own = text.startsWith(this.marker);
		if (this.checked && !own) text = text.replace(this.singleSpace, "%20");

		var gb = win.gBrowser, tl = gb.visibleTabs.length;
		if (own)
			for(var ind = 3, arr = text.split("\n"), len = arr.length; ind < len; ind += 3)
				gb.addTrustedTab(arr[ind]);
		else {
			var urls = this.parse(text);
			if (urls?.size) for(var url of urls) gb.addTrustedTab(url);
		}
		if (!e.button && !e.shiftKey) gb.selectedTab = gb.visibleTabs[tl];
	},
	parse(text) {
		var result = new Set();

		var candidates = new Set(
			text.split(this.space).filter(this.colon)
		);
		for(var str of candidates) {
			var url = this.url(str);
			if (url) result.add(str);
			else {
				var bb = true;
				for(var splitter of this.splitters) {
					var arr = str.split(splitter).filter(this.colon);
					for(var sub of arr) {
						if (bb) { // []
							var ind = sub.indexOf("=");
							if (ind != -1 && ind < sub.indexOf(":"))
								sub = sub.slice(ind + 1);
						}
						url = this.url(sub);
						url && result.add(url);
					}
					bb = false;
				}
			}
		}
		// console log instead of open
		//if (true) return Services.console.logStringMessage(Array.from(result).join("\n"));

		//var {size} = result;
		//if (size > 100 && !Services.prompt.confirm(null, null, `Количество вкладок: ${size}! Открыть?`)) return; // limit?

		return result;
	},
	space: /\s+/,
	colon: str => str.includes(":"),
	splitters: [/[\[\]]/, /[()]/, ",", ";", '"', "'"],

	unwanedEnds: /,$/,
	url(str) {
		try {
			var scheme = Services.io.extractScheme(str);
			if (scheme.length + 1 == str.length || scheme == "default") return;
			var ph = Services.io.getProtocolHandler(scheme);
			if (ph.scheme == scheme)
				return Services.io.newURI(str.replace(this.unwanedEnds, "")).spec;
		} catch {}
	},
	text(tabs) {
		var res = [];
		for(var tab of tabs) {
			var br = tab.linkedBrowser;
			var url = br.currentURI.spec, beg = url.slice(0, 40);
			var title = br.contentTitle || "untitled";
			if (title.startsWith(beg)) title = beg;
			res.push(title + "\n" + url);
		}
		return this.marker + res.join("\n\n");
	},
	copy(text) {
		var cb = Services.clipboard.kGlobalClipboard;
		var ch = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
		(this.copy = text => ch.copyStringToClipboard(text, cb))(text);
	},
	async pick(win, fileName) {
		try {
			var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);
			await win.IOUtils.makeDirectory(file.path);
		} catch {
			file = Services.dirsvc.get("Desk", Ci.nsIFile);
		}
		var fp = win.makeFilePicker();
		fp.init(win, "", fileName ? fp.modeSave : fp.modeOpen);
		fp.displayDirectory = file;
		fp.appendFilter("", "*.txt");
		fp.appendFilters(fp.filterAll);
		if (fileName) fp.defaultString = fileName;
		return await new Promise(fp.open) != fp.returnCancel && fp.file;
	}
}))();

Отсутствует

 

№33427-05-2022 14:32:14

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Да почти любой спецсимвол, кроме, пожалуй, скобок (и точка под вопросом). Так как есть нормально, потом всегда можно будет изменить.
   
На мой взгляд осталось два момента...
1. Не открывает ANSI файлы, а это стандартная кодировка Windows.
2. Неверно открывает URL с запятой в конце. При копировании со страниц адресов оформленных тегами (адрес-адрес) они копируются с прилипшей запятой:

Выделить код

Код:

<a href="https://en.wikipedia.org/">https://en.wikipedia.org/</a>,
[https://en.wikipedia.org/](https://en.wikipedia.org/),
[url=https://en.wikipedia.org/]https://en.wikipedia.org/[/url],

Всегда получается "https://en.wikipedia.org/," при копировании.
   
Кстати, там может быть и точка с запятой. Может по аналогии с singleSpace сделать, строку с перечислением отсекающих символов?
Даже не символов, а группы символов, например: ,\s ;\s
   
А в singleSpace: / (?![\s"... экранировать символы нужно и какие, или вообще можно все экранировать?

Отредактировано _zt (27-05-2022 15:07:51)

Отсутствует

 

№33529-05-2022 12:41:57

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

Неверно открывает URL с запятой в конце.

Да, есть опечатки в коде.
Про копирование не понял. Поскольку код не занимается
копированием со страниц, то, видимо, это объяснение откуда что берётся.
Точку с запятой добавил в unwantedEnds: /[,;]$/,

Не открывает ANSI файлы, а это стандартная кодировка Windows.

Насколько мне известно, в Firefox нет API для определения кодировки.
Самое простое так: пытаемся прочитать как UTF-8, если ошибка,
тогда читаем бинарную строку и конвертируем в Windows-1251.

или

Есть ещё такой жуткий вариант: загружаем добро в невидимое окно как документ,
где Firefox сам определит кодировку по содержимому, и забираем результат.
В многопроцессном режиме, естественно, грузится не захочет, поэтому ещё
и свой протокол надо регистрировать. Ну и в консоли будет спам, что мол
кодировка не указана, что ожидаемо. Вобщем, только на крайний случай,
если первый вариант не подойдёт.

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

Выделить код

Код:

//.......
	async cmd(e) {
		var num = e.target.value;
		if (num == 7)
			return this.setPref(this.checked = e.target.hasAttribute("checked"));
		var win = e.view;
		if (num < 5) {
			var tabs = num % 2 ? win.gBrowser.selectedTabs : win.gBrowser.visibleTabs;
			if (num > 2) return this.copy(this.text(tabs));
			var file = await this.pick(
				win, `Linkset ${new Date().toLocaleString("mn").replace(/:/g, "\ua789")} [${tabs.length}] .txt`
			);
			return file && win.IOUtils.writeUTF8(file.path, this.text(tabs));
		}
		if (num == 6) var text = win.readFromClipboard();
		else {
			var file = await this.pick(win);
			if (!file) return;
			var text = await this.read(file);
		}
		if (!text) return;
		// if (!text || text.length > 500_000) return; // limit?

		var own = text.startsWith(this.marker);
		if (this.checked && !own) text = text.replace(this.singleSpace, "%20");

		var gb = win.gBrowser, tl = gb.visibleTabs.length;
		if (own)
			for(var ind = 3, arr = text.split("\n"), len = arr.length; ind < len; ind += 3)
				gb.addTrustedTab(arr[ind]);
		else {
			var urls = this.parse(text);
			if (urls?.size) for(var url of urls) gb.addTrustedTab(url);
		}
		if (!e.button && !e.shiftKey) gb.selectedTab = gb.visibleTabs[tl];
	},
	read(file) {
		var read1251 = async file => {
			var suc = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
				.createInstance(Ci.nsIScriptableUnicodeConverter);
			suc.charset = "windows-1251";
			var reader = new FileReader();

			return (read1251 = async file => {
				reader.readAsBinaryString(file);
				await new Promise(resolve => reader.onloadend = resolve);
				return suc.ConvertToUnicode(reader.result);
			})(file);
		}
		var {IOUtils} = Cu.getGlobalForObject(Cu);
		return (this.read = async file => {
			try {return await IOUtils.readUTF8(file.path);}
			catch {return read1251(file);}
		})(file);
	},
	parse(text) {
		var result = new Set();

		var candidates = new Set(
			text.split(this.space).filter(this.colon)
		);
		for(var str of candidates) {
			var url = this.url(str);
			if (url) result.add(url);
			else {
				var bb = true;
				for(var splitter of this.splitters) {
					var arr = str.split(splitter).filter(this.colon);
					for(var sub of arr) {
						if (bb) { // []
							var ind = sub.indexOf("=");
							if (ind != -1 && ind < sub.indexOf(":"))
								sub = sub.slice(ind + 1);
						}
						url = this.url(sub);
						url && result.add(url);
					}
					bb = false;
				}
			}
		}
		// console log instead of open
		//if (true) return Services.console.logStringMessage(Array.from(result).join("\n"));

		//var {size} = result;
		//if (size > 100 && !Services.prompt.confirm(null, null, `Количество вкладок: ${size}! Открыть?`)) return; // limit?

		return result;
	},
	space: /\s+/,
	colon: str => str.includes(":"),
	splitters: [/[\[\]]/, /[()]/, ",", ";", '"', "'"],

	unwantedEnds: /[,;]$/,
	url(str) {
		try {
			var scheme = Services.io.extractScheme(str);
			if (scheme.length + 1 == str.length || scheme == "default") return;
			var ph = Services.io.getProtocolHandler(scheme);
			if (ph.scheme == scheme)
				return Services.io.newURI(str.replace(this.unwantedEnds, "")).spec;
		} catch {}
	},
	text(tabs) {
		var res = [];
		for(var tab of tabs) {
			var br = tab.linkedBrowser;
			var url = br.currentURI.spec, beg = url.slice(0, 40);
			var title = br.contentTitle || "untitled";
			if (title.startsWith(beg)) title = beg;
			res.push(title + "\n" + url);
		}
		return this.marker + res.join("\n\n");
	},
	copy(text) {
		var cb = Services.clipboard.kGlobalClipboard;
		var ch = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
		(this.copy = text => ch.copyStringToClipboard(text, cb))(text);
	},
	async pick(win, fileName) {
		try {
			var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);
			await win.IOUtils.makeDirectory(file.path);
		} catch {
			file = Services.dirsvc.get("Desk", Ci.nsIFile);
		}
		var fp = win.makeFilePicker();
		fp.init(win, "", fileName ? fp.modeSave : fp.modeOpen);
		fp.displayDirectory = file;
		fp.appendFilter("", "*.txt");
		fp.appendFilters(fp.filterAll);
		if (fileName) fp.defaultString = fileName;
		if (await new Promise(fp.open) == fp.returnCancel) return;
		if (fileName) var file = fp.file;
		else {
			var file = fp.domFileOrDirectory;
			file.path = fp.file.path;
		}
		return file;
	}
}))();

экранировать символы нужно и какие, или вообще можно все экранировать?

Ой, даже затрудняюсь ответить.
Нужно экранировать те, которые требуется включить в класс символов буквально,
чтобы соотетствовали сами себе, но без экранирования будут иметь другой смысл.


А можно экранировать, наоборот, те, которые при экранировании не образуют другой смысл.
Например s соответствует букве «эс», а \s соответствует любому юникодному символу-разделителю,
но z соответствует букве «зэт», и \z тоже соответствует букве «зэт».

Отсутствует

 

№33630-05-2022 02:45:58

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby пишет

Про копирование не понял.

Это не про скрипт, это про список, а он может быть откуда угодно, в том числе скопирован со страницы.
   

Dumby пишет

Есть ещё такой жуткий вариант

Как то сложно все. Не надо наверное, я потестирую то что есть.
   
Не нравится мне как это работает - "if (url) result.add(url);" , окно группировки одновременно открытых вкладок TST растягивается во все окно браузера по ширине. Причем, все равно что открываешь, ansi или utf8. В предыдущем варианте текст url не шифровался и окно не растягивало. Речь про адреса с utf8 символами, например, приведенный выше яндекс. Можно это поправить? Может обратную дешифровку сделать при "выводе" из скрипта?

Отредактировано _zt (30-05-2022 03:22:34)

Отсутствует

 

№33730-05-2022 09:38:10

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

Может обратную дешифровку сделать при "выводе" из скрипта?

Если именно при открытии вкладок, то можно так попробовать
(это если и для своего, и для сторонних форматов).

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

Выделить код

Код:

/*
		if (own)
			for(var ind = 3, arr = text.split("\n"), len = arr.length; ind < len; ind += 3)
				gb.addTrustedTab(arr[ind]);
		else {
			var urls = this.parse(text);
			if (urls?.size) for(var url of urls) gb.addTrustedTab(url);
		}
		if (!e.button && !e.shiftKey) gb.selectedTab = gb.visibleTabs[tl];
	},
*/
		if (own)
			for(var ind = 3, arr = text.split("\n"), len = arr.length; ind < len; ind += 3)
				gb.addTrustedTab(this.decode(arr[ind]));
		else {
			var urls = this.parse(text);
			if (urls?.size) for(var url of urls) gb.addTrustedTab(this.decode(url));
		}
		if (!e.button && !e.shiftKey) gb.selectedTab = gb.visibleTabs[tl];
	},
	decode: url => url.startsWith("data:") ? url : decodeURI(url),


А так-то, было бы неплохо самому Автору дополнения рассмотреть
возможность ограничения ширины списка адресов, а то у меня тут
попался data:… адрес, так окно расколбасило не просто «во все окно браузера по ширине»,
а далеко за пределы экрана, овер шестнадцать тысяч (!) пикселей.
Ну или пользовательский смирительный стиль какой-нибудь запилить.

Отсутствует

 

№33830-05-2022 23:23:42

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Спасибо, теперь нормально.
   

Dumby пишет

смирительный стиль

Ну так как то.

userContent.css

Выделить код

Код:

@-moz-document url-prefix(moz-extension://uuid) {
/* Не позволять растягивать дополнительные окна больше заданного размера */
.rich-confirm-dialog {
    max-width: 800px !important;
}
}

Отредактировано _zt (30-05-2022 23:26:37)

Отсутствует

 

№33931-05-2022 04:26:32

voqabuhe
Участник
 
Группа: Members
Зарегистрирован: 06-12-2011
Сообщений: 3231
UA: Firefox 101.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
[firefox] 101 в расширение add_toolbar_buttons.2021.9.5.xpi  от Vitaliy V. перестала полноценно работать кнопка Дополнения, не открывается список. Можешь поправить? Или хотя бы скрипт починить из этого расширения №9229?

Отредактировано voqabuhe (31-05-2022 05:32:01)

Отсутствует

 

№34031-05-2022 08:03:32

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

voqabuhe пишет

перестала полноценно работать кнопка Дополнения, не открывается список

ChromeUtils.import(…, null) сто лет как считался "не по понятиям".
Может замени в parent.js

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

Выделить код

Код:

/*
XPCOMUtils.defineLazyGetter(this, "GlobalManager", () => {
    const { GlobalManager } = ChromeUtils.import("resource://gre/modules/Extension.jsm", null);
    return GlobalManager;
});
*/
XPCOMUtils.defineLazyGetter(this, "GlobalManager", () =>
    ChromeUtils.import("resource://gre/modules/ExtensionParent.jsm").ExtensionParent.GlobalManager
);

Отсутствует

 

№34131-05-2022 08:44:26

voqabuhe
Участник
 
Группа: Members
Зарегистрирован: 06-12-2011
Сообщений: 3231
UA: Firefox 101.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby

Dumby пишет

ChromeUtils.import(…, null) сто лет как считался "не по понятиям".
Может замени в parent.js

Гениально! Спасибо!

Отсутствует

 

№34231-05-2022 17:04:45

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby пишет

Может замени в parent.js
скрытый текст

Благодарю :beer:


Win7

Отсутствует

 

№34301-06-2022 01:36:31

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
На [firefox] 102 превьюшки TST улетели в край экрана, можете поправить.

Отсутствует

 

№34401-06-2022 18:17:57

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

можете поправить

Следуем за ними.

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

Выделить код

Код:

/*
			var z = win.windowUtils.screenPixelsPerCSSPixel;
*/
			var z = win.devicePixelRatio;

Отсутствует

 

№34502-06-2022 19:17:32

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Спасибо. Трудно самому такое найти, особенно когда не знаешь чего искать.
   
Этот скрипт не позволяет запустить [firefox] 102, если в scriptschrome: >> load:, а если в  scriptsallchrome: >> load: - крашит [firefox] при вызове соответствующего окна / панели (places\/bookmarksSidebar\.xhtml или places\/places\.xhtml).

Отсутствует

 

№34602-06-2022 21:19:50

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

крашит

Ну да, я упоминал. Если грузить скрипт снаружи в объект
глобального системного объекта, то, на ранних бетах и найтли,
разрабы валят пользователю браузер.


Это не касается доживающих последние времена NSVO.
Но Cu.import() больше таковые не возвращает.


Пока сам Cu.import() ещё с нами, можно так попробовать

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

Выделить код

Код:

/*
	if (!g[key]) {
		Services.scriptloader.loadSubScript(
			`data:,this.${key}=TransactionsHistory.proxifiedToRaw;`, g
		);
		var raws = g[key];
*/
	var raws = g.TransactionsHistory?.proxifiedToRaw;
	if (raws) g = raws;
	if (!g[key]) {
		if (!raws) {
			Services.scriptloader.loadSubScript(
				`data:,this.${key}=TransactionsHistory.proxifiedToRaw;`, g
			);
			raws = g[key];
		}

Отсутствует

 

№34703-06-2022 00:10:35

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Работает, спасибо. Эта правка до esr доживет или неизвестно?

Отсутствует

 

№34803-06-2022 08:02:23

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

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

до esr доживет или неизвестно?

Так 102 всё уже, готова. Почти весь отвал делается в Nightly.
Бывают, конечно, исключения, но это редкость.

Отсутствует

 

№34906-06-2022 11:54:42

xrun1
Участник
 
Группа: Members
Зарегистрирован: 12-12-2013
Сообщений: 1160
UA: Firefox 101.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

В [firefox] 101 (может и раньше) отвалилась кнопка "Дополнения" из расширения Add Toolbar Buttons.
Была такая отдельно от 18.09.2020

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

Выделить код

Код:

try {(() => {
    var id = "ucf-aom-button",
    label = "Дополнения",
    tooltiptext = "ЛКМ: Меню дополнений\nShift+ЛКМ: Меню дополнений + открыть менеджер\nСКМ: Открыть менеджер дополнений",
    img = "data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' height='16' width='16' viewBox='0 0 48 48'><g><rect x='0' y='0' width='48' height='48' rx='3' ry='3' style='fill:rgb(0, 120, 173);'/><path style='opacity:0.25;fill:black;' d='M 24,4.5 18,12 3,23.7 12,32.7 3.9,44.1 7.8,48 H 45 C 46.7,48 48,46.7 48,45 V 26.1 L 34.8,12.9 31.8,12.3 Z'/><path style='fill:white;' d='M 19.88,3 C 16.93,3 14.55,4.662 14.55,6.701 14.63,7.474 15.11,8.438 15.37,8.762 16.59,10.41 16.59,11.44 16.29,12.06 H 6.299 C 4.476,12.06 3,13.53 3,15.35 V 23.68 C 3.625,24 4.65,24 6.299,22.77 6.625,22.52 7.587,22.02 8.363,21.94 10.4,21.94 12.06,24.35 12.06,27.29 12.06,30.24 10.4,32.65 8.363,32.65 7.725,32.63 6.774,32.07 6.299,31.82 4.65,30.59 3.625,30.59 3,30.91 V 41.71 C 3,43.53 4.476,45 6.299,45 H 19.58 C 19.88,44.38 19.88,43.35 18.65,41.71 18.4,41.38 17.91,40.42 17.82,39.65 17.82,37.6 20.23,35.94 23.18,35.94 26.14,35.94 28.55,37.6 28.55,39.65 28.53,40.28 27.97,41.23 27.71,41.71 26.47,43.35 26.47,44.38 26.79,45 H 32.65 C 34.47,45 35.96,43.53 35.96,41.71 V 32.55 C 36.56,32.23 37.59,32.23 39.23,33.47 39.72,33.73 40.68,34.29 41.29,34.29 43.35,34.29 45,31.91 45,28.94 45,25.99 43.35,23.59 41.29,23.59 40.54,23.67 39.58,24.17 39.23,24.41 37.59,25.65 36.56,25.65 35.96,25.33 V 15.35 C 35.96,13.53 34.47,12.06 32.65,12.06 H 23.49 C 23.19,11.44 23.19,10.41 24.41,8.762 24.66,8.287 25.22,7.337 25.23,6.713 25.23,4.662 22.85,3 19.88,3' /></g></svg>",
    checked = "data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' height='16' width='16'><path d='M 4,5 7.5,8.5 12,4 V 8 L 8,12 H 7 L 4,9 Z' style='fill:white'/></svg>",
    show_version = true,
    show_description = true,
    user_permissions = true,
    show_hidden = true,
    show_disabled = true,
    enabled_first = true,
    exceptions_listset = new Set([

    ]);
    exceptions_type_listset = new Set([

    ]);
    if (!("AddonManager" in this))
        ChromeUtils.defineModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");
    if (!("GlobalManager" in this))
        XPCOMUtils.defineLazyGetter(this, "GlobalManager", () => {
            const { GlobalManager } = ChromeUtils.import("resource://gre/modules/Extension.jsm", null);
            return GlobalManager;
        });
    var extensionOptionsMenu = {
        get alertsService() {
            delete this.alertsService;
            return this.alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
        },
        get clipboardHelp() {
            delete this.clipboardHelp;
            return this.clipboardHelp = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
        },
        get exceptions_type_listarr() {
            delete this.exceptions_type_listarr;
            var arr = ["extension", "theme", "locale", "dictionary"];
            if (!exceptions_type_listset.size)
                return this.exceptions_type_listarr = arr;
            return this.exceptions_type_listarr = arr.filter(type => !exceptions_type_listset.has(type));
        },
        populateMenu: async function(e) {
            var popup = e.target, doc = e.view.document;
            var addons = await AddonManager.getAddonsByTypes(this.exceptions_type_listarr);
            var addonsMap = new WeakMap(),
            setAttributesMenu = (mi, addon, extension) => {
                var permissions, uuid,
                props = {
                    label: `${addon.name}${show_version ? ` ${addon.version}` : ""}`,
                    class: "menuitem-iconic",
                    tooltiptext: `${(show_description && addon.description) ? `${addon.description}\n` : ""}ID: ${addon.id}${addon.isActive && (uuid = extension?.uuid) ? `\nUUID: ${uuid}` : ""}${(user_permissions && (permissions = addon.userPermissions?.permissions)?.length) ? `\nРазрешения: ${permissions.join(", ")}` : ""}\n${addon.optionsURL ? "\nЛКМ: Настройки" : ""}\nCtrl+ЛКМ: Копировать ID${uuid ? "\nShift+ЛКМ: Копировать UUID" : ""}${addon.creator?.url ? "\nCtrl+Shift+ЛКМ: Автор" : ""}${addon.homepageURL ? "\nСКМ: Домашняя страница" : ""}${!addon.isBuiltin ? "\nCtrl+СКМ: Просмотр источника" : ""}\nShift+СКМ: Просмотр источника во вкладке\nПКМ: Включить/Отключить${(!addon.isSystem && !addon.isBuiltin) ? "\nCtrl+ПКМ: Удалить" : ""}`,
                };
                for (let p in props)
                    mi.setAttribute(p, props[p]);
                if (addon.iconURL)
                    mi.setAttribute("image", addon.iconURL);
                var cls = mi.classList;
                addon.isActive ? cls.remove("ucf-disabled") : cls.add("ucf-disabled");
                addon.optionsURL ? cls.remove("ucf-notoptions") : cls.add("ucf-notoptions");
                addon.isSystem ? cls.add("ucf-system") : cls.remove("ucf-system");
                cls.add(`ucf-type-${addon.type}`);
            };
            addons.filter(a => !(a.iconURL || "").startsWith("resource://search-extensions/")).sort((a, b) => {
                var ka = `${(enabled_first ? a.isActive ? "0" : "1" : "")}${a.type || ""}${a.name.toLowerCase()}`;
                var kb = `${(enabled_first ? b.isActive ? "0" : "1" : "")}${b.type || ""}${b.name.toLowerCase()}`;
                return (ka < kb) ? -1 : 1;
            }).forEach(addon => {
                if (!exceptions_listset.has(addon.id) &&
                    (!addon.hidden || show_hidden) &&
                    (!addon.userDisabled || show_disabled)) {
                    let extension = GlobalManager.extensionMap.get(addon.id),
                    mi = doc.createXULElement("menuitem");
                    setAttributesMenu(mi, addon, extension);
                    mi._Addon = addon;
                    mi._Extension = extension;
                    popup.append(mi);
                    addonsMap.set(addon, mi);
                }
            });
            var click = (e) => {
                this.handleClick(e);
            };
            popup.addEventListener("click", click);
            var listener = {
                onEnabled: addon => {
                    var mi = addonsMap.get(addon);
                    if (mi)
                        setAttributesMenu(mi, addon, mi._Extension);
                },
                onDisabled: addon => {
                    listener.onEnabled(addon);
                },
                onInstalled: addon => {
                    var extension = GlobalManager.extensionMap.get(addon.id),
                    mi = doc.createXULElement("menuitem");
                    setAttributesMenu(mi, addon, extension);
                    mi._Addon = addon;
                    mi._Extension = extension;
                    popup.prepend(mi);
                    addonsMap.set(addon, mi);
                },
                onUninstalled: addon => {
                    var mi = addonsMap.get(addon);
                    if (mi) {
                        mi.remove();
                        addonsMap.delete(addon);
                    }
                },
            };
            AddonManager.addAddonListener(listener);
            popup.addEventListener("popuphiding", (e) => {
                AddonManager.removeAddonListener(listener);
                popup.removeEventListener("click", click);
                addonsMap = null;
                while (popup.hasChildNodes())
                    popup.firstChild.remove();
            }, { once: true });
        },
        handleClick: function(e) {
            var win = e.view, mi = e.target;
            if (!("_Addon" in mi) || !("_Extension" in mi))
                return;
            var addon = mi._Addon, extension = mi._Extension;
            switch (e.button) {
                case 0:
                    if (e.ctrlKey && e.shiftKey) {
                        if (addon.creator?.url)
                            win.gBrowser.selectedTab = this.addTab(win, addon.creator.url);
                    } else if (e.ctrlKey) {
                        this.clipboardHelp.copyString(addon.id);
                        try {
                            this.alertsService.showAlertNotification(`${img}`, "ID в буфере обмена!", addon.id, false);
                        } catch(e) {}
                    } else if (e.shiftKey) {
                        if (extension?.uuid) {
                            this.clipboardHelp.copyString(extension.uuid);
                            try {
                                this.alertsService.showAlertNotification(`${img}`, "UUID в буфере обмена!", extension.uuid, false);
                            } catch(e) {}
                        }
                    } else if (addon.isActive && addon.optionsURL)
                        this.openAddonOptions(addon, win);
                    win.closeMenus(mi);
                    break;
                case 1:
                    if (e.ctrlKey) {
                        if (!addon.isBuiltin)
                            this.browseDir(addon);
                    } else if (e.shiftKey)
                        this.browseDir(addon, win);
                    else if (addon.homepageURL)
                        win.gBrowser.selectedTab = this.addTab(win, addon.homepageURL);
                    win.closeMenus(mi);
                    break;
                case 2:
                    if (!e.ctrlKey) {
                        let endis = addon.userDisabled ? "enable" : "disable";
                        if (addon.id == "screenshots@mozilla.org")
                            Services.prefs.setBoolPref("extensions.screenshots.disabled", !addon.userDisabled);
                        else if (addon.id == "webcompat-reporter@mozilla.org")
                            Services.prefs.setBoolPref("extensions.webcompat-reporter.enabled", addon.userDisabled);
                        addon[endis]({ allowSystemAddons: true });
                    } else if (!addon.isSystem && !addon.isBuiltin && Services.prompt.confirm(win, null, `Удалить ${addon.name}?`))
                        addon.uninstall();
                break;
            }
        },
        openAddonOptions: function(addon, win) {
            switch (addon.optionsType) {
                case 5:
                    win.BrowserOpenAddonsMgr(`addons://detail/${encodeURIComponent(addon.id)}/preferences`);
                    break;
                case 3:
                    win.switchToTabHavingURI(addon.optionsURL, true);
                    break;
            }
        },
        browseDir: function(addon, win) {
            try {
                if (!win) {
                    let file = Services.io.getProtocolHandler("file")
                    .QueryInterface(Ci.nsIFileProtocolHandler)
                    .getFileFromURLSpec(addon.getResourceURI().QueryInterface(Ci.nsIJARURI).JARFile.spec);
                    if (file.exists())
                        file.launch();
                } else
                    win.gBrowser.selectedTab = this.addTab(win, addon.getResourceURI().spec);
            } catch (e) {}
        },
        addTab: function(win, url, params = {}) {
            params.triggeringPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
            params.relatedToCurrent = true;
            return win.gBrowser.addTab(url, params);
        },
    };
    CustomizableUI.createWidget({
        id: id,
        type: "custom",
        label: label,
        tooltiptext: tooltiptext,
        localized: false,
        defaultArea: CustomizableUI.AREA_NAVBAR,
        onBuild: function(doc) {
            var btn = doc.createXULElement("toolbarbutton"), win = doc.defaultView,
            props = {
                id: id,
                label: label,
                tooltiptext: tooltiptext,
                type: "menu",
                class: "toolbarbutton-1 chromeclass-toolbar-additional",
            };
            for (let p in props)
                btn.setAttribute(p, props[p]);
            btn.addEventListener("click", (e) => {
                if (e.button == 0) {
                    if (e.shiftKey)
                        win.BrowserOpenAddonsMgr();
                } else if (e.button == 1)
                    win.BrowserOpenAddonsMgr();
            });
            var mp = doc.createXULElement("menupopup");
            mp.id = `${id}-popup`;
            mp.addEventListener("click", (e) => {
                e.preventDefault();
                e.stopPropagation();
            });
            mp.addEventListener("contextmenu", (e) => {
                e.preventDefault();
                e.stopPropagation();
            });
            mp.addEventListener("popupshowing", (e) => {
                extensionOptionsMenu.populateMenu(e);
            });
            btn.append(mp);
            var btnstyle = "data:text/css;charset=utf-8," + encodeURIComponent(`
                #${id}, #${id}-popup menuitem {
                    list-style-image: url("${img}") !important;
                }
                #${id}-popup menuitem::after {
                    display: -moz-box !important;
                    content: "" !important;
                    height: 16px !important;
                    width: 16px !important;
                    padding: 0 !important;
                    border: 1px solid rgb(0, 116, 232) !important;
                    border-radius: 0 !important;
                    background-repeat: no-repeat !important;
                    background-position: center !important;
                    background-size: 16px !important;
                    background-color: rgb(0, 116, 232) !important;
                    background-image: url("${checked}") !important;
                    opacity: 1 !important;
                }
                #${id}-popup menuitem.ucf-disabled::after {
                    border-color: currentColor !important;
                    background-color: transparent !important;
                    background-image: none !important;
                    opacity: .6 !important;
                }
                #${id}-popup menuitem.ucf-disabled > label,
                #${id}-popup menuitem.ucf-notoptions > label {
                    opacity: .6 !important;
                }
                #${id}-popup menuitem.ucf-system > label {
                    text-decoration: underline !important;
                    text-decoration-style: dotted !important;
                }
                #${id}-popup menuitem > label {
                    margin-inline-end: 0 !important;
                }
                #${id}-popup menuitem > .menu-accel-container {
                    display: -moz-box !important;
                    padding: 4px !important;
                    margin: 0 !important;
                    opacity: 1 !important;
                }
                #${id}-popup menuitem > .menu-accel-container .menu-iconic-accel {
                    display: -moz-box !important;
                    margin: 0 !important;
                    height: 8px !important;
                    width: 8px !important;
                    border-radius: 4px !important;
                    background-color: transparent !important;
                    opacity: 1 !important;
                    font-size: 0 !important;
                }
                #${id}-popup menuitem.ucf-type-dictionary > .menu-accel-container .menu-iconic-accel {
                    background-color: rgb(227, 27, 93) !important;
                }
                #${id}-popup menuitem.ucf-type-locale > .menu-accel-container .menu-iconic-accel {
                    background-color: rgb(48, 172, 55) !important;
                }
                #${id}-popup menuitem.ucf-type-theme > .menu-accel-container .menu-iconic-accel {
                    background-color: rgb(219, 106, 0) !important;
                }
            `);
            try {
                win.windowUtils.loadSheetUsingURIString(btnstyle, win.windowUtils.USER_SHEET);
            } catch (e) {}
            return btn;
        },
    });
})();} catch (e) {}


Есть новее?

Отсутствует

 

№35006-06-2022 12:20:13

sandro79
Участник
 
Группа: Members
Зарегистрирован: 15-11-2017
Сообщений: 1750
UA: Firefox 91.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

xrun1 пишет

В [firefox] 101 (может и раньше) отвалилась кнопка "Дополнения" из расширения Add Toolbar Buttons

Я здесь добавил обновлённый вариант.
Скрипт с под первого спойлера отсюда тоже пока работает.

Отсутствует

 

Board footer

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