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);
Отсутствует
вместо зеленой звездочки при добавлении кнопки ярыка сайта отображаетя глобус посмотрите пожалуйста
Не получилось воспроизвести.
Никакого глобуса, либо favicon страницы, либо зелёная звёздочка.
может там в коде уже что то надо изменить
В смысле какого-то отвала — нет, не вижу ничего такого.
А в смысле косячков — конечно же есть, куда без них.
Например, вместо this.write определённо должно быть this.save
Отсутствует
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)
Отсутствует
А смотрю со своими иконками наверно не справитесь
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>
Отсутствует
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; } }))();
Вкладки в контейнере.............
//Вкладки в контейнере............. (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)
Отсутствует
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) }))();
Отсутствует
даже готовое не могу сообразить с кнопкой save доавил код что Вы только что дали в custom_script.js
Я хз почему не работает, и что значит добавил, нужно заменить код в custom_script.js
Отсутствует
egorsemenov06
Наверняка где то ошибку синтаксиса допустили, все там должно работать
Отсутствует
Vitaliy V. раз тут завал просьб, добавлю свои 3 копейки:
Просьба улучшить ucf_contextmenuopenwith для нормальной работы с yt-dlp:
1) в режиме "Открыть страницу в …" если в Clipboard только одна строка и текст заканчивается на .m3u8, то передавать его вместо %OpenURI
2) есть выделенный текст ? передать его вместо %OpenURI. Чтобы работало на moz-extension://, где Video DownloadHelper открывает «Детали» со ссылками.
(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);
Отсутствует
если в Clipboard только одна строка и текст заканчивается на .m3u8
Ссылки с m3u не всегда так заканчиваются, может быть так .m3u8?бла-бла-бла, и почему только плейлисты m3u а просто медиа файлы и т.д.
Кстати для прямых ссылок на медиа и m3u не нужен yt-dlp, см. ниже пример копирования потока с FFmpeg, можно сразу конвертировать с заданным кодеком.
Короче сделал так, при зажатой клавише Shift или СКМ ссылка берется из буфера, и ещё добавил параметр clipboard можно добавить пункт для работы с буфером обмена.
Чтобы работало на 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)
Отсутствует
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; }, };
Отсутствует
Почему напрямую не работает 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)
Отсутствует
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").
Или подождать, вдруг сами исправят.
Отсутствует
Vitaliy V.
Dumby
Я помню что по dom вы не любите, но на и начало задалбывать копирование адреса источника вместе с копируемым текстом, есть решение, или может скрипт придумаете? Если это вообще dom.
Отредактировано _zt (04-05-2024 08:45:59)
Отсутствует
Vitaliy V. спасибо за новый ucf_contextmenu_openwith !
Вопрос - как получить stdout при выполнении команд (терминала) ?
Скрипт создаёт строку в контекст-меню даже при отсутствии yt-dlp, поэтому нужна ещё проверка.
Например, берём последнюю строку из stdout, если «0», значит всё ОК:
which yt-dlp; echo $?
Отсутствует
В результате, в консоли появляется запись типа
«Key null of menuitem Панель меню could not be found»
Может задать им пустой атрибут "key" (ну, как для "accesskey").
Хорошо, буду иметь ввиду если не исправят, пока это ничего не ломает, останова кода нигде не вызывает,
это всего лишь мусорит в консоли console.error(msg); в menu.js -> _computeAccelTextFromKeyIfNeeded() {
по dom вы не любите
Смотря какой, DOM есть не только на сайтах, а где есть HTML XHTML XML, интерфейс браузера в том числе.
на и начало задалбывать копирование адреса источника вместе с копируемым текстом, есть решение, или может скрипт придумаете?
А подробнее как воспроизвести это, может как раз какой-нибудь скрипт у вас это и делает.
Скрипт создаёт строку в контекст-меню даже при отсутствии yt-dlp, поэтому нужна ещё проверка.
Такие проверки дорого стоят, может быть задержка появления меню или пунктов, лучше сделать например так: при клике на пункт если приложение отсутствует, то выводится уведомление типа такое то приложение по данному пути не найдено, установите, или скрыть пункт меню
Отредактировано Vitaliy V. (04-05-2024 15:24:00)
Отсутствует
А где можно достать UserChromeFiles для Firefox 88? Тот, который для последних версий, в нем не работает.
Отсутствует
А где можно достать UserChromeFiles для Firefox 88?
Win7
Отсутствует
Добавил поддержку Гром-птицы, но без панелей и кнопок, CustomizableUI там урезанный поэтому кнопки таким способом не добавить.
Для доступа к настройкам UserChromeFiles добавленны пункты в меню.
Для версии 115-116 нужно также заменить файлы из архива UserChromeFiles_Fix_115_ESR.zip
Отредактировано Vitaliy V. (07-05-2024 15:15:54)
Отсутствует
LGS
У меня какая версия firefox ?! Если работает на 126 думаете на 125 не будет.
Короче у вас либо старая версия Add Toolbar Buttons, либо слетел код для отключения подписи.
P.S. если старая версия от 2021 сначала её нужно удалить, потом ставить новую, а то будет два расширения установленно, т.к. в новой изменился ID
Отредактировано Vitaliy V. (08-05-2024 13:41:33)
Отсутствует
А подробнее как воспроизвести это, может как раз какой-нибудь скрипт у вас это и делает.
Да нет, нет такого и никогда не ставил, даже в обезьяну, просто такое не интересует.
Вот например - https://vyborok.com
Попробуйте скопировать что угодно (текст). И таких сайтов сейчас все больше и больше.
Конечно это от версии не зависит, а то я выше так написал, что можно подумать, что это только в 126+ так.
Отредактировано _zt (08-05-2024 14:50:12)
Отсутствует
_zt
dom.event.clipboardevents.enabled = false
Отсутствует
У меня какая версия firefox ?! Если работает на 126 думаете на 125 не будет
Я немного по другому думаю - почему у вас и других работает, а у меня нет..?
у вас либо старая версия Add Toolbar Buttons, либо слетел код для отключения подписи
Ни 2021, ни 2024 версии не работают. АТВ устанавливается, в списке установленных отображается, но кнопок нет. В ФФ124 все нормально.
Антиподписной код у меня этот:
https://forum.mozilla-russia.org/viewto … 59#p800159
Вроде бы не менялся, хотя, может, я что-то и пропустил...
Отредактировано LGS (08-05-2024 19:25:02)
Отсутствует