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

Будьте в курсе последних изменений в мире Mozilla, следя за нашим микроблогом в Twitter.

№142627-04-2024 10:51:58

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

Re: UCF - ваши кнопки, скрипты…

egorsemenov06
Так всё то же самое

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

Выделить код

Код:

/*
	onCreated(btn) {
		btn.setAttribute("image", "data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path style='fill:none;stroke:context-fill rgb(39, 174, 129);stroke-opacity:context-fill-opacity;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;' d='M12.9 15.3H3.2c-.88 0-1.6-.6-1.6-1.4v-2.7c0-.4.33-.6.74-.6h1.72c.7 0 1.25-.64 1.25-1.2 0-.64-.55-1.15-1.25-1.15H2.34c-.41 0-.74-.32-.74-.68V5.84c0-.81.72-1.48 1.6-1.48h2.36V3.13c0-1.21.93-2.297 2.21-2.419C9.23.57 10.5 1.62 10.5 2.98v1.38h2.4c.9 0 1.5.67 1.5 1.48v8.06c0 .8-.6 1.4-1.5 1.4z'/></svg>");
*/
	get icon() {
		var icon = "data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path style='fill:none;stroke:context-fill rgb(39, 174, 129);stroke-opacity:context-fill-opacity;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;' d='M12.9 15.3H3.2c-.88 0-1.6-.6-1.6-1.4v-2.7c0-.4.33-.6.74-.6h1.72c.7 0 1.25-.64 1.25-1.2 0-.64-.55-1.15-1.25-1.15H2.34c-.41 0-.74-.32-.74-.68V5.84c0-.81.72-1.48 1.6-1.48h2.36V3.13c0-1.21.93-2.297 2.21-2.419C9.23.57 10.5 1.62 10.5 2.98v1.38h2.4c.9 0 1.5.67 1.5 1.48v8.06c0 .8-.6 1.4-1.5 1.4z'/></svg>";
		var subst = this.id.toLowerCase() + "-icon";
		Services.io.getProtocolHandler("resource")
			.QueryInterface(Ci.nsIResProtocolHandler)
			.setSubstitution(subst, Services.io.newURI(icon));
		delete this.icon;
		return this.icon = "resource://" + subst;
	},
	onCreated(btn) {
		btn.setAttribute("image", this.icon);

Отсутствует

 

№142727-04-2024 21:55:16

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

Re: UCF - ваши кнопки, скрипты…

egorsemenov06 пишет

вместо зеленой звездочки при добавлении кнопки ярыка сайта отображаетя глобус посмотрите пожалуйста

Не получилось воспроизвести.
Никакого глобуса, либо favicon страницы, либо зелёная звёздочка.

может там в коде уже что то надо изменить

В смысле какого-то отвала — нет, не вижу ничего такого.
А в смысле косячков — конечно же есть, куда без них.
Например, вместо this.write определённо должно быть this.save

Отсутствует

 

№142828-04-2024 12:48:50

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: Firefox 126.0

Re: UCF - ваши кнопки, скрипты…

egorsemenov06
Кстати насчет кнопки Save, лучше удалить иконку из скрипта Save.js self.image = ...
и добавить в CustomizableUI.createWidget({

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

Выделить код

Код:

onCreated(btn) {
		...
        btn.setAttribute("image", this.image);
    },
    get image() {
        var img = `${this.id.toLowerCase()}-img`;
        Services.io.getProtocolHandler("resource")
        .QueryInterface(Ci.nsIResProtocolHandler)
        .setSubstitution(img, Services.io.newURI("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path style='fill:none;stroke:context-fill  rgb(142, 142, 152);stroke-opacity:context-fill-opacity;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;' d='M3 .6C1.6.6.6 1.6.6 3v10c0 1.4 1 2.4 2.4 2.4h10c1.4 0 2.4-1 2.4-2.4V4.84L11.2.602Zm5.4 5.8h2V1m-2 0v5.4H7L5.6 5V1m-2 14v-2.6l1-1h6.8l1 1V15'/></svg>"));
        delete this.image;
        return this.image = `resource://${img}`;
    },


А в этих двух кнопках заменить image: ...,
на get image() {...}, из кода выше, но со своими иконками здесь Services.io.newURI("...")
btn.setAttribute... добавлять не нужно там уже есть

Для defaultFavicon также заменить defaultFavicon: ..., и изменить строку var img = ...;

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

Выделить код

Код:

get defaultFavicon() {
        var img = `${this.id.toLowerCase()}-default-favicon-img`;
        Services.io.getProtocolHandler("resource")
        .QueryInterface(Ci.nsIResProtocolHandler)
        .setSubstitution(img, Services.io.newURI("иконка"));
        delete this.defaultFavicon;
        return this.defaultFavicon = `resource://${img}`;
    },

Отредактировано Vitaliy V. (28-04-2024 13:07:11)

Отсутствует

 

№142928-04-2024 14:12:22

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: Firefox 126.0

Re: UCF - ваши кнопки, скрипты…

А смотрю со своими иконками наверно не справитесь

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

Выделить код

Код:

data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24'><path style='fill:context-fill rgb(142, 142, 152);fill-opacity:context-fill-opacity;' d='M10 3H4a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1zm10 0h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1zM10 13H4a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1zm8 1h-2v2h-2v2h2v2h2v-2h2v-2h-2z'/></svg>


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

Выделить код

Код:

data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path style='fill:context-fill rgb(142, 142, 152);fill-opacity:context-fill-opacity;' d='M13.384 3.408c.535.276 1.22 1.152 1.556 1.963a8 8 0 0 1 .503 3.897l-.009.077-.026.224A7.758 7.758 0 0 1 .006 8.257v-.04q.025-.545.114-1.082c.01-.074.075-.42.09-.489l.01-.051a6.6 6.6 0 0 1 1.041-2.35q.327-.465.725-.87.35-.358.758-.65a1.5 1.5 0 0 1 .26-.137c-.018.268-.04 1.553.268 1.943h.003a5.7 5.7 0 0 1 1.868-1.443 3.6 3.6 0 0 0 .021 1.896q.105.07.2.152c.107.09.226.207.454.433l.068.066.009.009a2 2 0 0 0 .213.18c.383.287.943.563 1.306.741.201.1.342.168.359.193l.004.008c-.012.193-.695.858-.933.858-2.206 0-2.564 1.335-2.564 1.335.087.997.714 1.839 1.517 2.357a4 4 0 0 0 .439.241q.114.05.228.094c.325.115.665.18 1.01.194 3.043.143 4.155-2.804 3.129-4.745v-.001a3 3 0 0 0-.731-.9 3 3 0 0 0-.571-.37l-.003-.002a2.68 2.68 0 0 1 1.87.454 3.92 3.92 0 0 0-3.396-1.983q-.116.001-.23.01l-.042.003V4.31h-.002a4 4 0 0 0-.8.14 7 7 0 0 0-.333-.314 2 2 0 0 0-.2-.152 4 4 0 0 1-.088-.383 5 5 0 0 1 1.352-.289l.05-.003c.052-.004.125-.01.205-.012C7.996 2.212 8.733.843 10.17.002l-.003.005.003-.001.002-.002h.002l.002-.002h.015a.02.02 0 0 1 .012.007 2.4 2.4 0 0 0 .206.48q.09.153.183.297c.49.774 1.023 1.379 1.543 1.968.771.874 1.512 1.715 2.036 3.02l-.001-.013a8 8 0 0 0-.786-2.353'/> </svg>


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

Выделить код

Код:

data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24'><path style='fill:context-fill rgb(142, 142, 152);fill-opacity:context-fill-opacity;' d='M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M6,4H13L18,9V17.58L16.16,15.74C17.44,13.8 17.23,11.17 15.5,9.46C14.55,8.5 13.28,8 12,8C10.72,8 9.45,8.5 8.47,9.46C6.5,11.41 6.5,14.57 8.47,16.5C9.44,17.5 10.72,17.97 12,17.97C12.96,17.97 13.92,17.69 14.75,17.14L17.6,20H6V4M14.11,15.1C13.55,15.66 12.8,16 12,16C11.2,16 10.45,15.67 9.89,15.1C9.33,14.54 9,13.79 9,13C9,12.19 9.32,11.44 9.89,10.88C10.45,10.31 11.2,10 12,10C12.8,10 13.55,10.31 14.11,10.88C14.67,11.44 15,12.19 15,13C15,13.79 14.68,14.54 14.11,15.1Z' /></svg>

Отсутствует

 

№143028-04-2024 14:40:13

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: Firefox 126.0

Re: UCF - ваши кнопки, скрипты…

egorsemenov06
Вот кнопка Save

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

Выделить код

Код:

(async () => CustomizableUI.createWidget({
	id: "ucf-cbbtn-Save",
	tooltiptext: "Сохранить",
	localized: false,
	get initCode() {
		delete this.initCode;
		return this.initCode = Cu.readUTF8URI(Services.io.newURI(
			"chrome://user_chrome_files/content/custom_scripts/Save.js"
		));
	},
	cbu: {
		types: {
			128: "Bool", boolean: "Bool",
			64: "Int", number: "Int",
			32: "String", string: "String"
		},
		getPrefs(pref) {
			try {
				return Services.prefs[`get${
					this.types[Services.prefs.getPrefType(pref)]
				}Pref`](pref);
			}
			catch {return null;}
		},
		setPrefs(pref, val) {
			Services.prefs[`set${this.types[typeof val]}Pref`](pref, val);
		}
	},
	gClipboard: {
		get ch() {
			delete this.ch;
			return this.ch = Cc["@mozilla.org/widget/clipboardhelper;1"]
				.getService(Ci.nsIClipboardHelper);
		},
		write(str) {
			this.ch.copyStringToClipboard(str, Services.clipboard.kGlobalClipboard);
		}
	},
	custombuttonsUtils: {
		writeFile(path, data) {
			try {
				if (path.includes(":\\")) path = path.replace(/\//g, "\\");
				var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
				file.initWithPath(path);
				file.exists() && file.remove(false);

				var strm = Cc["@mozilla.org/network/file-output-stream;1"]
					.createInstance(Ci.nsIFileOutputStream);
				strm.init(file, 0x04 | 0x08, 420, 0);
				strm.write(data, data.length);
				strm.flush();
				strm.close();
			} catch(ex) {
				Cu.reportError("Custom Buttons: " + [path, "---", ex, ex.stack].join("\n"));
			}
		}
	},
	addDestructor(destructor, context) {
		this._destructors.push({destructor, context});
	},
	addEventListener(...args) {
		var trg = args[3];
		if (!trg) trg = args[3] = this.ownerGlobal;
		trg.addEventListener(...args);
		this._handlers.push(args);
	},

    onCreated(btn) {
		var win = btn.ownerGlobal;
		btn._handlers = new win.Array();
		btn._destructors = new win.Array();
		win.addEventListener("unload", this, {once: true});
		new win.Function(
			"self,_id,cbu,xhtmlns,addDestructor,addEventListener,gClipboard,custombuttonsUtils",
			this.initCode
		).call(
			btn, btn, this.id, this.cbu,
			"http://www.w3.org/1999/xhtml",
			this.addDestructor.bind(btn),
			this.addEventListener.bind(btn),
			this.gClipboard, this.custombuttonsUtils
		);
        btn.setAttribute("image", this.image);
    },
    get image() {
        var img = `${this.id.toLowerCase()}-img`;
        Services.io.getProtocolHandler("resource")
        .QueryInterface(Ci.nsIResProtocolHandler)
        .setSubstitution(img, Services.io.newURI("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path style='fill:none;stroke:context-fill  rgb(142, 142, 152);stroke-opacity:context-fill-opacity;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;' d='M3 .6C1.6.6.6 1.6.6 3v10c0 1.4 1 2.4 2.4 2.4h10c1.4 0 2.4-1 2.4-2.4V4.84L11.2.602Zm5.4 5.8h2V1m-2 0v5.4H7L5.6 5V1m-2 14v-2.6l1-1h6.8l1 1V15'/></svg>"));
        delete this.image;
        return this.image = `resource://${img}`;
    },
	handleEvent(e) {
		var btn = e.target.getElementById(this.id);
		for(var args of btn._handlers)
			args.pop().removeEventListener(...args);
		delete btn._handlers;
		for(var {destructor, context} of btn._destructors)
			try {destructor.call(context, "destructor");}
			catch(ex) {Cu.reportError(ex);}
		delete btn._destructors;
	}
}))();


а из Save.js нужно удалить self.image = ... ;


Вкладки в контейнере.............

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

Выделить код

Код:

//Вкладки в контейнере.............
(async () => CustomizableUI.createWidget(({
	label: "Вкладки в контейнере",
	get image() {
        var img = `${this.id.toLowerCase()}-img`;
        Services.io.getProtocolHandler("resource")
        .QueryInterface(Ci.nsIResProtocolHandler)
        .setSubstitution(img, Services.io.newURI("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24'><path style='fill:context-fill rgb(142, 142, 152);fill-opacity:context-fill-opacity;' d='M10 3H4a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1zm10 0h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1zM10 13H4a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1zm8 1h-2v2h-2v2h2v2h2v-2h2v-2h-2z'/></svg>"));
        delete this.image;
        return this.image = `resource://${img}`;
    },
	get defaultFavicon() {
        var img = `${this.id.toLowerCase()}-default-favicon-img`;
        Services.io.getProtocolHandler("resource")
        .QueryInterface(Ci.nsIResProtocolHandler)
        .setSubstitution(img, Services.io.newURI("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path style='fill:context-fill rgb(142, 142, 152);fill-opacity:context-fill-opacity;' d='M13.384 3.408c.535.276 1.22 1.152 1.556 1.963a8 8 0 0 1 .503 3.897l-.009.077-.026.224A7.758 7.758 0 0 1 .006 8.257v-.04q.025-.545.114-1.082c.01-.074.075-.42.09-.489l.01-.051a6.6 6.6 0 0 1 1.041-2.35q.327-.465.725-.87.35-.358.758-.65a1.5 1.5 0 0 1 .26-.137c-.018.268-.04 1.553.268 1.943h.003a5.7 5.7 0 0 1 1.868-1.443 3.6 3.6 0 0 0 .021 1.896q.105.07.2.152c.107.09.226.207.454.433l.068.066.009.009a2 2 0 0 0 .213.18c.383.287.943.563 1.306.741.201.1.342.168.359.193l.004.008c-.012.193-.695.858-.933.858-2.206 0-2.564 1.335-2.564 1.335.087.997.714 1.839 1.517 2.357a4 4 0 0 0 .439.241q.114.05.228.094c.325.115.665.18 1.01.194 3.043.143 4.155-2.804 3.129-4.745v-.001a3 3 0 0 0-.731-.9 3 3 0 0 0-.571-.37l-.003-.002a2.68 2.68 0 0 1 1.87.454 3.92 3.92 0 0 0-3.396-1.983q-.116.001-.23.01l-.042.003V4.31h-.002a4 4 0 0 0-.8.14 7 7 0 0 0-.333-.314 2 2 0 0 0-.2-.152 4 4 0 0 1-.088-.383 5 5 0 0 1 1.352-.289l.05-.003c.052-.004.125-.01.205-.012C7.996 2.212 8.733.843 10.17.002l-.003.005.003-.001.002-.002h.002l.002-.002h.015a.02.02 0 0 1 .012.007 2.4 2.4 0 0 0 .206.48q.09.153.183.297c.49.774 1.023 1.379 1.543 1.968.771.874 1.512 1.715 2.036 3.02l-.001-.013a8 8 0 0 0-.786-2.353'/> </svg>"));
        delete this.defaultFavicon;
        return this.defaultFavicon = `resource://${img}`;
    },
	id: "ucf-cbbtn-LnkCreator",
	localized: false,
	onCreated(btn) {
		btn.owner = this;
		btn.tooltipText = this.label;
		btn.setAttribute("image", this.image);
		btn.setAttribute("oncommand", "owner.createLnk(this)");
	},
	init() {
		this.widget.parent = this;
		this.widget.contextmenu.destroy = id => {
			CustomizableUI.destroyWidget(id);
			delete this.data[id.slice(8)];
			this.save();
		}
		try {this.data = JSON.parse(Cu.readUTF8URI(Services.io.newURI(
			`chrome://user_chrome_files/content/custom_scripts/${this.id}-data.json`
		)))}
		catch {this.data = {}; return this;}
		for(var [id, inf] of Object.entries(this.data))
			this.createWidget(id, inf.url, inf.name);
		return this;
	},
	get fs() {
		delete this.fs;
		return this.fs = Cc["@mozilla.org/browser/favicon-service;1"]
			.getService(Ci.nsIFaviconService);
	},
	createLnk(btn) {
		var id = Date.now();
		var gb = btn.ownerGlobal.gBrowser;
		var uri = gb.currentURI;
		var label = gb.contentTitle.slice(0, 75);

		var widget = this.createWidget(id, uri, label);
		var {area, position} = CustomizableUI.getPlacementOfWidget(this.id);
		CustomizableUI.addWidgetToArea(widget.id, area, position + 1);

		this.data[id] = {name: label, url: uri.spec};
		this.save();
	},
	createWidget(id, url, label) {
		var obj = {
			uri: url.spec ? url : Services.io.newURI(url),
			id: "ucf-lnk-" + id, label, ...this.widget
		};
		var widget = obj.widget = CustomizableUI.createWidget(obj);
		this.fs.getFaviconDataForPage(obj.uri, obj);
		return widget;
	},
	tip: "\nShift+ПКМ - Удалить кнопку",
	widget: {
		localized: false,
		onCreated(btn) {
			btn.uri = this.uri;
			btn.addTab = this.addTab;
			btn.oncontextmenu = this.contextmenu;
			btn.setAttribute("oncommand", "addTab(this)");
			btn.tooltipText = this.label + this.parent.tip;
			this.image && btn.setAttribute("image", this.image);
		},
		addTab(btn) {
			var gb = btn.ownerGlobal.gBrowser;
			gb.selectedTab = gb.addTrustedTab(btn.uri.spec, {userContextId: 1});
		},
		contextmenu: function checkShift(e) {
			if (e.shiftKey)
				e.preventDefault(),
				checkShift.destroy(e.target.id);
		},
		onComplete(uri, len, arr, mmt) {
			this.image = len
				? `data:${mmt};base64,${btoa(String.fromCharCode(...arr))}`
				: this.parent.defaultFavicon
			for(var {node} of this.widget.instances)
				node.hasAttribute("image") || node.setAttribute("image", this.image);
			delete this.widget;
		}
	},
	save() {
		var file = Services.dirsvc.get("UChrm", Ci.nsIFile), CC = Components.Constructor;
		["user_chrome_files", "custom_scripts", this.id + "-data.json"].forEach(file.append);
		var te = new (Cu.getGlobalForObject(Cu).TextEncoder)();
		var fos = CC("@mozilla.org/network/file-output-stream;1", "nsIFileOutputStream", "init")
			// MODE_{WRONLY, CREATE, TRUNCATE}, PERMS_FILE
			.bind(null, file, 0x02 | 0x08 | 0x20, 0o644, 0);
		var bos = CC("@mozilla.org/binaryoutputstream;1", "nsIBinaryOutputStream", "setOutputStream");

		(this.save = () => {
			var stream = new fos();
			try {new bos(stream).writeByteArray(
				te.encode(JSON.stringify(this.data))
			);} catch(ex) {Cu.reportError(ex);}
			finally {stream.close();}
		})();
	}
}).init()))();


Третью кнопку тоже выкладывать?

Отредактировано Vitaliy V. (28-04-2024 14:40:34)

Отсутствует

 

№143128-04-2024 14:54:43

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: Firefox 126.0

Re: UCF - ваши кнопки, скрипты…

egorsemenov06

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

Выделить код

Код:

//Атрибут инспектор...........................
(async () => CustomizableUI.createWidget({
	id: "AttributesInspector",
	label: "Attributes Inspector",
	get image() {
        var img = `${this.id.toLowerCase()}-img`;
        Services.io.getProtocolHandler("resource")
        .QueryInterface(Ci.nsIResProtocolHandler)
        .setSubstitution(img, Services.io.newURI("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24'><path style='fill:context-fill rgb(142, 142, 152);fill-opacity:context-fill-opacity;' d='M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M6,4H13L18,9V17.58L16.16,15.74C17.44,13.8 17.23,11.17 15.5,9.46C14.55,8.5 13.28,8 12,8C10.72,8 9.45,8.5 8.47,9.46C6.5,11.41 6.5,14.57 8.47,16.5C9.44,17.5 10.72,17.97 12,17.97C12.96,17.97 13.92,17.69 14.75,17.14L17.6,20H6V4M14.11,15.1C13.55,15.66 12.8,16 12,16C11.2,16 10.45,15.67 9.89,15.1C9.33,14.54 9,13.79 9,13C9,12.19 9.32,11.44 9.89,10.88C10.45,10.31 11.2,10 12,10C12.8,10 13.55,10.31 14.11,10.88C14.67,11.44 15,12.19 15,13C15,13.79 14.68,14.54 14.11,15.1Z' /></svg>"));
        delete this.image;
        return this.image = `resource://${img}`;
    },
	localized: false,
	onCreated(btn) {
		btn.setAttribute("image", this.image);
		btn.setAttribute("tooltiptext", this.label);
		btn.onmouseenter = btn.onmouseleave = this.onmouse;

		btn.setAttribute("oncommand", "handleCommand(this)");
		btn.handleCommand = this.handleCommand;
	},
	get handleCommand() {
		delete this.handleCommand;
		return this.handleCommand = btn => {
			(btn.handleCommand = new btn.ownerGlobal.Function(this.code).bind(btn))();
		}
	},
	get code() {
		delete this.code;
		return this.code = "this.focusedWindow && this.focusedWindow.focus();\n" +
			Cu.readUTF8URI(Services.io.newURI(
				"chrome://user_chrome_files/content/custom_scripts/custom_script/attributesInspector.js"
			));
	},
	onmouse: e => e.target.focusedWindow =
		e.type.endsWith("r") && Services.wm.getMostRecentWindow(null)
}))();

Отсутствует

 

№143228-04-2024 15:21:35

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: unknown 0.0

Re: UCF - ваши кнопки, скрипты…

egorsemenov06 пишет

даже готовое не могу сообразить с кнопкой save доавил код что Вы только что  дали в  custom_script.js

Я хз почему не работает, и что значит добавил, нужно заменить код в custom_script.js

Отсутствует

 

№143328-04-2024 15:55:12

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: unknown 0.0

Re: UCF - ваши кнопки, скрипты…

egorsemenov06
Наверняка где то ошибку синтаксиса допустили, все там должно работать

Отсутствует

 

№143429-04-2024 04:23:05

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

Re: UCF - ваши кнопки, скрипты…

Vitaliy V. раз тут завал просьб, добавлю свои 3 копейки:


Просьба улучшить ucf_contextmenuopenwith для нормальной работы с yt-dlp:
1) в режиме "Открыть страницу в …" если в Clipboard только одна строка и текст заканчивается на .m3u8, то передавать его вместо %OpenURI
2) есть выделенный текст ? передать его вместо %OpenURI. Чтобы работало на moz-extension://, где Video DownloadHelper открывает «Детали» со ссылками.

ucf_contextmenuopenwith.js – возможно, этот код устарел

Выделить код

Код:

(this.contextmenuopenwith = {
	_eventlisteners: [],
	menupage: {},
	menulink: {},
	init(that) {
		var attrimage = true; // true или false Добавить иконки (атрибут "image") или нет
		var submenu = false; // true или false Добавить подменю для пунктов или нет
		var prelabpage = false; // Добавить вначале "Открыть страницу в ";
		var prelablink = false; // Добавить вначале "Открыть ссылку в ";
		// [true или false Показывать пункт на странице или нет, true или false Показывать пункт на ссылках или нет, 'ID пункта', 'имя приложения', 'путь к приложению', 'аргументы через пробел (то что в двойных кавычках считается за один аргумент)', 'иконка (для Windows необязательно)'],
		var arrayWindows = [
//			[true, true, 'edge', 'Microsoft Edge', 'C:\\Windows\\explorer.exe', '"microsoft-edge:%OpenURI "', 'moz-icon://file://C:\\ndows\\SystemApps\\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\\MicrosoftEdge.exe?size=16'],
			[true, true, 'videodownloader', '4K Downloader', 'C:\\Program Files (x86)\\4KDownload\\4kvideodownloader\\4kvideodownloader.exe', '%OpenURI'],
//			[true, true, 'potplayer', 'DAUM PotPlayer', 'C:\\Program Files\\PotPlayer\\PotPlayerMini64.exe', '%OpenURI'],
//			[true, true, 'vlc', 'VLC', 'C:\\Program Files\\VideoLAN\\VLC\\vlc.exe', '%OpenURI'],
		];
		var arrayLinux = [ // для Linux
			// [true, true, 'vlc', 'VLC', '/usr/bin/vlc', '%OpenURI', 'moz-icon://stock/vlc?size=menu'],
			// [false, true, 'thunderbird', 'Thunderbird', '/usr/bin/thunderbird', '-compose "to=%OpenURI"', 'moz-icon://stock/thunderbird?size=menu'],
			[true, true, 'yt-dlp', 'Скачать видео в yt-dlp', '/usr/bin/xterm', '-e "yt-dlp \'%OpenURI\'; beep; sleep 3"', 'moz-icon://stock/go-down?size=menu'], // терминал вашей Рабочей среды, в ~/.config/yt-dlp.conf указан каталог загрузки
			[false, true, 'mpv', 'Смотреть в MPV плеер', '/usr/bin/mpv', '--ytdl-format=bestvideo[height<=?720][fps<=?30]+bestaudio/best[height<=?720][fps<=?30] "%OpenURI"', 'moz-icon://stock/mpv?size=menu'],
		];
		var arrayMacos = [ // для MacOS
			// [true, true, 'downie', 'Скачать видео в Downie 4', '/usr/bin/open', '-b com.charliemonroe.Downie-4 %OpenURI', 'moz-icon://file:///Applications/Downie 4.app?size=16'],
			[true, true, 'yt-dlp', 'Найти/скачать видео: yt-dlp', '/usr/bin/osascript', `-e "tell app %quotTerminal%quot to activate do script %quotyt-dlp '%OpenURI' && say 'download complete'; exit%quot"`, 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAAAAAClZ7nPAAAAAXRSTlMAQObYZgAAACNJREFUCNdjYH/AgBX9/89Q/4/B/g+D/A8G/g8gEeYDDIwNAIB7EDCcKCcMAAAAAElFTkSuQmCC'], // 'moz-icon://file:///System/Library/Image Capture/Support/Application/AutoImporter.app?size=16'
			[true, true, 'mpv', 'Смотреть в MPV плеер', '/usr/bin/open', '-n -a mpv --args --ytdl-format=bestvideo[height<=?720][fps<=?30]+bestaudio/best[height<=?720][fps<=?30] %OpenURI', 'moz-icon://file:///Applications/mpv.app?size=16'],
			[true, true, 'Safari', 'Обзор страницы в Safari', '/usr/bin/open', '-b com.apple.Safari %OpenURI', 'chrome://branding/content/icon32.png'],
		];

		var arrayOS, platform = AppConstants.platform, length;
		if (platform == "win")
			arrayOS = arrayWindows;
		else if (platform == "linux")
			arrayOS = arrayLinux;
		else if (platform == "macosx")
			arrayOS = arrayMacos;
		else
			return;
		if (!(length = arrayOS.length))
			return;
		var addEventListener = this.addEventListener.bind(this);
		var popup = document.querySelector("#contentAreaContextMenu");
		var create = evt => {
			if (evt.target != popup || gContextMenu.webExtBrowserType === "popup") return;
			popup.removeEventListener("popupshowing", create);
			var seppage = popup.querySelector("#context-sep-selectall") || popup.querySelector("#frame-sep") || popup.lastElementChild;
			var seplink = popup.querySelector("#context-sep-copylink") || popup.querySelector("#context-sep-open") || popup.firstElementChild;
			var fragpage = document.createDocumentFragment(), fraglink = document.createDocumentFragment(), _prelabpage = "", _prelablink = "";
			if (length == 1) submenu = false;
			if (!submenu)
				_prelabpage = prelabpage ? "Открыть страницу в " : "", _prelablink = prelablink ? "Открыть ссылку в " : "";
			arrayOS.forEach(item => {
				var id = item[2], name = item[3], path = item[4], arg = !item[5] ? "" : item[5];
				if (!id || !name || !path) return;
				var iconpath = !item[6] ? (`moz-icon://file://${path}?size=16`) : item[6];
				if (item[0]) {
					let menuitem_0 = document.createXULElement("menuitem");
					menuitem_0.id = `open-current-page-with-${id}`;
					menuitem_0.className = "menuitem-iconic open-current-page-with-application";
					menuitem_0.setAttribute("label", `${_prelabpage}${name}`);
					menuitem_0.applicationpath = path;
					menuitem_0.applicationarg = arg;
					if (attrimage)
						menuitem_0.setAttribute("image", iconpath);
					fragpage.append(menuitem_0);
					addEventListener(menuitem_0, "command", function page(event) {
						try {
							var target = event.currentTarget, arg = target.applicationarg, file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
							file.initWithPath(target.applicationpath);
							if (!file.exists() || !file.isExecutable()) return;
							arg = (arg !== "") ? arg.split(/\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/g).map(sp => {
								if (/%OpenURI/g.test(sp)) {
									let uri = gBrowser.selectedBrowser.currentURI.displaySpec;
									try {
										let _uri = ReaderMode.getOriginalUrl(uri);
										if (_uri)
											uri = Services.io.newURI(_uri).displaySpec;
									} catch(e) {}
									try {
										uri = decodeURIComponent(uri);
									} catch(e) {}
									return sp.replace(/^"|"$/g, "").replace(/%quot/g, '"').replace(/%OpenURI/g, uri);
								}
								return sp.replace(/^"|"$/g, "").replace(/%quot/g, '"');
							}) : [];
							var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
							process.init(file);
							process.runwAsync(arg, arg.length);
						} catch(e) {}
					});
				}
				if (item[1]) {
					let menuitem_1 = document.createXULElement("menuitem");
					menuitem_1.id = `open-link-with-${id}`;
					menuitem_1.className = "menuitem-iconic open-link-with-application";
					menuitem_1.setAttribute("label", `${_prelablink}${name}`);
					menuitem_1.applicationpath = path;
					menuitem_1.applicationarg = arg;
					if (attrimage)
						menuitem_1.setAttribute("image", iconpath);
					fraglink.append(menuitem_1);
					addEventListener(menuitem_1, "command", function link(event) {
						try {
							var target = event.currentTarget, arg = target.applicationarg, file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
							file.initWithPath(target.applicationpath);
							if (!file.exists() || !file.isExecutable() || !window.gContextMenu?.linkURI?.displaySpec) return;
							arg = (arg !== "") ? arg.split(/\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/g).map(sp => {
								if (/%OpenURI/g.test(sp)) {
									let uri = gContextMenu.linkURI.displaySpec;
									try {
										let _uri = ReaderMode.getOriginalUrl(uri);
										if (_uri)
											uri = Services.io.newURI(_uri).displaySpec;
									} catch(e) {}
									try {
										uri = decodeURIComponent(uri);
									} catch(e) {}
									return sp.replace(/^"|"$/g, "").replace(/%quot/g, '"').replace(/%OpenURI/g, uri);
								}
								return sp.replace(/^"|"$/g, "").replace(/%quot/g, '"');
							}) : [];
							var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
							process.init(file);
							process.runwAsync(arg, arg.length);
						} catch(e) {}
					});
				}
			});
			that.unloadlisteners.push("contextmenuopenwith");
			var funcpopupshowing, funcpopuphiding;
			if (!submenu) {
				seppage.after(fragpage);
				seplink.before(fraglink);
				funcpopupshowing = () => {
					var link = gContextMenu.onLink || gContextMenu.onMailtoLink;
					for(let arr of this._eventlisteners) {
						if (arr[2].name === "page")
							arr[0].hidden = link;
						else if (arr[2].name === "link")
							arr[0].hidden = !link;
					}
				};
				funcpopuphiding = () => {
					for(let arr of this._eventlisteners) {
						if (arr[1] === "command")
							arr[0].hidden = true;
					}
				};
			} else {
				if (fragpage.children.length) {
					let menu = this.menupage = document.createXULElement("menu");
					menu.id = "open-current-page-with-submenu";
					menu.className = "menu-iconic open-current-page-with-application";
					menu.setAttribute("label", "Открыть страницу в...");
					let menupopup = document.createXULElement("menupopup");
					menupopup.append(fragpage);
					menu.append(menupopup);
					seppage.after(menu);
				}
				if (fraglink.children.length) {
					let menu = this.menulink = document.createXULElement("menu");
					menu.id = "open-link-with-submenu";
					menu.className = "menu-iconic open-link-with-application";
					menu.setAttribute("label", "Открыть ссылку в...");
					let menupopup = document.createXULElement("menupopup");
					menupopup.append(fraglink);
					menu.append(menupopup);
					seplink.before(menu);
				}
				funcpopupshowing = () => {
					var link = gContextMenu.onLink || gContextMenu.onMailtoLink;
					this.menupage.hidden = link;
					this.menulink.hidden = !link;
				};
				funcpopuphiding = () => {
					this.menupage.hidden = true;
					this.menulink.hidden = true;
				};
			}
			funcpopupshowing();
			addEventListener(popup, "popupshowing", e => {
				if (e.target != popup || gContextMenu.webExtBrowserType === "popup") return;
				funcpopupshowing();
			});
			addEventListener(popup, "popuphiding", e => {
				if (e.target != popup) return;
				funcpopuphiding();
			});
		};
		popup.addEventListener("popupshowing", create);
	},
	addEventListener(...arr) {
		var elm = arr[0];
		if (!elm)
			return;
		elm.addEventListener(...arr.slice(1));
		this._eventlisteners.push(arr);
	},
	destructor() {
		for(let arr of this._eventlisteners)
			arr.shift().removeEventListener(...arr);
		delete this._eventlisteners;
	}
}).init(this);

Отсутствует

 

№143530-04-2024 11:29:13

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: Firefox 126.0

Re: UCF - ваши кнопки, скрипты…

Dobrov пишет

если в Clipboard только одна строка и текст заканчивается на .m3u8

Ссылки с m3u не всегда так заканчиваются, может быть так .m3u8?бла-бла-бла, и почему только плейлисты m3u а просто медиа файлы и т.д.
Кстати для прямых ссылок на медиа и m3u не нужен yt-dlp, см. ниже пример копирования потока с FFmpeg, можно сразу конвертировать с заданным кодеком.
Короче сделал так, при зажатой клавише Shift или СКМ ссылка берется из буфера, и ещё добавил параметр clipboard можно добавить пункт для работы с буфером обмена.

Dobrov пишет

Чтобы работало на moz-extension://, где Video DownloadHelper

А разве не работает на moz-extension:// там вроде только в popup отключено, короче не знаю проверь сам на Video DownloadHelper


Код упростил теперь один и тот же пункт для ссылок, страницы, выделенного, буфера

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

Выделить код

Код:

// Script For browser window document [ChromeOnly]
/**
* @param {String | Symbol} id (required) ID
* @param {Boolean} attrimage (required) Добавить иконки (атрибут "image") или нет
* @param {Boolean} submenu (required) Добавить подменю для пунктов или нет
* @param {String} preitem (required) Prefix для пунктов, где Prefix не указан в name
* @param {String} menuname (required) Название меню, если submenu = true
* @param {String} selector (required) Селектор в контекстном меню перед которым добавлять пункты
*
* @param {String} name: (required)
*   '[Prefix |]Название',
* @param {String} path: (required)
*   'Путь к приложению',
* @param {String} tooltip: (optional)
*   Подсказка для пункта меню
* @param {String} args: (optional)
*   `Аргументы через пробел "то что в двойных кавычках считается за один аргумент"`,
*   Собственные аргументы:
*   %OpenURL% - адрес
*   %ProfD% - путь до профиля
*   %FilePicker% - выбор папки, например для скачивания
*   %Prompt(message)% - вызвать диалоговое окно для изменения текста, например названия медиа файла
*   %quot% - двойные кавычки
* @param {String} rcargs: (optional)
*   Тоже что и args но выполняется по правому клику
* @param {Boolean} clipboard: (optional)
*   Адрес из буфера обмена
* @param {String} iconpath: (optional)
*   'Иконка',
*/
(async (
    id = Symbol("contextmenuopenwith"),
    attrimage = true,
    submenu = true,
    preitem = "Открыть в ",
    menuname = "Открыть в...",
    selector = "#context-sep-open",

    Linux = [
        {
            name: 'VLC',
            path: '/usr/bin/vlc',
            iconpath: 'moz-icon://stock/vlc?size=menu',
        },
        {
            name: 'Haruna',
            path: '/usr/bin/haruna',
            iconpath: 'moz-icon://stock/haruna?size=menu',
        },
        {
            name: 'Скачать в |Yt-dlp',
            path: '/usr/bin/konsole',
            tooltip: 'ПКМ: Скачать в Yt-dlp с выбором папки',
            // yt-dlp скачать видео, используя куки браузера, предпочтительно .mp4 с кодеком hevc|h265|avc|h264 с разрешением <=1080
            args: `--hold --workdir ~/Загрузки -e "yt-dlp --cookies-from-browser firefox:%ProfD% -f %quot%bv[height<=1080][ext=mp4][vcodec~='^(hevc|h265|avc|h264)']+ba[ext~='(aac|m4a)']/best[height<=1080][ext=mp4]/best[height<=1080]/best%quot% %OpenURL%"`,
            // с выбором папки
            rcargs: `--hold --workdir %FilePicker% -e "yt-dlp --cookies-from-browser firefox:%ProfD% -f %quot%bv[height<=1080][ext=mp4][vcodec~='^(hevc|h265|avc|h264)']+ba[ext~='(aac|m4a)']/best[height<=1080][ext=mp4]/best[height<=1080]/best%quot% %OpenURL%"`,
            iconpath: 'moz-icon://stock/youtube-dl?size=menu',
        },
        {
            name: 'Скачать из буфера в |FFmpeg',
            path: '/usr/bin/konsole',
            tooltip: 'ПКМ: Скачать из буфера в FFmpeg с выбором папки и названия файла',
            // ffmpeg копировать поток видео аудио в контейнер mp4
            args: `--hold --workdir ~/Загрузки -e "ffmpeg -i %OpenURL% -c copy -f mp4 Video.mp4"`,
            // с выбором папки и названия файла
            rcargs: `--hold --workdir %FilePicker% -e "ffmpeg -i %OpenURL% -c copy -f mp4 %Prompt(Video.mp4)%"`,
            clipboard: true,
            iconpath: 'moz-icon://stock/utilities-terminal?size=menu',
        },
    ],
    Windows = [
        {
            name: 'VLC',
            path: 'C:\\Program Files\\VideoLAN\\VLC\\vlc.exe',
        },
    ],
    macOS = [

    ],
/***************************************************/
    popup,
    showing = e => (e.target != popup || gContextMenu.webExtBrowserType === "popup" || (gContextMenu.isContentSelected || gContextMenu.onTextInput) && !gContextMenu.linkURL),
    hiding = e => (e.target != popup),
) => (this[id] = {
    get ProfD() {
        delete this.ProfD;
        return this.ProfD = Services.dirsvc.get("ProfD", Ci.nsIFile).path;
    },
    _eventListeners: [],
    _eventCListeners: [],
    init() {
        switch (Services.appinfo.OS) {
            case "Linux":
                this.arrOS = Linux;
                break;
            case "WINNT":
                this.arrOS = Windows;
                break;
            case "Darwin":
                this.arrOS = macOS;
                break;
            default:
                return;
        }
        var alength = this.arrOS.length;
        if (!alength) return;
        if (alength == 1) submenu = false;
        popup = document.querySelector("#contentAreaContextMenu");
        this.addListener(popup, "popupshowing", this);
        setUnloadMap(id, () => this.destructor());
    },
    addListener(elm, type, listener) {
        elm.addEventListener(type, listener);
        this._eventListeners.push({elm, type, listener});
    },
    addCListener(elm, type, listener) {
        elm.addEventListener(type, listener);
        this._eventCListeners.push({elm, type, listener});
    },
    handleEvent(e) {
        this[e.type](e);
    },
    popupshowing(e) {
        if (showing(e)) return;
        var contextsel = popup.querySelector(`:scope > ${selector}`) || popup.querySelector(":scope > menuseparator:last-of-type");
        var fragment = document.createDocumentFragment();
        var itemId = 0;
        this.arrOS.forEach(item => {
            var {name, path, tooltip, args, rcargs, clipboard, iconpath} = item;
            if (!name) name = "contextmenuopenwith";
            name = name.split("|");
            var mitem = document.createXULElement("menuitem");
            mitem.id = `ucf-menu-open-with-${++itemId}`;
            mitem.className = "menuitem-iconic ucf-menu-open-with";
            var str = name.join(""), len = name.length > 1;
            if (submenu) {
                mitem.setAttribute("label", len ? name.slice(1).join("") : str);
                if (tooltip)
                    mitem.tooltipText = `${str}\n${tooltip}`;
                else if (len)
                    mitem.tooltipText = str;
            } else {
                mitem.setAttribute("label", `${len ? "" : preitem}${str}`);
                if (tooltip)
                    mitem.tooltipText = tooltip;
            }
            mitem.apppath = path;
            mitem.appargs = args;
            mitem.apprcargs = rcargs;
            mitem.appclipboard = clipboard;
            if (attrimage)
                mitem.setAttribute("image", iconpath || `moz-icon://file://${path}?size=16`);
            fragment.append(mitem);
            this.addCListener(mitem, "click", this);
        });
        if (submenu) {
            let rootmenu = this.rootmenu = document.createXULElement("menu");
            rootmenu.id = "ucf-menu-open-with-submenu";
            rootmenu.className = "menu-iconic ucf-menu-open-with";
            rootmenu.setAttribute("label", menuname);
            let mpopup = document.createXULElement("menupopup");
            mpopup.append(fragment);
            rootmenu.append(mpopup);
            contextsel.before(rootmenu);
            this.popupshowing = this.menuShow;
            this.popuphiding = this.menuHide;
        } else {
            contextsel.before(fragment);
            this.popupshowing = this.itemsShow;
            this.popuphiding = this.itemsHide;
        }
        this.addListener(popup, "popuphiding", this);
    },
    menuShow(e) {
        if (showing(e)) return;
        this.rootmenu.hidden = false;
    },
    itemsShow(e) {
        if (showing(e)) return;
        for (let {elm} of this._eventCListeners)
            elm.hidden = false;
    },
    menuHide(e) {
        if (hiding(e)) return;
        this.rootmenu.hidden = true;
    },
    itemsHide(e) {
        if (hiding(e)) return;
        for (let {elm} of this._eventCListeners)
            elm.hidden = true;
    },
    async click(e) {
        try {
            let {appargs, apprcargs, apppath: path, appclipboard: clipboard} = e.currentTarget, file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
            file.initWithPath(path);
            if (!file.exists()) return;
            if (file.isExecutable()) {
                let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
                process.init(file);
                let args = !(e.button === 2 && apprcargs) ? appargs : apprcargs;
                let URL = !clipboard === !(e.shiftKey || e.button === 1) ? (gContextMenu?.linkURI?.displaySpec || this.getCurrentURL()) : this.readFromClipboard();
                if (args) {
                    let openuri = false;
                    args = args.split(/\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/);
                    for (let [ind, sp] of args.entries()) {
                        sp = sp.replace(/^["']+|["']+$/g, "").replace(/%quot%/g, '"').replace("%ProfD%", this.ProfD);
                        if (/%FilePicker%/.test(sp)) {
                            let filePicker = await this.filePicker();
                            if (!filePicker)
                                throw "Отмена!";
                            sp = sp.replace(/%FilePicker%/, filePicker);
                        }
                        let match = sp.match(/%Prompt\((.*?)\)%/);
                        if (match) {
                            let newName = { value: match[1] };
                            if (!Services.prompt.prompt(window, "Запрос", "Введите название", newName, null, {}))
                                throw "Отмена!";
                            sp = sp.replace(/%Prompt\(.*?\)%/, newName.value);
                        }
                        if (/%OpenURL%/.test(sp)) {
                            openuri = true;
                            sp = sp.replace("%OpenURL%", URL);
                        }
                        args[ind] = sp;
                    }
                    if (!openuri)
                        args.push(URL);
                } else
                    args = [URL];
                process.runwAsync(args, args.length);
            } else
                file.launch();
        } catch (e) {console.log(e);}
    },
    filePicker() {
        return new Promise(resolve => {
            var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
            try {
                fp.init(window.browsingContext, "Выбор папки", fp.modeGetFolder);
            } catch {
                fp.init(window, "Выбор папки", fp.modeGetFolder);
            }
            fp.open(res => resolve(res == fp.returnOK ? fp.file.path : null));
        });
    },
    readFromClipboard() {
        try {
            let trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
            trans.init(docShell.QueryInterface(Ci.nsILoadContext));
            trans.addDataFlavor("text/plain");
            let {clipboard} = Services, data = {}, url = "";
            clipboard.getData(trans, clipboard.kGlobalClipboard);
            trans.getTransferData("text/plain", data);
            if (data.value)
                url = data.value.QueryInterface(Ci.nsISupportsString).data.trim();
            if (/^(?:https?|ftp):/.test(url)) return url;
        } catch {}
        throw "Нет адреса в буфере обмена!";
    },
    getCurrentURL() {
        var url = gBrowser.selectedBrowser.currentURI.displaySpec;
        try {
            let _url = ReaderMode.getOriginalUrl(url);
            if (_url)
                url = Services.io.newURI(_url).displaySpec;
        } catch {}
        return url;
    },
    destructor() {
        for (let {elm, type, listener} of this._eventListeners)
            elm.removeEventListener(type, listener);
        for (let {elm, type, listener} of this._eventCListeners)
            elm.removeEventListener(type, listener);
    },
}).init())();

Отредактировано Vitaliy V. (29-05-2024 01:34:23)

Отсутствует

 

№143601-05-2024 04:42:13

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

Re: UCF - ваши кнопки, скрипты…

Vitaliy V. – спасибо!


Вопрос: делаю общие функции в MJS-скрипте через scriptsbackground: [ // In background [System Principal]:
Почему напрямую не работает globalThis[Symbol.for('Dobrov')] = Dobrov; и можно ли сделать проще, без
ChromeUtils.domProcessChild.childID || ({
………
}).init("browser-delayed-startup-finished");

Выделить код

Код:

var {Services} = globalThis || ChromeUtils.import("resource://gre/modules/Services.jsm");
var win = wm.getMostRecentWindow("navigator:browser") || globalThis;
var name = "Dobrov", EXPORTED_SYMBOLS = [`${name}Child`];
// так не работает: globalThis[Symbol.for('Dobrov')] = Dobrov;

ChromeUtils.domProcessChild.childID || ({
	init(topic) {
		globalThis[Symbol.for('Dobrov')] = Dobrov; //общие функции
	}
}).init("browser-delayed-startup-finished");

var Dobrov = {
	toTab(url = 'about:serviceworkers', go){ //открыть вкладку | закрыть её | выбрать
		for(var tab of win.gBrowser.visibleTabs)
			if(tab.linkedBrowser.currentURI.spec == url)
				{go ? win.gBrowser.selectedTab = tab : win.gBrowser.removeTab(tab); return;}
		win.gBrowser.addTrustedTab(url);
		win.gBrowser.selectedTab = win.gBrowser.visibleTabs[win.gBrowser.visibleTabs.length -1];
	},
	async Status(text,time){
		var StatusPanel = win.StatusPanel;
		if(StatusPanel.update.tid)
			win.clearTimeout(StatusPanel.update.tid)
		else {
			var {update} = StatusPanel;
			StatusPanel.update = () => {};
			StatusPanel.update.ret = () => {
				StatusPanel.update = update,StatusPanel.update();
			}
		}
		StatusPanel.update.tid = win.setTimeout(StatusPanel.update.ret,time || 5e3);
		StatusPanel._label = text;
	},
};

Отсутствует

 

№143701-05-2024 17:24:31

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: Firefox 126.0

Re: UCF - ваши кнопки, скрипты…

Dobrov пишет

Почему напрямую не работает globalThis[Symbol.for('Dobrov')] = Dobrov;

Так а как она заработает если на тот момент переменная var Dobrov = ещё не определена. Тогда пиши ниже или сразу так
globalThis[Symbol.for('Dobrov')] = {
    toTab(url = 'about:serviceworkers', go){ и т.д.
И вообще почему нормально не использовать export var Dobrov = {
потом где надо импортировать модуль
var {Dobrov} = ChromeUtils.importESModule(...
Или если это для JSWindowActorChild то должно быть что то вроде
export class DobrovChild extends JSWindowActorChild {
Вообще конечно странный код, зачем например это нужно
var {Services} = globalThis || ChromeUtils.import("resource://gre/modules/Services.jsm");
при том что импорт после || ни при каких условиях не будет выполнено даже если Services отсутствует в globalThis

Отредактировано Vitaliy V. (01-05-2024 17:35:02)

Отсутствует

 

№143804-05-2024 08:36:14

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

Re: UCF - ваши кнопки, скрипты…

Bug 1892965 - Rename Sidebar launcher and SidebarUI


Vitaliy V.
Затрагивает две сайдбарские кнопки в составе UCF.



Кстати, ещё, из-за этого бага,
если у тулбара отсутствует атрибут "key", то
в Главное меню —> Вид —> Панели инструментов
(аналогично и в customize-режиме «Настройка панели инструментов…»)


onViewToolbarsPopupShowing()
проставляет на тулбарский менюитем атрибут "key" как "null".


В результате, в консоли появляется запись типа
«Key null of menuitem Панель меню could not be found».


Так вот, это относится и к тулбарам UCF.
Может задать им пустой атрибут "key" (ну, как для "accesskey").
Или подождать, вдруг сами исправят.

Отсутствует

 

№143904-05-2024 08:44:17

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

Re: UCF - ваши кнопки, скрипты…

Vitaliy V.
Dumby
Я помню что по dom вы не любите, но на [aurora] и [nightly] начало задалбывать копирование адреса источника вместе с копируемым текстом, есть решение, или может скрипт придумаете? Если это вообще dom.

Отредактировано _zt (04-05-2024 08:45:59)

Отсутствует

 

№144004-05-2024 13:15:03

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

Re: UCF - ваши кнопки, скрипты…

Vitaliy V. спасибо за новый ucf_contextmenu_openwith !
Вопрос - как получить stdout при выполнении команд (терминала) ?


Скрипт создаёт строку в контекст-меню даже при отсутствии yt-dlp, поэтому нужна ещё проверка.
Например, берём последнюю строку из stdout, если «0», значит всё ОК:
which yt-dlp; echo $?

Отсутствует

 

№144104-05-2024 14:54:02

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: Firefox 126.0

Re: UCF - ваши кнопки, скрипты…

Dumby пишет

В результате, в консоли появляется запись типа
«Key null of menuitem Панель меню could not be found»
Может задать им пустой атрибут "key" (ну, как для "accesskey").

Хорошо, буду иметь ввиду если не исправят, пока это ничего не ломает, останова кода нигде не вызывает,
это всего лишь мусорит в консоли console.error(msg); в menu.js -> _computeAccelTextFromKeyIfNeeded() {

_zt пишет

по dom вы не любите

Смотря какой, DOM есть не только на сайтах, а где есть HTML XHTML XML, интерфейс браузера в том числе.

_zt пишет

на [aurora] и [nightly] начало задалбывать копирование адреса источника вместе с копируемым текстом, есть решение, или может скрипт придумаете?

А подробнее как воспроизвести это, может как раз какой-нибудь скрипт у вас это и делает.

Dobrov пишет

Скрипт создаёт строку в контекст-меню даже при отсутствии yt-dlp, поэтому нужна ещё проверка.

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

Отредактировано Vitaliy V. (04-05-2024 15:24:00)

Отсутствует

 

№144205-05-2024 19:12:34

Алексей У.
Участник
 
Группа: Members
Зарегистрирован: 10-04-2021
Сообщений: 182
UA: Firefox 69.0

Re: UCF - ваши кнопки, скрипты…

А где можно достать UserChromeFiles для Firefox 88? Тот, который для последних версий, в нем не работает.

Отсутствует

 

№144305-05-2024 21:23:52

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

Re: UCF - ваши кнопки, скрипты…

Алексей У. пишет

А где можно достать UserChromeFiles для Firefox 88?

Проверяйте!l


Win7

Отсутствует

 

№144407-05-2024 15:14:53

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: Firefox 126.0

Re: UCF - ваши кнопки, скрипты…

Добавил поддержку Гром-птицы, но без панелей и кнопок, CustomizableUI там урезанный поэтому кнопки таким способом не добавить.
Для доступа к настройкам UserChromeFiles добавленны пункты в меню.
Для версии [thunderbird] 115-116 нужно также заменить файлы из архива UserChromeFiles_Fix_115_ESR.zip

скрытый текст
UserChromeFilesTB.png

Отредактировано Vitaliy V. (07-05-2024 15:15:54)

Отсутствует

 

№144508-05-2024 12:18:50

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

Re: UCF - ваши кнопки, скрипты…

В [firefox]125 Add Toolbar Buttons отвалился, само расширение есть, а кнопок нет... в 117, вроде, было подобное. Можно ли как-то вылечить..?
Пока откатился на 124.0.2.

Отсутствует

 

№144608-05-2024 13:34:38

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: Firefox 126.0

Re: UCF - ваши кнопки, скрипты…

LGS
У меня какая версия firefox ?! Если работает на 126 думаете на 125 не будет.
Короче у вас либо старая версия Add Toolbar Buttons, либо слетел код для отключения подписи.
P.S. если старая версия от 2021 сначала её нужно удалить, потом ставить новую, а то будет два расширения установленно, т.к. в новой изменился ID

Отредактировано Vitaliy V. (08-05-2024 13:41:33)

Отсутствует

 

№144708-05-2024 14:47:44

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

Re: UCF - ваши кнопки, скрипты…

Vitaliy V. пишет

А подробнее как воспроизвести это, может как раз какой-нибудь скрипт у вас это и делает.

Да нет, нет такого и никогда не ставил, даже в обезьяну, просто такое не интересует.
Вот например - https://vyborok.com
Попробуйте скопировать что угодно (текст). И таких сайтов сейчас все больше и больше.
Конечно это от версии [firefox] не зависит, а то я выше так написал, что можно подумать, что это только в 126+ так.

Отредактировано _zt (08-05-2024 14:50:12)

Отсутствует

 

№144808-05-2024 15:02:51

Vitaliy V.
Участник
 
Группа: Members
Зарегистрирован: 19-09-2014
Сообщений: 2186
UA: Firefox 126.0

Re: UCF - ваши кнопки, скрипты…

_zt
dom.event.clipboardevents.enabled = false

Отсутствует

 

№144908-05-2024 17:48:47

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

Re: UCF - ваши кнопки, скрипты…

Vitaliy V.
Точно, спасибо. А ведь раньше было отключено, но потом arkenfox с толку сбил.

Отсутствует

 

№145008-05-2024 19:16:37

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

Re: UCF - ваши кнопки, скрипты…

Vitaliy V. пишет

У меня какая версия firefox ?! Если работает на 126 думаете на 125 не будет

Я немного по другому думаю - почему у вас и других работает, а у меня нет..?

Vitaliy V. пишет

у вас либо старая версия Add Toolbar Buttons, либо слетел код для отключения подписи

Ни 2021, ни 2024 версии не работают. АТВ устанавливается, в списке установленных отображается, но кнопок нет. В ФФ124 все нормально.
Антиподписной код у меня этот:
https://forum.mozilla-russia.org/viewto … 59#p800159
Вроде бы не менялся, хотя, может, я что-то и пропустил...

Отредактировано LGS (08-05-2024 19:25:02)

Отсутствует

 

Board footer

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