rubel
Это что ли?
// ==UserScript== // @name MENU`s Restart Items // @author Vitaliy V. // @include main // @note https://forum.mozilla-russia.org/viewtopic.php?pid=785107#p785107 // @shutdown window.menusrestartitems.uninit(); // ==/UserScript== location.href.startsWith("chrome://browser/content/browser.x") && (this.menusrestartitems = { init(that) { var btnClass = "ucf-appmenu-restart-button", muimID = "ucf_menu_FileRestartItem", rLocale = Services.locale.requestedLocale.startsWith("ru"), rLabel = rLocale ? "Перезапуск": "Restart", rToolTiptext = rLocale ? "ЛКМ: Перезапустить приложение\nСКМ: Перезапустить без дополнений\nПКМ: Перезапустить и заново создать кэш быстрого запуска" : "L: Restart the application\nM: Restart without add-ons\nR: Restart and recreate the quick start cache.", ucf_script = (window.ucf_custom_script_win == that) ? "ucf_custom_script_win" : (window.ucf_custom_script_all_win == that) ? "ucf_custom_script_all_win" : "window"; var abtns = document.querySelector("template#appMenu-viewCache")?.content.querySelectorAll("#appMenu-quit-button, #appMenu-quit-button2") || document.querySelectorAll("#appMenu-quit-button"); for (let abtn of abtns) { let frag = MozXULElement.parseXULToFragment(`<toolbarbutton/>`); let btn = frag.firstElementChild; btn.id = muimID + '1'; btn.className = `${btnClass} subviewbutton${abtn.classList.contains("subviewbutton-iconic") ? "" : " subviewbutton-iconic"}`; btn.setAttribute("label", rLabel); btn.setAttribute("tooltiptext", rToolTiptext); btn.setAttribute("shortcut", "Ctrl+Alt+Q"); btn.setAttribute("onclick", `${ucf_script}.menusrestartitems.restart_mozilla(event)`); abtn.before(frag); } var aftermuim = document.querySelector("#menu_FilePopup #menu_FileQuitItem"); if (aftermuim) { let muim = document.createXULElement("menuitem"); muim.id = muimID; muim.className = "menuitem-iconic"; muim.setAttribute("label", rLabel); muim.setAttribute("tooltiptext", rToolTiptext); muim.setAttribute("acceltext", "Ctrl+Alt+Q"); muim.setAttribute("context", ""); muim.setAttribute("onclick", `${ucf_script}.menusrestartitems.restart_mozilla(event)`); aftermuim.before(muim); } var style = "data:text/css;charset=utf-8," + encodeURIComponent(` .${btnClass}.subviewbutton-iconic, #${muimID} { list-style-image: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='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='M11.4 5.6h4v-4M14.8 5C14.1 3.5 12 .6 8 .6S.6 4 .6 8 4 15.4 8 15.4s6.3-2.9 7-5'/></svg>") !important; } .${btnClass}.subviewbutton-iconic .toolbarbutton-icon, #${muimID} .menu-iconic-icon { -moz-context-properties: fill !important; fill: color-mix(in srgb, currentColor 20%, #f38525) !important; } `); try { windowUtils.loadSheetUsingURIString(style, windowUtils.USER_SHEET); } catch (e) {} window.addEventListener("keydown", this); that.unloadlisteners?.push("menusrestartitems"); }, restart_mozilla(e) { if (e.button == 0) this._restart_mozilla(); else if (e.button == 1) e.view.safeModeRestart(); else if (e.button == 2) this._restart_mozilla(true); }, _restart_mozilla(nocache = false) { var cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool); Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart"); if (cancelQuit.data) return false; if (nocache) Services.appinfo.invalidateCachesOnRestart(); var restart = Services.startup; restart.quit(restart.eAttemptQuit | restart.eRestart); }, handleEvent(e) { if (e.code == "KeyQ" && e.ctrlKey && e.altKey) this._restart_mozilla(); }, destructor() { window.removeEventListener("keydown", this); }, uninit() { var muimID = "ucf_menu_FileRestartItem"; this.destructor(); document.getElementById(muimID).remove(); document.getElementById(muimID + "1").remove(); delete menusrestartitems; } }).init(this);
Жизнь иногда такое выкидывает, что хочется подобрать...
На форуме
Был такой скрипт для открытия Findbar двойным щелчком СКМ. На новых версиях уже не работает. Что надо исправить?
скрытый текстaddEventListener("click", async e => {
if (e.button != 1 || e.detail != 2) return;var findbar = gFindBar;
if (findbar) {
if (!findbar.hidden) return //findbar.close();
} else {
findbar = await gFindBarPromise;
await new Promise(resolve => setTimeout(resolve, 0));
}
findbar.onFindCommand();}, false, gBrowser.tabpanels || 1);
О, я смотрю на руборде не поленились заняться
выканючиванием из тебя всяких подробностей.
Тогда можно попробовать заменить click на mousedown.
Ну и вынести асинхрон в отдельную функцию,
чтобы не плодить лишние промисы.
Код не для CB (а то приведённый выглядит именно так).
(async () => { var dblmmd = async () => { var findbar = gFindBar; if (findbar) { if (!findbar.hidden) return //findbar.close(); } else { findbar = await gFindBarPromise; //await new Promise(setTimeout); } findbar.onFindCommand(); } gBrowser.tabpanels.addEventListener( "mousedown", e => e.button == 1 && e.detail == 2 && dblmmd() ); })();
Отредактировано Dumby (16-11-2024 12:54:34)
Отсутствует
Dumby
Да, код был для СВ, но прекрасно работал в старом USF! Спасибо за исправления. Так же на Руборде предложили еще вариант
var findbar = gFindBar;
if (findbar) {
if (!findbar.hidden) return //findbar.close();
} else {
findbar = await gFindBarPromise;
await new Promise(resolve => setTimeout(resolve, 0));
}
findbar.onFindCommand();
Отсутствует
Да, код был для СВ, но прекрасно работал в старом USF!
Охотно верю. Но работал чуть иначе.
В CB такой код добавляет слушатель клика
для где-то в пределах области контента,
а в UCF он добавляет слушатель клика
в пределах всего окна браузера.
предложили еще вариант
Вариант немного странный.
Чтобы работало нужен включённый autoscroller,
и чтобы он нарисовался, то есть, чтобы было что скроллить.
Хорошо, это так и заявлено, сочтём за концепцию.
Но вот, допустим, начинаем обычную autoscroll-сессию, скроллим сколько надо,
и завершаем autoscroll-сессию, кнопкой мыши или нажав клавишу Esc.
И тут — выскакивает findbar, а это уже не то, что должно ожидаться.
Отсутствует
Тогда можно попробовать заменить click на mousedown
А если бы не получилось, в том числе и через mouseup, то какие есть альтернативы? Не факт, что нативную функцию preventClickEvent() ваяли только для авто скролла и с каким-то странным пояснением;
"The following mouse click/auxclick event on the autoscroller shouldn't be fired in web content for compatibility with Chrome".
Пробовал нивелировать через stopPropagation() - работает, но тогда и авто скролл не появляется, а как его самому запустить - не знаю
Отсутствует
Всем привет!
На загруженные файлы можно перейти, нажав кнопку “Показать в проводнике», пока список Загрузок не очищен.
Вопрос: как из JS-кода показать в проводнике последний загруженный файл ?
В идеале не только последний, но и по номеру - перейти в проводнике на последний, предпоследний и т.д. файл.
Ещё надо получить полный путь к последнему загруженному файлу (чтоб переименовывать по имени из буфера обмена).
Отсутствует
А можно ли приспособить старый USF от 2021-6-5 работать с FF128 и новее?
Это довольно заморочно.
Даже если можно, то это не слишком хорошая идея.
Получится нечто неподдерживаемое, и выпадающее из общего обсуждения.
Надо полагать, что чем-то не устраивает "новый" UCF.
Тогда лучше попытаться «приспособить» неустройки используя его,
а не тащить старый.
Так что же не так с новым?
Может расскажи о проблеме, вдруг там решение несложное.
А если бы ...
... не получилось, в том числе и через mouseup, то какие есть альтернативы?
Что значит «если бы не получилось»?
Если бы не получилось, то пробовать дальше,
пытаться разобраться что происходит, чесать репу...
То есть — смотреть по конкретной ситуации.
А если, и в итоге не получилось,
ну что ж, такое бывает, чаще чем хотелось бы.
Не факт, что нативную функцию preventClickEvent() ваяли только для авто скролла
Что значит «ваяли только»? Это типа
«мы запилим метод, но использовать будем только для автоскролла, и никогда иначе»?
Ну тогда да, звучит маловероятно, и получается, что «не факт».
Это вообще рассуждение о намерении, которое знать невозможно,
если только оно не указано явно.
А ваяли именно для автоскролла. Bug —> part 2 —> webidl diff.
Я помотрел в 134, и preventClickEvent() используется только в gre omni,
и только в двух местах, и оба связаны с автоскроллером.
Но да, «не факт», что в будущем, им не приспичит использовать где-то ещё.
как его самому запустить - не знаю
Что значит «запустить»? Запустить на чём?
Подлежащее скроллу добро находится в другом процессе
(ну, если только речь не о страницах в этом процессе, типа about:license).
И из этого процесса мы не знаем на чём там мышь приземлилась.
Так что, либо разворачивать что-то в контентских процессах,
либо ... даже не знаю что. Можно попробовать по координатам
подрядить nsIDOMWindowUtils.elementFromPoint()
но уверенности, конечно, никакой.
Вот, допустим, попробуем вызов автоскроллера по Alt+ЛКМ.
Ну, просто демо-набросок для консоли.
(() => { var callHandleEvent = (makeEvent, ids, x, y) => { for(var id of ids) { var actor = WindowGlobalChild .getByInnerWindowId(id).getActor("AutoScroll"); var win = actor.document.ownerGlobal; if (win.windowRoot.ownerGlobal == win) { // ??? var r = win.devicePixelRatio; x /= r; y /= r; } var trg = win.windowUtils.elementFromPoint( x - win.mozInnerScreenX, y - win.mozInnerScreenY, true, false ); if (trg && !trg.matches("iframe,frame")) { actor.handleEvent(makeEvent(trg, x, y)); break; } } } var makeEvent = (trg, x, y) => ({ button: 1, screenX: x, screenY: y, isTrusted: true, type: "mousedown", originalTarget: trg, composedTarget: trg, view: trg.ownerGlobal, clickEventPrevented() {} }); var prfx = "data:,(" + encodeURIComponent( callHandleEvent + ")(" + makeEvent + ", " ); var loadScripts = (bbc, x, y) => { var map = new Map(); for(var bc of bbc.getAllBrowsingContextsInSubtree()) { var cwg = bc.currentWindowGlobal; if (!cwg) continue; var id = cwg.innerWindowId; var pid = cwg.osPid, arr = map.get(pid); arr ? arr.push(id) : map.set(pid, [id]); } var {ppmm} = Services; for(var ind = 0, count = ppmm.childCount; ind < count; ind++) { var pmm = ppmm.getChildAt(ind); var ids = map.get(pmm.osPid); ids && pmm.loadProcessScript(prfx + `[${ids}], ${x}, ${y});`, false); } } gBrowser.tabpanels.addEventListener("click", e => { if (e.button || !e.altKey || e.ctrlKey || e.shiftKey) return; var br = gBrowser.selectedBrowser; if (!br.matches(":hover")) return; var x = e.screenX, y = e.screenY; if (br.isRemoteBrowser) { var r = window.devicePixelRatio; loadScripts(br.browsingContext, x *= r, y *= r); } else e.target.ownerGlobal .windowGlobalChild.getActor("AutoScroll") .handleEvent(makeEvent(e.originalTarget, x, y)); }); })();
На загруженные файлы можно перейти, нажав кнопку “Показать в проводнике», пока список Загрузок не очищен.
Вопрос: как из JS-кода показать в проводнике последний загруженный файл ?
В идеале не только последний, но и по номеру - перейти в проводнике на последний, предпоследний и т.д. файл.
Ещё надо получить полный путь к последнему загруженному файлу (чтоб переименовывать по имени из буфера обмена).
Список можно получить так (если вместе с приватными)
await (await Downloads.getList(Downloads.ALL)).getAll();
Объект Downloads есть в окне браузера.
А там, где нет — можно импортировать
resource://gre/modules/Downloads.sys.mjs
Выражение вернёт копию массива объектов Download
(упоминаются в resource://gre/modules/DownloadCore.sys.mjs).
Полный путь к файлу — будет download.target.path
Возможно, надо отфильтровать от каких-нибудь
неудавшихся, отменённых, перемещенных, ещё не докачавшихся,
это уже смотри сам, консоль в помощь.
Последний загруженный — наверно, у которого endTime
будет больше, чем у всех других успешно завершившихся.
Показать в проводнике файл — nsIFile.reveal()
неужели никогда файл в проводнике не открывал.
Отсутствует
Список можно получить так (если вместе с приватными)
await (await Downloads.getList(Downloads.ALL)).getAll();
Спасибо!
А как назначить код на событие ???.succeeded: «Загрузка завершена» ?
Отсутствует
Dobrov
Ну вот этот лист, он имеет метод addView()
Попробуй с консоли, и что-нибудь скачай.
Но вообще, вещь глобальная (не оконная).
(async () => { var list = await Downloads.getList(Downloads.ALL); list.addView({ onDownloadChanged(download) { if (!download.succeeded) return; console.log("download.succeeded", download); list.removeView(this); FileUtils.File(download.target.path).reveal(); } }); })();
Отсутствует
Dumby
со строкой list.removeView(this); работает однократно, без неё нормально.
Было нужно для фото с VK.com, открываемых отдельно, и автопереименования сохранённой картинки по имени из clipboard.
Возможно, для этого есть какой-либо userscript, но не нашёл…
Отсутствует