Vitaliy V.
Dumby
Что необходимо изменить или добавить в этом скрипте, что бы всплывающее окно автоматически закрывалось после перемещения курсора за пределы окна ?
Win7
Отсутствует
Там же двойной левый mousedown устанавливает или снимает загрузочную сессию.
Вот этого в предыдущем коде не понял. Желательно в подсказку добавлять справку по действиям, как в большинстве примеров:
Долгое нажатие Сохранить сессию, Колёсико или Клик + Ctrl Открыть сессию в новых вкладках, Правый клик Выделить и Открывать при запуске???
Ещё проблема - сохраняю пару сессий по две или три вкладки. При клике по имени сохранённой сессии (не boot) восстанавливается только последняя вкладка, первые пустые. (Firefox 97.0.1)
А что должно происходить, если имя сессии правым кликом выделено Красным? Оставляю одну пустую вкладку, при перезапуске браузера выделенная сессия не загружается…
Раскомментировал эту строку - тоже ничего не автозагружается: this.gs.SessionStoreInternal.getCurrentState = () => state;
Отсутствует
О, а скажите, можно ли посредством сабжа организовать такую штуку?
В доквантумном фоксе было расширение itsalltext. Становишься в textarea, жмёшь хоткей или кликаешь иконку (всплывала в уголке textarea) — и содержимое оной сохранялось в файле на диске и открывалось в текстовом редакторе, в каком настроено. А когда в редакторе сохранялся файл, содержимое textarea обновлялось. Можно было закрыть огнелиса, закрыть текстовый редактор, потом запустить их обратно и продолжить редактировать текст.
В квантуме же расширение больше не работает. Альтернативы требуют предварительно запустить текстовый редактор вручную, а в нём запустить плагин-сервер (есть для вима, для саблайма, ещё чего-то), и только тогда textarea обменивается текстом с редактором. Схема не намного удобней, чем просто запустить редактор и копипастить. Я б даже сказал, вообще шило на мыло.
А вот через UCF можно запускать сторонние приложения и значит — можно теоретически реализовать поведение старого аддона.
Отсутствует
Становишься в textarea, жмёшь хоткей или кликаешь иконку (всплывала в уголке textarea) — и содержимое оной сохранялось в файле на диске и открывалось в текстовом редакторе
В шапке темы скрипт hookClicks сохраняет выделенный текст или всю страницу в текстовый файл – правый клик по кнопке Загрузки. К имени файла добавляется заголовок вкладки и дата, но имя можно фиксированное прописать…
Отсутствует
Wave пишетСтановишься в textarea, жмёшь хоткей или кликаешь иконку (всплывала в уголке textarea) — и содержимое оной сохранялось в файле на диске и открывалось в текстовом редакторе
В шапке темы скрипт hookClicks сохраняет выделенный текст или всю страницу в текстовый файл – правый клик по кнопке Загрузки. К имени файла добавляется заголовок вкладки и дата, но имя можно фиксированное прописать…
Остаётся чтобы этот скрипт а) автоматически запускал текстовый редактор с этим файлом, б) по сохранению файла «снаружи» загружал его и обновлял содержимое страницы.
Отсутствует
Wave
С внешним редактором не знаю, а вот для ucf в есть такая кнопка. Что она делает - смотрите там мою просьбу выше.
Для Вашего пожелания можно было бы сделать следующее:
1. По ПКМ в textarea в меню появляется строчка, например, "Открыть Notepad". Текст выделяется, копируется в буфер, в открывается вкладка "Notepad" и текст вставляется.
2. При закрытии вкладки текст выделяется, копируется в буфер и во вкладке, из которой был открыт в textarea вставляется.
Дело за малым - устраивает это Вас? И если устраивает найти того, кто это напишет. Кнопку сделал Dumby.
UPD: можно и без строки меню, хоткеем. Невнимательно прочитал Ваш пост.
Добавлено 27-02-2022 14:54:56
UPD2: Можно поставить расширение "Управление историей форм". Будет сохраняться история редактирования.
Отредактировано xrun1 (27-02-2022 14:54:56)
Отсутствует
xrun1
Вы распакуйте 52 версию, какую нить портативку, да и установите расширение, что б понимать о чем речь. Расширение шикарное, тоже его очень не хватает. То что вы предлагаете не совсем то... я через буфер обмена быстрее и проще все сделаю.
Отсутствует
_zt
Если длинный пост всегда сначала пишу в редакторе, чтобы проверить орфографию. Поэтому расширением никогда не пользовался по причине ненужности лично для меня.
У меня портабельная есть 56-я, но ставить расширение лень. Предложил исходя из формулировки вопроса, что можно придумать на сей день. Нет так нет.
Отсутствует
UPD2: Можно поставить расширение "Управление историей форм". Будет сохраняться история редактирования.
У меня аналогичное расширение стоит, Textarea Cache. Оно, конечно, спасает от случайного перехода на другую страницу, закрытия вкладки и прочих неприятностей (на самом деле нет, потому что за всё время, что оно у меня стоит, так ни разу и не пригодилось).
Если длинный пост всегда сначала пишу в редакторе, чтобы проверить орфографию. Поэтому расширением никогда не пользовался по причине ненужности лично для меня.
Ну вот как поступаете вы. Придя куда-то, где нужно написать длинный пост, вы, вероятно, копируете в буфер обмена содержимое textarea (например, если там уже есть цитаты), запускаете редактор, вставляете из буфера обмена текст, пишете пост, копируете в буфер обмена текст, закрываете редактор, предварительно сказав «не сохранять» или введя имя файла и выбрав путь, и вставляете текст туда, куда писали.
.
Как поступал я, когда сидел на фф56-. Придя куда-то, где нужно писать длинный пост, нажимал хоткей, автоматом запускался редактор, где уже было то, что до этого было в textarea, писал пост, жал Ctrl-S, Alt-F4, переключался в браузер (если он не на переднем плане после закрытия редактора) и жал кнопку «отправить», т.к. в textarea текст уже тот, что я редактировал. Всё. Меньше действий — отсутствует ручной запуск редактора, два копирования-вставки в буфер, вопрос про то, что текст несохранён, с каким именем вы хотите его сохранить или вообще не хотите. Удобней (по крайней мере, мне).
.
Зы. Сами файлы расширение чистило по прошествии какого-то времени.
Отредактировано Wave (27-02-2022 19:50:19)
Отсутствует
Что необходимо изменить или добавить в этом скрипте, что бы всплывающее окно автоматически закрывалось после перемещения курсора за пределы окна ?
Да уж, мягко говоря, не слишком понятный вопрос.
Может попробуй добавить это, только удалить
затем не забудь, если Виталий что-то предложит.
(async bmrk => { await delayedStartupPromise; var popupshown = e => { var trg = e.target; if (trg.nodeName.startsWith("t")) return; var {curid, curbut} = autopopup; if (curid && trg.id == curid || curbut && ( curbut.className == "bookmark-item" && trg.matches(bmrk) || curbut.open && curbut.contains(trg.anchorNode || trg) && (curbut.type != "menu" || curbut.menupopup) )) trg.addEventListener("mouseleave", mouseleave), trg.addEventListener("popuphidden", popuphidden); } var popuphidden = function(e) { if (e.target == this) this.removeEventListener("mouseleave", mouseleave), this.removeEventListener("popuphidden", popuphidden); } var tid; var mouseleave = e => { tid && clearTimeout(tid); tid = setTimeout(check, 350, e.target); } var check = popup => { tid = null; popup.closest(":is(menupopup,panel):hover") || autopopup.curbut?.matches(":hover") || (popup.nodeName.startsWith("m") ? closeMenus(popup) : popup.hidePopup()); } var autopopup = ucf_custom_script_win.mouseoveropentoolbarbutton; var {destructor} = autopopup; autopopup.destructor = () => { destructor.call(autopopup); removeEventListener("popupshown", popupshown); } addEventListener("popupshown", popupshown); })("toolbarbutton.bookmark-item :scope");
Вот этого в предыдущем коде не понял.
История у него есть, не вдруг появился, а из даденого,
и обсуждалось, и хотелки добавлялись.
А если выдернуть из контекста, и смотреть по коду,
то конечно трудно понять, он же довольно большой.
Желательно в подсказку добавлять
Вот и займись этим. Если туда еще добавить про двиганье мышью,
и все клавиатурные аналоги мышиных действий, будет капитально.
при перезапуске браузера выделенная сессия не загружается
И не должна, перезапуск есть перезапуск, это действие определённого характера.
А вот если закрыть Firefox, то затем, при запуске, должна загружаться.
восстанавливается только последняя вкладка, первые пустые
Прямо в реальном времени это не работает.
Нужно подождать, а не сохранять сразу после открытия вкладок.
Если очень надо, то можно попробовать так:
задать небольшое значение настройки browser.sessionstore.interval
подождать секунду, вернуть настройку, и тогда сохранять.
Вроде работает, на первый взгляд.
(async (pid, mp, self) => CustomizableUI.createWidget((self = { id: "797321", label: "Simple Session Manager", tooltiptext: "Управление сессиями", localized: false, init() { this.handleEvent = e => this[e.type](e); this.onTimeout = async () => await this.saveSession() || this.save(); Services.obs.addObserver(this, "quit-application"); var {openMenu} = this; this.render = function() { this.openMenu = openMenu; this.constructor.prototype.render.call(this); } delete this.init; return this; }, image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEnQAABJ0BfDRroQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGxSURBVDiNnZE/T1NRGMZ/7zn3lmKLkIKpaUxZFINEJZ0YHXRwcnBxMQ6aOJi4+FH8Dm5OOjA4+AEYGCTRook1JlVIVUrbW/rnPg63UtReIr7bOXmf5/ye59jDlanHS3O+wn/Mu+/DF8HFeVe5f+vaPTdfPpF4UNvk6frmhwAvXOEsvrR0IoN47xM4CHCADmDQBkAHbdTrTBRZdgYLs6NTD/MiMC+gC8MO6ke8ffWsXv3S3JpksHouv7Z4/UEeM8z6IwKfEGjYRt0G1d3m1p3n0Y1JBi/vTtfKw1Yec2CHBDFmXYjboAgL4tTc5pXsmcNcDxIDUFQHuqgfYT69OAuE9qqAoX4jIcAL7b9H+0deOYYg3tkYXxx2EAo7dQYEBF/TEULD5oow7KHut18RhGVD3GwxMZ36YWn6IJd37vQCSMSNBpYQCMs43PQMAJXlwtr6k7CGfo9iznN1ebGY7Ak1NSJwYERYJgM+Q+nClVzp/OXc3wWMwdT+jAVKCMwLC2PUeoMrrEI4m94BQq0a6mxjoca/YKFgUCfeqR8jPhoHcIAHe3ST2+UFLv2T8o/5uMvrnx9Wn65p5nMEAAAAAElFTkSuQmCC", onCreated(btn) { btn.type = "menu"; btn.phTimestamp = 0; btn.render = this.render; btn.onclick = this.click; // btn.setAttribute("image", "chrome://user_chrome_files/content/custom_styles/svg/download-resume.svg"); btn.setAttribute("image", this.image); var popup = btn.ownerDocument.createXULElement("menupopup"); popup.filler = this; popup.id = pid; popup.setAttribute("onpopupshowing", "event.defaultPrevented || filler.fill(event)"); btn.prepend(popup); btn.addEventListener("mousedown", this); popup.addEventListener("command", this); btn.ownerGlobal.addEventListener("unload", () => { btn.removeEventListener("mousedown", this); popup.removeEventListener("command", this); if (popup.filler != this) popup.removeEventListener("dragstart", this), popup.removeEventListener("popuphidden", this); }, {once: true}); }, openMenu(arg) { var pos; if (this.matches(".widget-overflow-list > :scope")) pos = "after_start"; else var win = this.ownerGlobal, {width, height, top, bottom, left, right} = this.closest("toolbar").getBoundingClientRect(), pos = width > height ? `${win.innerHeight - bottom > top ? "after" : "before"}_start` : `${win.innerWidth - right > left ? "end" : "start"}_before`; this.firstChild.setAttribute("position", pos); delete this.openMenu; this.openMenu(arg); }, mousedown(e) { if (e.button) return; var trg = e.target; if (trg.nodeName.startsWith("t")) trg.mdTimestamp = Cu.now(), trg.tid = e.view.setTimeout(this.onTimeout, 500), e.preventDefault(); }, boot(trg) { var popup = trg.parentNode; var old = popup.querySelector("[boot]"); if (old != trg) old?.removeAttribute("boot"); trg.toggleAttribute("boot"); popup.bootChanged = true; }, muTimestamp: 0, click(e) { var trg = e.target; if (trg.nodeName == "menu") { if (e.button > 1) self.boot(trg); else if (Cu.now() - self.muTimestamp > 50) e.view.closeMenus(trg.menupopup), self.restoreSession(trg.label, (e.button || e.ctrlKey) && e.view); } else if (trg != this || e.button) return; e.view.clearTimeout(this.tid); if (this.mdTimestamp - this.phTimestamp > 50) this.open = true; }, async command(e) { var arg, trg = e.target, cmd = trg.value; if (cmd.startsWith("r")) arg = trg.parentNode.parentNode.label; await this[cmd](arg) || this.save(); }, dragstart(e) { var trg = e.target; if (trg.nodeName != "menu") return; var popup = trg.parentNode; this.dragData = {trg, mouse: true}; trg.menupopup.hidePopup(); var win = trg.ownerGlobal; win.setCursor("grabbing"); var {width} = trg.getBoundingClientRect(); trg.setAttribute("maxwidth", width); win.addEventListener("mouseup", this); popup.addEventListener("mousemove", this); }, mousemove(e) { var trg = e.target, dtrg = this.dragData.trg; if (trg == dtrg || trg.nodeName != "menu") return; e.movementY > 0 ? trg.nextSibling != dtrg && trg.after(dtrg) : trg.previousSibling != dtrg && trg.before(dtrg); }, mouseup(arg) { if (arg.constructor.isInstance?.(arg)) { arg.preventDefault(); var {trg} = this.dragData; this.dragData.mouse = false; this.muTimestamp = Cu.now(); } else var trg = arg; trg.removeAttribute("maxwidth"); trg.ownerGlobal.setCursor("auto"); trg.ownerGlobal.removeEventListener("mouseup", this); trg.parentNode.removeEventListener("mousemove", this); }, popuphidden(e) { if (!e.target.id) return; e.view.removeEventListener("keydown", this, true); var popup = e.target; popup.parentNode.phTimestamp = Cu.now(); var save; if (this.dragData) { var {trg, mouse} = this.dragData; mouse && this.mouseup(trg); delete this.dragData; var order = Array.from(popup.getElementsByTagName("menu"), m => m.label); if (order.toString() != this.meta.order.toString()) { var hasBoot = this.meta.boot != null; if (hasBoot) var bootName = this.meta.order[this.meta.boot]; this.meta.order = order; if (hasBoot) this.meta.boot = this.meta.order.indexOf(bootName); save = true; } } if (popup.bootChanged) { delete popup.bootChanged; var {boot} = this.meta; var bootNode = e.target.querySelector("[boot]"); var ind = bootNode && this.meta.order.indexOf(bootNode.label); if (ind != boot) this.meta.boot = ind, save = true; } save && this.save(e.view); }, sku: `#${pid} > menu[maxwidth]`, skd: `#${pid} > menu:is([maxwidth],[_moz-menuactive]):not([open])`, keydown(e) { if (e.repeat && e.key == "Shift" || !e.shiftKey && e.key != " ") return; var func = this.keyHandlers[e.key]; if (!func) return; var menu = e.view.windowRoot .ownerGlobal.document.querySelector(this.skd); if (menu) e.stopImmediatePropagation(), func.call(this, menu, e); }, keyup(e) { if (e.key != "Shift") return; var win = e.view.windowRoot.ownerGlobal; win.removeEventListener("keyup", this, true); win.document.querySelector(this.skd)?.removeAttribute("maxwidth"); }, keyHandlers: { Enter(menu) { this.boot(menu); }, ArrowDown(menu) { var ns = menu.nextSibling; if (ns) ns.after(menu), this.arrow(menu); }, ArrowUp(menu) { var ps = menu.previousSibling; if (ps.nodeName == "menu") ps.before(menu), this.arrow(menu); }, " "(menu, e) { e.preventDefault(); menu.ownerGlobal.closeMenus(menu.parentNode); this.restoreSession(menu.label, e.ctrlKey && menu.ownerGlobal); } }, arrow(menu) { if (menu.hasAttribute("maxwidth")) return; menu.setAttribute("maxwidth", menu.getBoundingClientRect().width); menu.ownerGlobal.addEventListener("keyup", this, true); this.dragData = {trg: menu}; }, fill(e) { var mxe = e.view.MozXULElement; var initFrag = mxe.parseXULToFragment(` <menuitem value="saveSession" class="menuitem-iconic" label="Сохранить сессию"/> <menuitem value="deleteAllSessions" class="menuitem-iconic" label="Удалить все сессии"/> <menuseparator/> `); this.menuFrag = mxe.parseXULToFragment(`<menu class="menu-iconic"><menupopup> <menuitem label="Переименовать" class="menuitem-iconic" value="renameSession"/> <menuitem label="Удалить" class="menuitem-iconic" value="removeSession"/> </menupopup></menu>`); this.regStyle(); var filler = {fill: e => e.target.id ? e.view.addEventListener("keydown", this, true) || e.target.fillFlag || this.fillSessions(e.target) : this.dragData?.mouse && e.preventDefault() }; (this.fill = e => { var trg = e.target; trg.setAttribute("context", ""); trg.append(trg.ownerDocument.importNode(initFrag, true)); (trg.filler = filler).fill(e); trg.addEventListener("dragstart", this); trg.addEventListener("popuphidden", this); })(e); }, fillSessions(popup) { while(popup.lastChild.nodeName == "menu") popup.lastChild.remove(); var ind = 0, {boot} = this.meta; for(var name of this.meta.order) { var df = popup.ownerDocument.importNode(this.menuFrag, true); df.firstChild.setAttribute("label", name); if (ind++ == boot) df.firstChild.toggleAttribute("boot"); popup.append(df); } popup.fillFlag = true; }, regStyle() { delete this.regStyle; var subst = "ucf-ssm-style-resurl"; Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler).setSubstitution( subst, Services.io.newURI("data:text/css;charset=utf-8," + encodeURIComponent(` @-moz-document url-prefix(chrome://browser/content/browser.xhtml) { #${pid} > menu { list-style-image: url("${this.image}"); } #${pid} > [value=saveSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKVSURBVHjajFNNTBNREJ6+7na73bLbQn8I0BKNCYWKGr0oYoiJPxeNh6oHozcOxgSVi4le1JNHQRPigRsewURNPKiJMQicSISUACelRVJ2tz/bdktpy9adBzT8xTjJ5L35ezNv5hsLHEAv7noEntguChx7EuV8oTydKRhfno8kCnt9LTuFZ7f87mAz/8rnl86GOoOBBq+LQX1S1ioLs0txWdEmsulS38Phlcy+BwZ6W0L+JsfolcjpsFDnBKNcgQ193bRUwSrwQFgr6Dkd3o9NzilqMdI/FF+sPYCZ245I4zdunw9DtQr6LxlK6bVdpdrcPAiHfGBYLDD69ltUXsmfw0oIGoPNjkHMjMHa3J9asDyRpoyEOrQR0+dq5MxR0c29Rj3Bhvn8YjeWjZmN9cpWcApSkzpkptYg8T1FdWjTfysg1Ang9YtdT+80OogTbJc7OlsD+OftzOqsBrMflqHe6QKXIEL00zLV0UpSBbM/G9DeEQy6OXKJsfPsCbdXYjb0Yu2/nmMS9LSGYGlYpXLPkxCwkq1mR98Gn8Q4XexxYhhgYKf3TPTfRDaPqklkvViaSSpaxSpw/x1v5e0UG8W10k+iW8qfF2ZiccIydFQ7ScsXKO8ep4NiYj4ai6k5+Eoev1F1Wcn8QJDgnAnHbGYRWTh800cZ77Ryzmr6eCGXzYGiZCcQ2vQ32XT5PiIMTJBI4Waw1ZtZzLu7XaSMd1s9b9paKJA+vpuKqols3y4ov7wXaPN67GPXIl1hnDOOansyVicHhGHMzHkzeDKqqPnr/UOJxX3LNNDb5BJd3KC3Uexu7wgEGxq3limRqcxH47FVWRtPreYePBpJagdu4zYhwjx1cMFus59CuVgqTmPDDlrnvwIMAGS8IFCLagHpAAAAAElFTkSuQmCC"); } #${pid} [value=restoreSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAACzElEQVQ4jX2QPWwbZRjHf+/5vfPdObZjO3Ga2pVpGtxCP4QIDKgqDCDUNQwgJCS2qFI3hBCRCvXSCcTAAu0GY0Fi4kuq+IjUCpWAgCTq4IpS3Di2G8c+x/bZ57t7mSJFMfBf/3p+z+95BPvy3pufxqKmcVY3ZFFKmQtFGIReuNnrDze6lv5TqfSyx4EIgA/e+fzkZML6MDmVnD80mz1kxW3DMAxQCs/z6Hb6g3q1Xt1ttdfa7dbFN668vrkHkADJhPntufNnc0LTDi7AjFkkUknzcGF2LvCDuZVvfiwCj+/1GoAmhL3x6x2cZhsVqjFIGIZs15ts/LJOJCLt/Z0EiE3Y9eLpR1ONaoMH9zbHAGiC9FSKkwunWF1Z3RoDABhRg/zRPPmj+XHA/0QDaLectFLj6gcT+AHdTm9mzMC27e766lrWtCwy2Qz2hIUeNVDAaDCku9ujWW/ij3wsO9oaMzCiunf66TMU5gt4wyGbf1Upr5W5u15mq1JDhYqZQo6HIuqtueLw4vLXzwC89NZXeQFw/ePv7zx5buHEf6nf3qgMVipOGE0ko6EKhoQi3NnZ+c51BwsaQLOxM9N1uv86vNtz+aHSDn0pH9S2tl6r/Pn3s/VG/WYunzs/NZ2OSID0dKpRrzZS98v3kYbEsi1004BQcbtc9Q07bdYb229/dvmFL5aWVvVts9mq1Wo/e54vJIAQqGOPzQHgj3zcvos39BAIBshRqJQYjYZ/AFy79tQIeHVx+ctiIDRTA+g43Xud9q4PIHVJPBknk82QzqY5VZg2UUrEYhOX9s5aXL5RnMykb8Rj9kcC4OrSVZ1Hpt+PJ5PPz+SzR5KpyYRpGgRKMei7fHLr7lBmZ1XHcX4LgsCxLPt4JBLRm82Hr4j9DyuVSprdO/ZELGafkXpkXtPA94OK03Vv/R4/csEw5XOGbuieN6y6bv/S9XdfvPkPTgcoDlpQJpwAAAAASUVORK5CYII="); } #${pid} [value=renameSession] { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPFJREFUeNrEU0sOgkAMbc1IIHoQT+KeY7hkBW5ccwLdsOICxI2X8peIGhggI21gggpCwsImM01f+tpOO0WlFIwR0efgeR5nsG0boihizPd91A5UwZDjuq5qwycwUkQYhttSr4Y4l76fDdtBEAQqz3OVZdnPQ09o2sQhrpBSQgnAen/qzLxZzljHcawxy7KAuCJNUyiKAm53SS0FBGQNlUW3lFO2iVCLYRhAXJEkCQPn65NGAswpL/4fWAebt1ZGXB3geHlw9maXsKqjS94CHNxF7xRM0/wKgI7jDBojvbnZAz3Gv/9E7NvGvmXCsev8EmAAWocA9ofpaRIAAAAASUVORK5CYII="); } #${pid} :is([value=removeSession], [value=deleteAllSessions]) { list-style-image: url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAABt0lEQVQ4ja2RT2sTURTFz8tk0nntFAQrVLBQxIUg/tkkMoLyIEVECHZhNrrxI+hOP5Mb6eBCcEipYIjZ2LpvhFasUtBSkwzOve+6mE6YSScuxLt67753fudyLvA/a7T+qCHmiTfrfWCMd3j9diPfq2SHX+uPnzJx71gP33w3bX9avBcE2j+SkK30Di7ffJ71VebMxD1hC2GGEEfH41prpftynIm92A0t2aYQQYgBThrndz/2KwCgf9Z2LNtImFOAtc356ijcCwJdJrZEUWzPfJpMAAAStPWR/h2Ktc10CoIQRUKEabFNvNbKfndcAKSjtrVfHW5YorWTzxDKYAxLtOWM+P7yt51hIYPpsDTNTyB/EwNAtWxdMuV8GCfbgxjxIviUYSV/SQOrbVjitbx4N8alBeXcdZR+3Tl3xS8FlIkt0dbnWH3xlbPgKgUo3HEq+tX7C4EuAAbGeOmqCuLIJt69s3PeQ1epKGfapCQJO6vGmwAWf/C1Wau6td8dV123BaAAUfHw6gSwtP3ugxA/y6X9INszAOQgbwFAIC/MQb9/Kv2vF2/UByejlVVn1Xiby/X6rPd/qj/1ak71UYKuwQAAAABJRU5ErkJggg=="); } #${pid} > menuseparator:last-child, #${pid} > menu[maxwidth] > .menu-right, #${pid} > [value=deleteAllSessions]:nth-last-child(2) { display: none; } #${pid} > menu[boot] { color: red; font-weight: bold; } #${pid} > menu[maxwidth] { color: blue; font-weight: bold; outline-offset: -2px; outline: 2px solid orangered; } } `.replace(/;$/gm, " !important;")))); var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(Services.io.newURI("resource://" + subst), sss.USER_SHEET); }, get gs() { delete this.gs; return this.gs = Cu.import("resource:///modules/sessionstore/SessionStore.jsm", {}); }, splice(name, newName) { var ind = this.meta.order.indexOf(name); if (ind == -1) return; var args = [ind, 1]; if (1 in arguments) args.push(newName); else { if (ind == this.meta.boot) this.meta.boot = null; else if (ind < this.meta.boot) this.meta.boot--; } this.meta.order.splice(...args); }, get meta() { var file = Services.dirsvc.get("UChrm", Ci.nsIFile); file.append("simple_session_manager.json"); this.path = file.path; try { this.data = JSON.parse(Cu.readUTF8File(file)); } catch { this.pp = file.parent.path; this.data = Object.create(null); } var meta = this.data[mp]; if (!meta) { var order = Object.keys(this.data); meta = this.data[mp] = {order, boot: null}; } delete this.meta; return this.meta = meta; }, async save(excWin) { var io = Cu.getGlobalForObject(Cu).IOUtils; if (this.pp) await io.makeDirectory(this.pp), delete this.pp; (this.save = excWin => { this.meta.order.length ? io.writeJSON(this.path, this.data) : io.remove(this.path, {ignoreAbsent: true}); for(var win of CustomizableUI.windows) { if (win == excWin) continue; var popup = win.document.getElementById(pid); if (popup) popup.fillFlag = false; } })(excWin); }, get prompter() { var {prompt} = Services; var p = {}, args = [null, null, "UCF Simple Session Manager"]; p.alert = prompt.alert.bind(...args); p.confirm = prompt.confirm.bind(...args); var pr = prompt.prompt.bind(...args); p.prompt = (msg, value) => { var res = {value}; return pr(msg, res, null, {}) ? res.value : null; } delete this.prompter; return this.prompter = p; }, observe(s, t, data) { Services.obs.removeObserver(this, "quit-application"); if (data.includes("restart")) return; var {boot} = this.meta; if (boot == null) return; var state = this.data[this.meta.order[boot]]; var ssi = this.gs.SessionStoreInternal; ssi.getCurrentState = () => state; Services.obs.removeObserver(ssi, "browser:purge-session-history"); Services.prefs.setBoolPref("browser.sessionstore.resume_session_once", true); }, get bwt() { delete this.bwt; var url = "resource:///modules/BrowserWindowTracker.jsm"; return this.bwt = ChromeUtils.import(url).BrowserWindowTracker; }, getName(state) { var wl = state.windows.length, tl = 0; for(var w of state.windows) tl += w.tabs.length; return `${ this.bwt.getTopWindow().gBrowser.selectedTab.label.slice(0, 70) } ${wl}/${tl} [${ new Date().toLocaleString("mn").replace(" ", "-") }]`; }, exists(name) { this.meta; return (this.exists = name => name in this.data && !this.prompter.alert("Сессия с тем же именем уже существует!"))(name); }, getState() { return JSON.parse(this.gs.SessionStore.getBrowserState()); }, get spref() { var pref = "browser.sessionstore.interval"; var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); var wait = cb => timer.initWithCallback(cb, 1e3, timer.TYPE_ONE_SHOT); delete this.spref; return this.spref = async cb => { var val = Services.prefs.getIntPref(pref); Services.prefs.setIntPref(pref, 100); await new Promise(wait); Services.prefs.setIntPref(pref, val); } }, async saveSession(name = this.getName(this.getState())) { var name = this.prompter.prompt("Сохранить:", name); if (name == null) return true; if (this.exists(name)) return this.saveSession(name); await this.spref(); this.data[name] = this.getState(); this.meta.order.push(name); //this.meta.order.unshift(name); //if (this.meta.boot != null) this.meta.boot++; }, restoreSession(name, win) { var ss = this.gs.SessionStore; var state = JSON.stringify(this.data[name]); win ? ss.setWindowState(win, state) : ss.setBrowserState(state); }, renameSession(name, newName = name) { var newName = this.prompter.prompt(`Переименовать "${name}" в:`, newName); if (newName == null || newName == name) return true; if (this.exists(newName)) return this.renameSession(name, newName); var {data} = this; this.splice(name, newName); data[newName] = data[name]; delete data[name]; }, removeSession(name) { if (!this.prompter.confirm(`Вы уверены, что хотите удалить ${name} ?`)) return true; delete this.data[name]; this.splice(name); }, deleteAllSessions() { if (!this.prompter.confirm(`Вы уверены, что хотите удалить все сессии?`)) return true; delete this.dragData; delete this.bwt.getTopWindow().document.getElementById(pid).bootChanged; this.meta = (this.data = Object.create(null))[mp] = {order: [], boot: null}; } }).init()))("ucf-ssm-menupopup", "{07cae4f5-18b0-487b-80eb-973304af9528}");
Отсутствует
Вот и займись этим. Если туда еще добавить про двиганье мышью,
и все клавиатурные аналоги мышиных действий, будет капитально.
Доработал код Менеджера сессий, добавил описание: (про двиганье мышью записал только сортирровку перетаскиванием)
Сделал обновление времени browser.sessionstore.interval в подсказке и нашёл такие возможности, может что-то пропустил:
tooltiptext: `Менеджер сессий: Браузер каждые 0.25 мин сохраняет сессии, это снижает ресурс SSD\n Правый клик на Имени сессии: Выделить и Открывать при запуске Колёсико или Клик + Ctrl: Открыть сессию в новых вкладках Сортировка: тащите строки мышью или курсором, удерживая Shift`, ……… btn.addEventListener("mouseenter", this); ……… btn.removeEventListener("mouseenter", this); ……… mouseenter(e) { // обновить время сохранения сессии браузера e.view.document.getElementById(self.id).tooltipText = self.tooltiptext.replace(new RegExp(/ые .* ми/,''),'ые '+ Services.prefs.getIntPref('browser.sessionstore.interval',15e3)/60e3 + ' ми'); },
Отсутствует
Всем привет! Значительно переработал расширенный профиль Firefox (в шапке темы), добавил скриптов и сократил объём архива до 3,3 Мб:
Визуальное представление: 4 режима Прокси разным фоном ≡ Меню, запрет графики фоном кнопки ⤓ «Загрузки», различные сообщения статуса при наведении на кнопки, например показ пути к папке Загрузок, масштаб шрифта, переключение прокси, предупреждение о включенном HTTPS и прочее…
На любых кнопках разрешены все клики мыши ⦺, градиентный Прогресс загрузки страниц, Четыре режима чтения, Меню переключения скрытых настроек (долгое нажатие 0.5 сек на пункте меню откроет эту опцию в about:config), Управления дополнениями, расширенный Инспектор атрибутов, Добавление закладки без запроса, Перевод сайта/текста, Проиграть/скачать видео или ссылку программой из контекстного меню, Поиск похожих фото, Сохранение картинок, которые нельзя сохранить обычным способом, Жесты мыши например перетаскивание ссылки вправо копирует её в буфер, Расположение страниц в Закладках показывается в подсказке Звёздочки, Авто-коррекция имён вкладок, Яркость колёсиком ± на Замке, показ Ссылок и прочее… — читайте подсказки кнопкок при наведении мыши и встроенную Справку (долгий клик по кнопке «Печать»).
2) ≡ стандартная кнопка Меню — вне курсора составной значок
◧ Левый+Alt или Колёсико: Развернуть | Восстановить окно
⩉ Ролик вверх: Полный экран, ◧ Держать кнопку: Закрыть Firefox
◨ правый Свернуть, + Shift Вернуть вкладку, ◨ + Alt Диспетчер задач
В меню ≡ Диалог сохранения "Страница / Выбранное в единый HTML"
3) Избранное + боковая панель с кнопками, Колёсико ± Масштаб
Клик мыши: открыть слева Журнал, ◧ + Shift - zoom Текст/страница
◧ левый клик мыши +Alt: Заладки, ◧ держать: Вкл/Выкл Антизапрет
⦿ Колёсико – «Топ сайтов», ◨ правый клик Меню настроек
4) Менеджер сессий — сохранить вкладки и положение страниц в базу
◨ клик на имени: Выделить и Открывать эту сессию при запуске
⦿ колёсико или Клик + Ctrl: Открыть сессию в новых вкладках
удалите папку startupCache перед запуском, рекомендуется Firefox 90+
Установите Demo-профиль согласно структуре папок. Запуск firefox -P user
Отредактировано Dobrov (12-03-2022 08:15:36)
Отсутствует
скрытый текст
А можно ещё сделать что бы работал на кнопках CB
Add, и ещё кнопку для перезапуска с удалением папки startupCache
Отредактировано kokoss (18-03-2022 23:35:15)
Win7
Отсутствует
А можно ещё сделать что бы работал на кнопках CB
Не требуется, «скрытый текст» и так работает на кнопках CB.
ещё кнопку для перезапуска с удалением папки startupCache
Ууу, сам бы от такой не отказался.
Папка в лисьем использовании, и её удаление, на первый взгляд, не представляется возможным.
Отсутствует
Не требуется, ... и так работает на кнопках CB.
Проверял в предыдущей версии UCF. В актуальной версии UCF у меня тоже не работает, походу не туда запихнул, пока не до конца разобрался куда добавлять...
Папка в лисьем использовании, и её удаление, на первый взгляд, не представляется возможным.
Надеюсь такая возможность со временем появится!
Win7
Отсутствует
и ещё кнопку для перезапуска с удалением папки startupCache
Есть перезапуск для меню или горячая клавиша Ctrl+Alt+Q. В меню гамбургера не показывает иконку. https://forum.mozilla-russia.org/viewto … 07#p785107
Отсутствует
В меню гамбургера не показывает иконку. https://forum.mozilla-russia.org/viewto … 07#p785107
Это не то, таких кнопок у меня несколько
Add, просто что бы заработали некоторые скрипты, приходится удалять эту папку
Отредактировано kokoss (19-03-2022 18:08:40)
Win7
Отсутствует
Папка в лисьем использовании, и её удаление, на первый взгляд, не представляется возможным.
Я сейчас проверил. Удаляется. Там ещё файл появляется .startup-incomplete, но он или само-удаляется при удалении папки, либо просто исчезает через некоторое время после запуска .
Отсутствует
Есть перезапуск для меню или горячая клавиша Ctrl+Alt+Q. В меню гамбургера не показывает иконку.
С иконкой
//Кнопка перезагрузки (this.menusrestartitems = { init(that) { var btnClass = "ucf-appmenu-restart-button", muimID = "ucf_menu_FileRestartItem", ucf_script = (window.ucf_custom_script_win == that) ? "ucf_custom_script_win" : "ucf_custom_script_all_win"; 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 = btnClass; btn.className = "subviewbutton subviewbutton-iconic"; btn.setAttribute("label", "Перезапуск"); btn.setAttribute("tooltiptext", "ЛКМ: Перезапустить приложение\nСКМ: Перезапустить без дополнений\nПКМ: Перезапустить и заново создать кэш быстрого запуска"); 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", "Перезапуск"); muim.setAttribute("tooltiptext", "ЛКМ: Перезапустить приложение\nСКМ: Перезапустить без дополнений\nПКМ: Перезапустить и заново создать кэш быстрого запуска"); 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("chrome://global/skin/icons/reload.svg") !important; } #${btnClass}.subviewbutton-iconic .toolbarbutton-icon, #${muimID} .menu-iconic-icon { -moz-context-properties: fill !important; fill: #e31b5d !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); } }).init(this);
Отсутствует
проверил
Увы, это не то, что можно «проверить».
Services.appinfo.invalidateCachesOnRestart(), разумеется, в основном, работает.
Иначе был бы соответствующий баг, STR, и всё такое.
Дело в том, что работает это не всегда.
Иногда, в некоторых случаях, совершенно рандомно,
без какой-либо закономерности, механизм даёт сбой, и кэш не очищается.
Очень неприятный глюк, особенно при возне с кодом,
когда перезапуски идут многими десятками.
Отсутствует
egorsemenov06
Спасибо. А то был непорядок.
Dumby
Можно удалить ведь и системной командой cmd /c rd /s /q "путь к папке\startupCache" > nul 2>&1 перед перезапуском. Не элегантное решение (окно cmd мелькает), зато результативное.
Но Вам виднее.
Отсутствует
Dumby
В full_theme есть скрипт setattributechromemargin.js, он отвечает за смещение области chrome относительно рамки окна ОС, в том числе с учетом Aero в Win 7.
На 100 скрипт перестал работать правильно, как минимум для Win 7.
Нижние углы окна 100 :
левая и верхняя кромки в порядке.
Вы можете поправить это? Изменение значений результата не дает.
full_theme_220116.zip user_chrome_files_211113.zip
Отредактировано _zt (09-05-2022 13:41:34)
Отсутствует
На 100 скрипт перестал работать правильно
Надеюсь это только
Bug 1754547 - Provide a @media query to target major platform/toolkits (Firefox 99+)
То есть, поменяли -moz-os-version на -moz-platform
Вы можете поправить это?
Тут бы хорошо что-то более персонализированное говорить.
Если не собираешься использовать скрипт на других осях
(где он проведёт проверку, увидит, что это не Win7(8), и ничего не сделает),
то и проверка не нужна, просто удали её (третья строка в setattributechromemargin.js).
Иначе, если обратная совместимость не нужна,
то просто замени -moz-os-version на -moz-platform (в двух местах).
Иначе пишем какую-нибудь дополнительную проверку.
Вот, например, более отвязный вариант скрипта, не как рекомендация,
а просто посмотреть вариант проверки (вторая, третья и четвёртая строки).
(async tit => { if (AppConstants.platform != "win") return; var key = parseInt(Services.appinfo.platformVersion) >= 99 ? "platform" : "os-version"; if (!matchMedia(`(-moz-${key}: windows-win7), (-moz-${key}: windows-win8)`).matches) return; Object.assign(tit, eval(`({${tit._update}})`.replace('"0,2,2,2"', "this.margin"))); var glass = matchMedia("(-moz-windows-glass)"); (glass.onchange = () => { tit.margin = glass.matches ? "0,7,7,7" : "0,0,0,0"; tit.enabled && document.documentElement.setAttribute("chromemargin", tit.margin); })(); })(window.TabsInTitlebar);
Отсутствует