Почему же, так же с патчем css файлов наверняка будет работать, тут не добавленно ничего такого новейшего.
Так в новой версии UCF нет vertical_top_bottom_bar.css, который присутствует в патче. Или это неважно?
«The Truth Is Out There»
Отсутствует
_zt
А что там может не работать если сам лоадер загружается то и модули должны
Отредактировано Vitaliy V. (08-08-2024 14:52:58)
Отсутствует
_zt
TST не могу проверить, есть то что можно проверить и не работает у вас?
Отсутствует
Vitaliy V.
Там всего три скрипта, два из них от TST, а третий работает.
Добавлено 21-05-2024 02:38:22
Dumby
Из за чего эти два .mjs скрипта могут не загружаться в крайнем ucf?
18-03-2024 20:30:25
Отредактировано _zt (21-05-2024 02:38:51)
Отсутствует
_zt
Похоже это связано с более ранней инициализацией фоновых скриптов, потому как более ничего не изменял что могло бы повлиять
Отсутствует
А точно, но его просто переименовать нужно в toolbars.css обновлю сейчас архив
Vitaliy V., спасибо. Обновился на 115 ESR, на первый взгляд всё работает нормально.
«The Truth Is Out There»
Отсутствует
Как исправить?
Значит придется сделать как было, иначе пишет global null на раннем этапе загрузки
ChromeUtils.importESModule("resource://gre/modules/ExtensionParent.sys.mjs").ExtensionParent.apiManager.global.tabTracker;
обновил два файла user_chrome.js user_chrome_tb.js
Отредактировано Vitaliy V. (21-05-2024 03:18:57)
Отсутствует
Vitaliy V.
Ура, заработало. Спасибо.
Тут еще один вопрос давно меня мучает. Нельзя ли растянуть панель табов на пару пикселей, или другим способом прикрыть виндовую обводку окна по бокам панели? Но только для панели табов.
Отсутствует
Dumby, поправьте пожалуйста кнопочку под 126.
// (async func => CustomizableUI.createWidget({ id: "ucf_SaveAsPNG", label: "Сохранить как PNG", tooltiptext: "Сохранить как PNG", localized: false, // defaultArea: CustomizableUI.AREA_NAVBAR, onCreated(btn) { var win = btn.ownerGlobal; new win.Function("_id, xhtmlns, addDestructor", func.toString().slice(7, -1)).call( btn, this.id, "http://www.w3.org/1999/xhtml", destructor => win.addEventListener("unload", destructor, {once: true}) ); btn.setAttribute("image", "data:image/png;base64,....."); } }))(() => { ((main, parts) => this._handleClick = () => { var df = MozXULElement.parseXULToFragment(` <menupopup> <menuitem class="menuitem-iconic" image="data:image/png;base64,....." label="Сохранить всю страницу как PNG" value="all"/> <menuitem class="menuitem-iconic" image="data:image/png;base64,....." label="Сохранить видимую часть страницы как PNG" value="page"/> <menuitem class="menuitem-iconic" image="data:image/png;base64,....." label="Сохранить выбранный элемент страницы как PNG" value="click"/> <menuitem class="menuitem-iconic" image="data:image/png;base64,....." label="Сохранить выбранную область страницы как PNG" value="clipping"/> </menupopup> `); var popup = df.firstChild; popup.setAttribute("context", ""); popup.setAttribute("oncommand", "handleCommand(event);"); popup.handleCommand = e => { var name = _id + ":DataURLReady"; main = main.replace("%MESSAGE_NAME%", name); var urls = {}, configurable = true, enumerable = true; Object.entries(parts).forEach(([key, part]) => Object.defineProperty(urls, key, { configurable, enumerable, get() { var value = `data:;charset=utf-8,({${ encodeURIComponent(main + part) }%0A}).init("${key}")`; Object.defineProperty(urls, key, {configurable, enumerable, value}); return value; }})); // Получить название вкладки без не сохраняемых символов и лишних пробелов ..... var getTabLabel = () => { var label = gBrowser.selectedTab.label; var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " "); return label.substring(0, 50); } var listener = msg => { var fp = makeFilePicker(); fp.init(window, "Сохранить как…", fp.modeSave); fp.appendFilter("", "*.png"); var fileName = getTabLabel(); fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '').replace(/\s+/g, '_').slice(0, 100).replace(/^\s+|\s+$/g, ''); var fileDate = (function () { var d = new Date(), z = function(n){return (n < 10 ? '0' : '') + n}; return '[' + z(d.getFullYear()) + '_' + z(d.getMonth()+1) + '_' + z(d.getDate()) + '\u00F7' + z(d.getHours()) + '_' + z(d.getMinutes()) + '_' + z(d.getSeconds()) + ']'; })(); fp.defaultString = fileName + "_" + fileDate + ".png"; fp.open(res => res == fp.returnCancel || !fp.file || makeWebBrowserPersist().saveURI( Services.io.newURI(msg.data), document.nodePrincipal, null, null, null, null, null, fp.file, null, null )); } messageManager.addMessageListener(name, listener); addDestructor(() => messageManager.removeMessageListener(name, listener)); (popup.handleCommand = e => gBrowser.selectedBrowser.messageManager .loadFrameScript(urls[e.target.value], false) )(e); } this.append(df); (this._handleClick = () => popup.openPopup(this, "after_start"))(); })(` init(cmd) { cmd.startsWith("c") ? this[cmd].init(this[cmd].parent = this) : this[cmd](); }, capture(win, x, y, width, height) { var canvas = win.document.createElementNS("${xhtmlns}", "canvas"); canvas.width = width; canvas.height = height; var ctx = canvas.getContext("2d"); var tryDraw = ind => { try {ctx.drawWindow(win, x, y, canvas.width, canvas.height, "white")} catch(ex) {canvas.height = ind * canvas.width; tryDraw(--ind);} } tryDraw(17); sendAsyncMessage("%MESSAGE_NAME%", canvas.toDataURL("image/png")); }, `, { all: `all() { var win = content; this.capture(win, 0, 0, win.innerWidth + win.scrollMaxX, win.innerHeight + win.scrollMaxY); }`, page: `page() { var win = content, doc = win.document, body = doc.body, html = doc.documentElement; var scrX = (body.scrollLeft || html.scrollLeft) - html.clientLeft; var scrY = (body.scrollTop || html.scrollTop) - html.clientTop; this.capture(win, scrX, scrY, win.innerWidth, win.innerHeight); }`, clipping: `clipping: { handleEvent(e) { if (e.button) return false; e.preventDefault(); e.stopPropagation(); switch(e.type) { case "mousedown": this.downX = e.pageX; this.downY = e.pageY; this.bs.left = this.downX + "px"; this.bs.top = this.downY + "px"; this.body.appendChild(this.box); this.flag = true; break; case "mousemove": if (!this.flag) return; this.moveX = e.pageX; this.moveY = e.pageY; if (this.downX > this.moveX) this.bs.left = this.moveX + "px"; if (this.downY > this.moveY) this.bs.top = this.moveY + "px"; this.bs.width = Math.abs(this.moveX - this.downX) + "px"; this.bs.height = Math.abs(this.moveY - this.downY) + "px"; break; case "mouseup": this.uninit(); break; } }, init() { var win = {}; Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager) .getFocusedElementForWindow(content, true, win); this.win = win.value; this.doc = this.win.document; this.body = this.doc.body; if (!HTMLBodyElement.isInstance(this.body)) { Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService) .showAlertNotification("${self.image}", ${JSON.stringify(self.label)}, "Не удается захватить!"); return false; } this.flag = null; this.box = this.doc.createElement("div"); this.bs = this.box.style; this.bs.border = "red dashed 1px"; this.bs.position = "absolute"; this.bs.zIndex = "2147483647"; this.defaultCursor = this.win.getComputedStyle(this.body, "").cursor; this.body.style.cursor = "crosshair"; ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.addEventListener(type, this, true)); }, uninit() { var pos = [this.win, parseInt(this.bs.left), parseInt(this.bs.top), parseInt(this.bs.width), parseInt(this.bs.height)]; this.body.style.cursor = this.defaultCursor; this.body.removeChild(this.box); this.parent.capture.apply(this, pos); ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.removeEventListener(type, this, true)); } }`, click: `click: { getPosition() { var html = this.doc.documentElement; var body = this.doc.body; var rect = this.target.getBoundingClientRect(); return [ this.win, Math.round(rect.left) + (body.scrollLeft || html.scrollLeft) - html.clientLeft, Math.round(rect.top) + (body.scrollTop || html.scrollTop) - html.clientTop, parseInt(rect.width), parseInt(rect.height) ]; }, highlight() { this.orgStyle = this.target.hasAttribute("style") ? this.target.style.cssText : false; this.target.style.cssText += "outline: red 1px solid; outline-offset: 1px; -moz-outline-radius: 2px;"; }, lowlight() { if (this.orgStyle) this.target.style.cssText = this.orgStyle; else this.target.removeAttribute("style"); }, handleEvent(e) { switch(e.type){ case "click": if (e.button) return; e.preventDefault(); e.stopPropagation(); this.lowlight(); this.parent.capture.apply(this, this.getPosition()); this.uninit(); break; case "mouseover": if (this.target) this.lowlight(); this.target = e.target; this.highlight(); break; } }, init() { this.win = content; this.doc = content.document; ["click", "mouseover"].forEach(type=> this.doc.addEventListener(type, this, true)); }, uninit() { this.target = false; ["click", "mouseover"].forEach(type=> this.doc.removeEventListener(type, this, true)); } }` }); });
«The Truth Is Out There»
Отсутствует
Консоль пишет
код на замену:
// fp.init(window, "Сохранить как…", fp.modeSave); fp.init( !("inIsolatedMozBrowser" in window.browsingContext.originAttributes) ? window.browsingContext : window , "Сохранить как…", fp.modeSave);
Жизнь иногда такое выкидывает, что хочется подобрать...
Отсутствует
Farby, большое спасибо.
«The Truth Is Out There»
Отсутствует
Farby
Как я понимаю, мне тоже надо изменить fp.init здесь? Перестало работать.
И ещё Экспорт папки в HTML.
Отсутствует
xrun1
Принуждать не имею право, но можете...
если не нужна обратная совместимость то fp.init(win, можно заменить fp.init(win.browsingContext,
Жизнь иногда такое выкидывает, что хочется подобрать...
Отсутствует
DumbyЭтот скрипт перестал работать, можете поправить? Возможно тоже с fp.init связано.
С правками от Farby заработало. Спасибо.
Экспорт папки в HTML тоже заработал.
Отредактировано _zt (21-05-2024 15:07:41)
Отсутствует
Vitaliy V. потестил новый UCF, есть пожелания:
1) неудобно, что в path: "…" не грузятся скрипты JSM и MJS – пока гружу так:
mjsmLoad = (s, e = /\.mjs$/i.test(s) ? "ESModule" : "") => `ChromeUtils.import${e}("chrome://user_chrome_files/content/custom_scripts/${s}")`;
2) зачем лишний ospath ? Проще заменять %OS% сразу в path: "custom_styles_all_user_%OS%.css"
3) насчёт вшитых в UCF имён OS: может проще брать нативные имена OS из AppConstants.platform ?
В UCF прошито имя «macos», но все используют macosx, кроме того, может кто-то Firefox на другой OS запустит, имя которой в UCF не вшито…
Отредактировано Dobrov (21-05-2024 16:43:30)
Отсутствует
Обновил UCF
Наконец-то в методах {_}load{All}ChromeScripts()
блоки catch перестали быть пустыми.
"UTF-8" так и кочует из версии в версию.
Нет, не мешает, конечно, просто смотрится довольно странно,
ведь третий аргумент для loadSubScript() удалили аж с Firefox 66.
И, немного напрягает использование там new win.Function()
Допустим, запускаем с консоли
setTimeout(
win => console.log(win.wrappedJSObject.ucf_custom_script_all_win),
1500,
openDialog("about:robots", "", "centerscreen")
);
В предыдущей версии UCF — логируется объект ucf_custom_script_all_win
А в этой версии — получаем EvalError, следом CSP-ругань, и логируется undefined
Да, я понимаю, пример высосан из пальца.
Вот, вспомнил более жизненный, но отдалённый пример.
Нужно включить настройку sidebar.revamp и перезапуститься.
И потыкать по кнопкам на <html:sidebar-main>
При загрузке в сайдбар таких страниц как «Customize sidebar»,
«Tabs from other devices», и «History» — в консоли та же картина.
Призрачно маячит и совсем серьёзная угроза.
Вот в этом баге они объясняют
чем им там что не нравится, и в том числе тем, что это
«stops us adding a restrictive CSP to browser windows».
То есть, как я понимаю, есть планы подсадить CSP-гадости и в окна браузера.
Тогда, разумеется, много чего может отвалиться, а не только здесь.
Вобщем — есть над чем задуматься.
Отсутствует
Но только для панели табов
Это врядли, это же системная рамка, панель вкладок или что либо от её не перекроет, но убрать всю рамку вероятно можно, но пока не пробовал, и у меня нет 10 только 11, не знаю есть разница или нет. Кстати напомните если сохранился код как я на win7 рамку окна скрывал, там вроде была замена системной рамки на рамку от ?
Dobrov
1. В path ничего лишнего не нужно, а вот с ospath могу добавить например параметр module: true и будет грузится ESModule, поддержку JSM добавлять смысла не вижу, в совместимой с UCF минимальной версии 115 работают ESModule
2. Это смотря с какой стороны посмотреть, конечно можно все свалить в кучу и пусть парсер трудится, но если попытаться оптимизировать код то в подавляющем большинстве случаев не требуются все эти проверки ОС, версий , а значит что происходит если if path вернет true то до else if дело не дойдет следовательно код отработает быстрее.
Или можешь предложи свою концепцию.
3. имена OS из AppConstants.platform, например win что это название ОС или окно или объект window ???
далее macosx это устаревшее название, современные яблочные ОС называются macos
может кто-то Firefox на другой OS запустит, имя которой в UCF не вшито и что случится, вернет то что выдаст Services.appinfo.OS.toLowerCase() какие проблемы с этим?
И, немного напрягает использование там new win.Function()
Согласен мне это тоже не нравится, но пока не нашел способа. А есть ли он кроме использования файла с loadSubScript?
А была ещё мысль использовать песочницу Cu.Sandbox для этого, но пока использовал что проще.
смотрится довольно странно,
ведь третий аргумент для loadSubScript() удалили аж с Firefox 66.
Ясно же что я совершенно не слежу за этими багами, я не настолько погружен в
Отредактировано Vitaliy V. (21-05-2024 18:50:38)
Отсутствует
А есть ли он кроме использования файла с loadSubScript?
Ну, loadSubScript() ведь грузит data: адреса.
И, даже вроде blob: адреса. А если resource: — то вообще шикарно.
ChromeUtils.compileScript() вроде тоже компилит с data: адресов.
Но асинхронно, однако если пнуть на старте, то, полагаю, к тому моменту,
когда понадобится, возвращённый promise уже успеет разрезольвиться PrecompiledScript'ом.
А дальше просто вызываем его метод executeInGlobal()
была ещё мысль использовать песочницу Cu.Sandbox для этого
Ну, если уж не жалко создавать для окон сандбоксы,
то тогда можно рассмотреть и альтернативу с использованием дебаггера.
Я вот так пробовал. Это не в смысле правки, а просто вспоминал как это делается.
Выглядит, кстати, проще всего. Огорчает только раз-лэйзи-фикация дебаггера.
/* new win.Function(` */ UcfPrefs.dbg.makeGlobalObjectReference(win).executeInGlobal(` window.ucf_custom_script_all_win = { //....... }; `); /* `).apply(win); */
Отсутствует
с ospath могу добавить например параметр module: true и будет грузится ESModule, поддержку JSM добавлять смысла не вижу, в совместимой с UCF минимальной версии 115 работают ESModule
Добавь пожалуйста! MJS скрипты нужны, здесь уже несколько таких есть.
Отсутствует
Появилась тестовая с вертикальными вкладками. Скачать можно здесь Directory Listing: /pub/firefox/nightly/latest-larch/
Отсутствует
loadSubScript() ведь грузит data: адреса
Да но вроде это не рекомендуемый способ, впрочем сделал так для параметра func,
а для создания объектов ucf_custom_script_win, ucf_custom_script_all_win использовал методы Cu.createObjectIn и Cu.exportFunction,
что там по ним багов не завезли?
Добавь пожалуйста! MJS скрипты нужны
Добавил проверь, только для фоновых скриптов, для оконных то скриптов вроде не требуется.
В параметре module кроме Boolean можно указать массив из строк ["importSymbol"]
это будет доступно в песочнице или так UcfPrefs.customSandbox.importSymbol
PS: Для модулей следует указать полный адрес chrome://user_chrome_files/content/custom_scripts/... в ospath
так как можно же не только из UCF импортировать но и браузера
UPD: впрочем добавил для модулей если вначеле есть %UCFDIR% то будет замена на chrome://user_chrome_files/content/custom_scripts/
Отредактировано Vitaliy V. (23-05-2024 17:33:54)
Отсутствует