в function saveFavicon() вместо строчки - saveImageURL(gBrowser.selectedTab.image, getSiteName(), null, false, false, null, window.document);
А можешь целиком исправленный этот блок выложить
// Сохранить иконку текущего сайта с диалогом сохранения ............. ?
а то я видать что-то не то меняю, она у меня не заводится.
Отредактировано voqabuhe (15-03-2020 22:39:36)
Отсутствует
А можешь целиком исправленный этот блок выложить
// Сохранить иконку текущего сайта с диалогом сохранения ............. function saveFavicon() { var uri = gBrowser.currentURI; function getSiteName() { try { var domain = uri.host.split('.') } catch(e) { return "" }; domain = (domain.length == 2) ? domain[0] : domain[1] return domain.charAt(0).toUpperCase() + domain.slice(1).split('.')[0] + " "; }; var url = gBrowser.selectedTab.image; url && saveImageURL( url, getSiteName(), null, false, false, null, null, /^data:(image\/[^;,]+)/i.test(url) ? RegExp.$1.toLowerCase() : Cc["@mozilla.org/mime;1"] .getService(Ci.nsIMIMEService).getTypeFromURI(Services.io.newURI(url)), null, PrivateBrowsingUtils.isContentWindowPrivate(content || window), document.nodePrincipal ); };
Отсутствует
Какую версию (и, главное, откуда) ставить на текущий Waterfox-Classic (+e10s, +Classic Theme Restorer), то бишь, как я понимаю, 56.3?
Ставил из CAA 0.5.8.9/2016 г, после рестарта внизу окна давно забытая панель неправильного XUL, аж на ностальгию пробило. На МозДеве вообще 0.0.5.5/2011.
Отредактировано VitaR (16-03-2020 17:29:32)
Отсутствует
Какую версию (и, главное, откуда) ставить на текущий Waterfox-Classic (+e10s, +Classic Theme Restorer), то бишь, как я понимаю, 56.3?
Ох, разве вспомнишь. Есть свидетельство от kokoss.
Точно вычислить самую оптимальную не возьмусь.
Скажем так: последняя оверлейная версия, похоже, здесь.
Но глюки с открытем из консоли строки с ошибкой на две дальше, чем на самом деле,
и с удалением горячей клавиши кнопки из cbIKeyMapService при закрытии окна браузера,
там присутствуют.
А так-то, поставил на Waterfox Classic 2020.03.1 и, на первый взгляд, в основном, всё работает.
Если в папке профиля осталась папка custombuttons c <parsererror>'ами от «неправильного XUL»,
то, после установки, следует закрыть Waterfox и удалить эту папку.
Отсутствует
Dumby а этот код можно подправить
//Показать адрес существующей закладки при наведении на звездочку BookmarkingUI.star.onmouseenter =e=> { var {bookmarks, placesRootId, tagsFolderId} = PlacesUtils, result = []; for( var id of BookmarkingUI._itemIds ) { var arr = []; while((id = bookmarks.getFolderIdForItem(id)) != placesRootId) { if (id == tagsFolderId) { arr = []; break; } arr.unshift(bookmarks.getItemTitle(id) || "(без заголовка)"); } arr.length && result.push(arr.join("\\")); } if (result.join()) e.target.tooltipText = "Адрес закладки:\n" + result.join("\n"); };
Отсутствует
а этот код можно подправить
Не знаю, можно, наверно
((bu, bm, {star} = bu) => addEventListener("mouseenter", { async handleEvent() { if (!this.starred) return; star.tooltipText = "\u3164"; var result = []; await this.fetch(); for(var guid of this.guids) { var arr = []; while(true) { if (!this.hover) return; var res = await bm.fetch(guid); if ((guid = res.parentGuid) == bm.rootGuid) { arr.unshift(bm.getLocalizedTitle(res)); break; } arr.unshift(res.title || "[Безымянная папка]"); } result.push(arr.join("\\")); } this.hover && this.setTooltip(result); }, get fetch() { addDestructor(() => this.starred && document.l10n.translateElements([star])); var set = this.guids = new Set(); var args = [b => set.add(b.parentGuid), {concurrent: true}]; delete this.fetch; return this.fetch = () => set.clear() || bm.fetch({url: gBrowser.currentURI.spec}, ...args); }, setTooltip(arr) { var m = arr.length > 1; var text = `Адрес${m ? "а" : ""} заклад${m ? "ок" : "ки"}:\n${arr.join("\n")}`; document.tooltipNode == star ? this.tt.label = text : star.tooltipText = text; }, get tt() { var list = InspectorUtils.getChildrenForNode(document.documentElement, true); delete this.tt; return this.tt = list.item(list.length - 1); }, get starred() {return bu._itemGuids.size;}, get hover() {return star.matches(":hover");} }, false, star || 1))(BookmarkingUI, PlacesUtils.bookmarks);
Отсутствует
Не знаю, можно, наверно
А можешь ещё добавить, если вкладка не в закладках, чтобы при наведение на звёздочку показывало последнюю папку куда добавлялась закладка?
Отредактировано voqabuhe (17-03-2020 17:48:15)
Отсутствует
Dumby спасибо
Отсутствует
А можешь ещё добавить, если вкладка не в закладках, чтобы при наведение на звёздочку показывало последнюю папку куда добавлялась закладка?
Не, я не знаю откуда взять об этом информацию.
Можно попробовать подрядить обсёрвер, чтобы он это дело пас,
но изначально всё равно неоткуда, со всеми вытекающими
((g, id, bm, bu, {star} = bu) => { addDestructor(r => r[5] == "e" && id in g && g[id].observe(r)); var bobs = g[id]; if (!bobs) { var fGuid = id + "Guid", pref = "CB." + fGuid; var {obs, prefs} = Services, pobs = PlacesObservers; var mk = PlacesUIUtils.LAST_USED_FOLDERS_META_KEY; bobs = g[id] = { async init() { bm.addObserver(this); pobs.addListener(["bookmark-added"], this.added = this.added.bind(this)); obs.addObserver(this, "quit-application-granted", false); var guid = g[fGuid] || prefs.getStringPref(pref, ""); if (!guid) try {var [guid] = await PlacesUtils.metadata.get(mk, []);} catch(ex) {guid = bm.unfiledGuid;} this.guids.length || this.guids.push(guid); }, observe(arg) { delete g[id]; bm.removeObserver(this); pobs.removeListener(["bookmark-added"], this.added); obs.removeObserver(this, "quit-application-granted"); var [guid] = this.guids; if (!arg) return prefs.setStringPref(pref, guid); if (arg[0] == "u") return g[fGuid] = guid; prefs.clearUserPref(pref); delete g[fGuid]; }, guids: [], skipTags: true, skipDescendantsOnItemRemoval: true, QueryInterface: g.ChromeUtils.generateQI([Ci.nsINavBookmarkObserver]), record(type, src, guid) { if (type == bm.TYPE_BOOKMARK && src == bm.SOURCES.DEFAULT) this.guids[0] = guid; }, added(events) { for(var e of events) this.record(e.itemType, e.source, e.parentGuid); }, onItemMoved(a, b, c, d, e, itemType, f, oldParentGuid, newParentGuid, source) { newParentGuid != oldParentGuid && this.record(itemType, source, newParentGuid); } }; var ps = ["onBeginUpdateBatch", "onEndUpdateBatch", "onItemRemoved", "onItemChanged", "onItemVisited"]; var noop = () => {}; for(var p of ps) bobs[p] = noop; bobs.init(); } addEventListener("mouseenter", { async handleEvent() { var starred = bu._itemGuids.size; star.tooltipText = this.char; starred && await this.fetch(); var result = []; for(var guid of (starred ? this : bobs).guids) { var arr = []; while(true) { if (!this.hover) return; var res = await bm.fetch(guid); if ((guid = res.parentGuid) == bm.rootGuid) { arr.unshift(bm.getLocalizedTitle(res)); break; } arr.unshift(res.title || "[Безымянная папка]"); } result.push(arr.join("\\")); } this.hover && this.setTooltip(result, starred); }, get fetch() { var set = this.guids = new Set(); var args = [b => set.add(b.parentGuid), {concurrent: true}]; delete this.fetch; return this.fetch = () => set.clear() || bm.fetch({url: gBrowser.currentURI.spec}, ...args); }, setTooltip(arr, starred) { var text = arr.join("\n"); if (starred) { var m = arr.length > 1; text = `Адрес${m ? "а" : ""} заклад${m ? "ок" : "ки"}:\n${text}`; } document.tooltipNode == star ? this.tt.label = text : star.tooltipText = text; }, get char() { addDestructor(() => document.l10n.translateElements([star])); delete this.char; return this.char = "\u3164"; }, get tt() { var list = InspectorUtils.getChildrenForNode(document.documentElement, true); delete this.tt; return this.tt = list.item(list.length - 1); }, get hover() {return star.matches(":hover");} }, false, star || 1); })( Cu.getGlobalForObject(Cu), "CBStarTooltipBookmarkAddedListener", PlacesUtils.bookmarks, BookmarkingUI );
а можно ли этот код адаптировать для custom_script.js
Можно, но хотелось бы услышать обоснование, например типа
я открываю окна браузера многими десятками,
поэтому хочу, чтобы всё обрабатывалось одним объектом
, или тому подобное, или совсем не подобное.
Иначе, проще и логичнее адаптировать код для custom_script_win.js
try {((bu, bm, {star} = bu) => { var listener = { async handleEvent() { if (!bu._itemGuids.size) return; star.tooltipText = "\u3164"; var result = []; await this.fetch(); for(var guid of this.guids) { var arr = []; while(true) { if (!this.hover) return; var res = await bm.fetch(guid); if ((guid = res.parentGuid) == bm.rootGuid) { arr.unshift(bm.getLocalizedTitle(res)); break; } arr.unshift(res.title || "[Безымянная папка]"); } result.push(arr.join("\\")); } this.hover && this.setTooltip(result); }, get fetch() { var set = this.guids = new Set(); var args = [b => set.add(b.parentGuid), {concurrent: true}]; delete this.fetch; return this.fetch = () => set.clear() || bm.fetch({url: gBrowser.currentURI.spec}, ...args); }, setTooltip(arr) { var m = arr.length > 1; var text = `Адрес${m ? "а" : ""} заклад${m ? "ок" : "ки"}:\n${arr.join("\n")}`; document.tooltipNode == star ? this.tt.label = text : star.tooltipText = text; }, get tt() { var list = InspectorUtils.getChildrenForNode(document.documentElement, true); delete this.tt; return this.tt = list.item(list.length - 1); }, get hover() {return star.matches(":hover");} }; star.addEventListener("mouseenter", listener); addEventListener("unload", () => star.removeEventListener("mouseenter", listener) , {once: true}); })(BookmarkingUI, PlacesUtils.bookmarks);} catch(ex) {Cu.reportError(ex);}
Отсутствует
Dumby
Это Ваш код (очистить историю закрытых вкладок)
Отсутствует
Не, я не знаю откуда взять об этом информацию.
А в том же окне звёздочки из строки Папка никак нельзя взять, там же как раз остаётся последняя папка в которую добавлялась закладка?
Можно попробовать подрядить обсёрвер, чтобы он это дело пас,
но изначально всё равно неоткуда, со всеми вытекающими
Не, так ничего к сожалению не показывает. А не, вру, извините, вроде всё показывает, буду посмотреть. Спасибо большое.
Отредактировано voqabuhe (18-03-2020 22:34:26)
Отсутствует
Dumby
Можно, но хотелось бы услышать обоснование
я бы объяснил, если бы понимал все отличия между custom_script.js | custom_script_all_win.js | custom_script_win.js (инфу толком не нашел)
просто, я как-то надолго задержался на старом FF52esr и теперь, когда решил обновиться, отчасти не понимаю, что тут теперь да как
даже не смог запустить само расширение CB
ткните пожалуйста меня носом, где взять РАБОЧИЙ комплект раскладок файлов по папкам и само дополнение
Добавлено:
спасибо, код для звездочки работает
Отредактировано Inko7 (18-03-2020 23:48:28)
Отсутствует
Чтобы еще приделать к коду, чтоб видно было , что тухнет?
Ну, например
document.querySelector( "#mainPopupSet > tooltip[onpopupshowing*=undoCloseTabsList]" )?.undoCloseTabsList.updUI();
А в том же окне звёздочки из строки Папка никак нельзя взять, там же как раз остаётся последняя папка в которую добавлялась закладка?
Может и взял бы, если бы после «показывало последнюю папку куда добавлялась закладка»
было бы так и написано « посредством окна звёздочки».
если бы понимал все отличия между custom_script.js | custom_script_all_win.js | custom_script_win.js (инфу толком не нашел)
custom_script_win.js исполняется в каждом окне браузера (browser.xhtml)
по событию "DOMContentLoaded".
custom_script_all_win.js исполняется так же, как и custom_script_win.js,
но во всех top-level (не контент вкладок, не сайдбар) окнах документов
с адресами по протоколу chrome:// , включая окна браузера.
Например: «Библиотека», «Информация о странице», «О Mozilla Firefox»,
и даже окошки алертов.
даже не смог запустить само расширение CB
ткните пожалуйста меня носом, где взять РАБОЧИЙ комплект раскладок файлов по папкам и само дополнение
Здесь необходимый конфигурационный код (второй спойлер).
Состоит из двух частей, антиподписячей и запускатора CB,
чтобы запускался раньше, чем запустился бы без него.
Позволяет устанавливать на релиз и бету paxmod'ы (WebExtensions Experiments)
и неподписанные WebExtensions, при наличии id в манифесте.
Задумайся! Оно тебе надо?
Типа внешний или внутренний «синдром кота», и всё такое.
Если да, тогда добавь код в начало своего config.js. Рестарт.
Само дополнение? Ну, могу предложить попробовать такой вариант:
вот длинная текстовая data-ссылка на простую HTML страницу.
Выделить всё, скопировать в адресную строку, нажать Enter.
Со страницы скачать custom_buttons-0.0.7.0.0.10-fx-paxmod.xpi
Ещё раз задумайся. Всё подвешено на очень тоненьком волоске,
расползается под пальцами, нуждается в постоянном уходе.
Не стоит строить на CB какую-либо стратегию, и уже очень давно.
Но если хочешь просто завести ностальгическую игрушку,
тогда добро пожаловать.
можно поправить пожалуйста эту кнопку для 74.0
Не, за эту не возьмусь, слишком заморочно, прости великодушно.
Отредактировано Dumby (19-03-2020 14:46:47)
Отсутствует
Хочу при помощи CB исправить баг, который не устранен и в свежих версиях MyPal.
Подробно здесь:
https://bugzilla.mozilla.org/show_bug.cgi?id=754623
Здесь суть:
https://hg.mozilla.org/mozilla-central/rev/6763cbc32e3e
С программированием дружу весьма поверхностно, но понимаю что в browser-places.js нужно просто заместить функцию gBrowser.visibleTabs.forEach
Все же увидел что это не описание функции, а передача ей параметров. Так что ее трогать не нужно. Тогда есть шанс просто заменить пару строк в browser-places.js ?
Отредактировано Grishanenko (19-03-2020 20:22:05)
Отсутствует
Dumby
спасибо за информацию!
Отредактировано Inko7 (19-03-2020 18:17:53)
Отсутствует
egorsemenov06 дальше сам с пунктами меню
// Блокировать повторный запуск функций и обработчиков при открытии настройки панелей ........................ var icon = this.icon ||document.getAnonymousElementByAttribute( this, 'class', 'toolbarbutton-icon'); icon.style.width = '16px', icon.style.height = '16px'; this.bottomPanel = function(aURL) { var prefBranch = "custombuttons.bottomPanel." if(!aURL && aURL != "") { try { aURL = Services.prefs.getCharPref(prefBranch + "url"); } catch(ex) { aURL = ""; } } if(aURL == "") return; if(aURL == gURLBar.value && !aURL.match(/^\w+?\:/)) aURL = "http://" + aURL; var panelID = "bottom-panel"; var gPanel = document.getElementById(panelID); var height; try { height = Services.prefs.getIntPref(prefBranch + "height"); } catch(ex) { height = 400; } if(gPanel) { var src = gPanel.firstChild.nextSibling.getAttribute("src"); if(aURL != src) { gPanel.firstChild.nextSibling.setAttribute("src", aURL); //gPanel.firstChild.nextSibling.loadURI(aURL); } else { Services.prefs.setIntPref(prefBranch + "height", gPanel.height); gPanel.parentNode.removeChild(gPanel.previousSibling); gPanel.parentNode.removeChild(gPanel); } } else { var appContent = document.getElementById("appcontent"); var spl = appContent.appendChild(document.createXULElement("splitter")); spl.setAttribute("collapse", "after"); spl.style.border = "none"; spl.style.borderTop = "1px solid threedhighlight"; spl.setAttribute("onclick", "this.setAttribute('state', '');"); var box = appContent.appendChild(document.createXULElement("vbox")); box.id = panelID; box.height = height; box.orient = "vertical"; var tbr = box.appendChild(document.createXULElement("toolbar")); tbr.setAttribute("fullscreentoolbar", true); var labelButton = tbr.appendChild(document.createXULElement("label")); labelButton.setAttribute("value", "Нижняя панель"); var spr = tbr.appendChild(document.createXULElement("spacer")); spr.setAttribute("flex", 1); var btc = tbr.appendChild(document.createXULElement("toolbarbutton")); btc.className = "tabs-closebutton"; btc.closePanel = function() { var gPanel = document.getElementById("bottom-panel"); gPanel.parentNode.removeChild(gPanel.previousSibling); gPanel.parentNode.removeChild(gPanel); } btc.setAttribute("id", "closeBottomPanel"); btc.style.listStyleImage = "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACt0lEQVQ4jaWSzUtUYRTGn/fcGZ25H+m9Iyne8fpFq4lGCsFFIW21NiKKuHIn4qpazDraabnMTVEh+Af0B0QIIohBowhlkM1MMTre+VLngzv3PW1SKWvVWR0eOL/zcM4jmBn/U4G/iTuzsyK7unoLUl4HABDtdExNbV1fXr60Tfzp4J1h3Dd1/ak1OHhN7+kBiHCaTsPd2NgrlMsP7x4fv/0nYE3XH9ix2GLbzIwQmvYbmCsVHL16xd+3tx/dOTl5dqbTWfPeMIavOs6COT0tmBmyWAS1toJaWyGLRbCUMKemxFXHWXhvGMOXACrw2BwdJYUITX190MbG4O/twf/yBdrYGJr6+6EQwbx3j1QhHv8GWDfNNjUavR3u6ACyWQRjMQRsG+rkJNSJCQRsG8FYDDKbRbi9Harj3F43zbYLB41Gr2bbRIUCFACnS0vwMhkEbBsB24aXyaCcSEDJZiFyOWidnYRGo/f8jQpQp9NTiFwOACCJACEuDsgMeXAAuC7YMECeBwWonwOaLOtT/evXMhTlSs00oS8vI2jbqGcyADOau7pgvHiB8vg4tMND1F233GRZn87pzIwtXX9eiEb5uLubC2/ecC2V4qOhIT4aGuJqKsX516/52HG4EI3ylq4/P5s7z8FHy2qXnvehOxTqDBGhFongiusCAMqWhVA+j5qU+Far/RDB4M2BfP7gUpCSLS03qr7/NiyEExEC6i+9AsBlRpU5FVaU+zdKpeSlHCSTSazOzW0XNW2gCjzZ9/3Pu77Pu77P+77/uQo8cTVt4OXMzM7a2tpFlBOJhFhZWWkulUphz/NUKWWYmUPM3GwCKgBRAKoA6kRUI6JKIBCo6rpeGRkZqQlmRjqdxuLiIm1ublIul6NKpaI0Gg3yfV8AABFxMBiUoVBIRiIRPx6Py/n5eRmPx/ETBvM/dPD/rBwAAAAASUVORK5CYII=)"; btc.setAttribute("oncommand", "this.closePanel()"); var ifr = box.appendChild(document.createXULElement("browser")); ifr.setAttribute("type", "content"); ifr.setAttribute("flex", 1); ifr.setAttribute("src", aURL); ifr.setAttribute("tooltip", "aHTMLTooltip"); ifr.setAttribute("onclick", "return contentAreaClick(event, true)"); ifr.setAttribute("autocompletepopup", "PopupAutoComplete"); ifr.setAttribute("contextmenu", "contentAreaContextMenu"); ifr.setAttribute("contentcontextmenu", "contentAreaContextMenu"); } Services.prefs.setCharPref(prefBranch + "url", aURL); } //------------------------------------ function addMenuitem(aLabel, aURL, aNode, aObjString) { var mItem = aNode.appendChild(document.createXULElement("menuitem")); mItem.setAttribute("label", aLabel); mItem.setAttribute("oncommand", aObjString + ".bottomPanel('" + aURL + "');"); } function addSeparator(aNode, aNum) { var separator = aNode.appendChild(document.createXULElement("menuseparator")); separator.id = "bottom-panel-button-separator" + aNum; } var mPopup = document.createXULElement("menupopup"); mPopup.setAttribute("oncommand", "event.stopPropagation()"); mPopup.setAttribute("onpopupshowing", "this.parentNode.popupShowing(this)"); objString = "this.parentNode.parentNode"; addMenuitem("about:about", "about:about", mPopup, objString); addMenuitem("about:config", "about:config", mPopup, objString); addMenuitem("about:support", "about:support", mPopup, objString); addMenuitem("about:memory", "about:memory", mPopup, objString); addMenuitem("about:debugging", "about:debugging", mPopup, objString); addMenuitem("about:cache", "about:cache", mPopup, objString); addMenuitem("about:networking", "about:networking", mPopup, objString); addMenuitem("about:performance", "about:performance", mPopup, objString); addSeparator(mPopup, 0); addMenuitem("Настройки", "about:preferences", mPopup, objString); addMenuitem("Дополнения", "chrome://mozapps/content/extensions/extensions.xhtml?type=extensions", mPopup, objString); addMenuitem("Менеджер Паролей", "chrome://passwordmgr/content/passwordManager.xhtml", mPopup, objString); addMenuitem("DOM Inspector", "chrome://inspector/content/", mPopup, objString); addSeparator(mPopup, 0); addMenuitem("Загрузки", "about:downloads", mPopup, objString); addMenuitem("Управление закладками", "chrome://browser/content/places/places.xhtml", mPopup, objString); addMenuitem("Куки", "chrome://browser/content/preferences/siteDataSettings.xhtml", mPopup, objString); addMenuitem("История", "chrome://browser/content/places/historySidebar.xhtml", mPopup, objString); addMenuitem("О Firefox", "chrome://browser/content/aboutDialog.xhtml", mPopup, objString); this.appendChild(mPopup); this.type = "menu"; this.orient = "horizontal"; function handleKeydown(e) { if ( !e.shiftKey && !e.altKey && !e.ctrlKey && e.keyCode == 27 ) { if ( !document.getElementById('closeBottomPanel') ) return; e.preventDefault(); e.stopPropagation(); document.getElementById('closeBottomPanel').click(); }; } window.addEventListener('keydown', handleKeydown, false);
Отсутствует
Может и взял бы, если бы после «показывало последнюю папку куда добавлялась закладка»
было бы так и написано « посредством окна звёздочки».
Да ладно, зачем бы я пытался ограничить творческий процесс мастера какими-то рамками. Эт я так, больше для себя спросил. А кнопка замечательно работает, ещё раз спасибо.
Отсутствует
Dumby подскажи вот только сейчас заметил ошибку, она правда не на что не влияет, но все таки - this.parentNode.popupShowing в строчке - mPopup.setAttribute("onpopupshowing", "this.parentNode.popupShowing(this)"); Это как то можно исправить в коде
// Блокировать повторный запуск функций и обработчиков при открытии настройки панелей ........................ var icon = this.icon ||document.getAnonymousElementByAttribute( this, 'class', 'toolbarbutton-icon'); icon.style.width = '16px', icon.style.height = '16px'; this.bottomPanel = function(aURL) { var prefBranch = "custombuttons.bottomPanel." if(!aURL && aURL != "") { try { aURL = Services.prefs.getCharPref(prefBranch + "url"); } catch(ex) { aURL = ""; } } if(aURL == "") return; if(aURL == gURLBar.value && !aURL.match(/^\w+?\:/)) aURL = "http://" + aURL; var panelID = "bottom-panel"; var gPanel = document.getElementById(panelID); var height; try { height = Services.prefs.getIntPref(prefBranch + "height"); } catch(ex) { height = 400; } if(gPanel) { var src = gPanel.firstChild.nextSibling.getAttribute("src"); if(aURL != src) { gPanel.firstChild.nextSibling.setAttribute("src", aURL); //gPanel.firstChild.nextSibling.loadURI(aURL); } else { Services.prefs.setIntPref(prefBranch + "height", gPanel.height); gPanel.parentNode.removeChild(gPanel.previousSibling); gPanel.parentNode.removeChild(gPanel); } } else { var appContent = document.getElementById("appcontent"); var spl = appContent.appendChild(document.createXULElement("splitter")); spl.setAttribute("collapse", "after"); spl.style.border = "none"; spl.style.borderTop = "1px solid threedhighlight"; spl.setAttribute("onclick", "this.setAttribute('state', '');"); var box = appContent.appendChild(document.createXULElement("vbox")); box.id = panelID; box.height = height; box.orient = "vertical"; var tbr = box.appendChild(document.createXULElement("toolbar")); tbr.setAttribute("fullscreentoolbar", true); var labelButton = tbr.appendChild(document.createXULElement("label")); labelButton.setAttribute("value", "Нижняя панель"); var spr = tbr.appendChild(document.createXULElement("spacer")); spr.setAttribute("flex", 1); var btc = tbr.appendChild(document.createXULElement("toolbarbutton")); btc.className = "tabs-closebutton"; btc.closePanel = function() { var gPanel = document.getElementById("bottom-panel"); gPanel.parentNode.removeChild(gPanel.previousSibling); gPanel.parentNode.removeChild(gPanel); } btc.setAttribute("id", "closeBottomPanel"); btc.style.listStyleImage = "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACt0lEQVQ4jaWSzUtUYRTGn/fcGZ25H+m9Iyne8fpFq4lGCsFFIW21NiKKuHIn4qpazDraabnMTVEh+Af0B0QIIohBowhlkM1MMTre+VLngzv3PW1SKWvVWR0eOL/zcM4jmBn/U4G/iTuzsyK7unoLUl4HABDtdExNbV1fXr60Tfzp4J1h3Dd1/ak1OHhN7+kBiHCaTsPd2NgrlMsP7x4fv/0nYE3XH9ix2GLbzIwQmvYbmCsVHL16xd+3tx/dOTl5dqbTWfPeMIavOs6COT0tmBmyWAS1toJaWyGLRbCUMKemxFXHWXhvGMOXACrw2BwdJYUITX190MbG4O/twf/yBdrYGJr6+6EQwbx3j1QhHv8GWDfNNjUavR3u6ACyWQRjMQRsG+rkJNSJCQRsG8FYDDKbRbi9Harj3F43zbYLB41Gr2bbRIUCFACnS0vwMhkEbBsB24aXyaCcSEDJZiFyOWidnYRGo/f8jQpQp9NTiFwOACCJACEuDsgMeXAAuC7YMECeBwWonwOaLOtT/evXMhTlSs00oS8vI2jbqGcyADOau7pgvHiB8vg4tMND1F233GRZn87pzIwtXX9eiEb5uLubC2/ecC2V4qOhIT4aGuJqKsX516/52HG4EI3ylq4/P5s7z8FHy2qXnvehOxTqDBGhFongiusCAMqWhVA+j5qU+Far/RDB4M2BfP7gUpCSLS03qr7/NiyEExEC6i+9AsBlRpU5FVaU+zdKpeSlHCSTSazOzW0XNW2gCjzZ9/3Pu77Pu77P+77/uQo8cTVt4OXMzM7a2tpFlBOJhFhZWWkulUphz/NUKWWYmUPM3GwCKgBRAKoA6kRUI6JKIBCo6rpeGRkZqQlmRjqdxuLiIm1ublIul6NKpaI0Gg3yfV8AABFxMBiUoVBIRiIRPx6Py/n5eRmPx/ETBvM/dPD/rBwAAAAASUVORK5CYII=)"; btc.setAttribute("oncommand", "this.closePanel()"); var ifr = box.appendChild(document.createXULElement("browser")); ifr.setAttribute("type", "content"); ifr.setAttribute("flex", 1); ifr.setAttribute("src", aURL); ifr.setAttribute("tooltip", "aHTMLTooltip"); ifr.setAttribute("onclick", "return contentAreaClick(event, true)"); ifr.setAttribute("autocompletepopup", "PopupAutoComplete"); ifr.setAttribute("contextmenu", "contentAreaContextMenu"); ifr.setAttribute("contentcontextmenu", "contentAreaContextMenu"); } Services.prefs.setCharPref(prefBranch + "url", aURL); } //------------------------------------ function addMenuitem(aLabel, aURL, aNode, aObjString) { var mItem = aNode.appendChild(document.createXULElement("menuitem")); mItem.setAttribute("label", aLabel); mItem.setAttribute("oncommand", aObjString + ".bottomPanel('" + aURL + "');"); } function addSeparator(aNode, aNum) { var separator = aNode.appendChild(document.createXULElement("menuseparator")); separator.id = "bottom-panel-button-separator" + aNum; } var mPopup = document.createXULElement("menupopup"); mPopup.setAttribute("oncommand", "event.stopPropagation()"); mPopup.setAttribute("onpopupshowing", "this.parentNode.popupShowing(this)"); objString = "this.parentNode.parentNode"; addMenuitem("about:about", "about:about", mPopup, objString); addMenuitem("about:config", "about:config", mPopup, objString); addMenuitem("about:support", "about:support", mPopup, objString); addMenuitem("about:memory", "about:memory", mPopup, objString); addMenuitem("about:debugging", "about:debugging", mPopup, objString); addMenuitem("about:cache", "about:cache", mPopup, objString); addMenuitem("about:networking", "about:networking", mPopup, objString); addMenuitem("about:performance", "about:performance", mPopup, objString); addSeparator(mPopup, 0); addMenuitem("Настройки", "about:preferences", mPopup, objString); addMenuitem("Дополнения", "chrome://mozapps/content/extensions/extensions.xhtml?type=extensions", mPopup, objString); addMenuitem("Менеджер Паролей", "chrome://passwordmgr/content/passwordManager.xhtml", mPopup, objString); addMenuitem("DOM Inspector", "chrome://inspector/content/", mPopup, objString); addSeparator(mPopup, 0); addMenuitem("Загрузки", "about:downloads", mPopup, objString); addMenuitem("Управление закладками", "chrome://browser/content/places/places.xhtml", mPopup, objString); addMenuitem("Куки", "chrome://browser/content/preferences/siteDataSettings.xhtml", mPopup, objString); addMenuitem("История", "chrome://browser/content/places/historySidebar.xhtml", mPopup, objString); addMenuitem("О Firefox", "chrome://browser/content/aboutDialog.xhtml", mPopup, objString); this.appendChild(mPopup); this.type = "menu"; this.orient = "horizontal"; function handleKeydown(e) { if ( !e.shiftKey && !e.altKey && !e.ctrlKey && e.keyCode == 27 ) { if ( !document.getElementById('closeBottomPanel') ) return; e.preventDefault(); e.stopPropagation(); document.getElementById('closeBottomPanel').click(); }; } window.addEventListener('keydown', handleKeydown, false);
Отсутствует
а библиотека user_chrome_files имеет больше шансов на существование?
А если в смысле как производное от конфигурационного файла,
то здесь все в одной лодке.
Баг о превращении config.js в ничто существует.
И патч к багу есть, и патч к багу одобрен.
То есть, стоит сделать пару кликов, и, уже максимум через сутки,
можно будет констатировать:
«Файерфокс Релиз Бетович. Время смерти ... »
критично чего не хватает, так это кнопки Switch Keyboard Layout
пожалуйста портируй ее для user_chrome_files
Как-то так, наверно (в custom_script.js)
// http://infocatcher.ucoz.net/js/cb/switchKeybLayout.js // https://github.com/Infocatcher/Custom_Buttons/tree/master/Switch_Keyboard_Layout // Switch Keyboard Layout button for Custom Buttons // (code for "code" section) // (c) Infocatcher 2009, 2013-2014 // version 0.2.0 - 2014-10-20 // Convert text, typed in wrong keyboard layout. // Configured for Russian <-> English. try {(keybUtils => CustomizableUI.createWidget({ type: "custom", id: "SwitchKeyboardLayout", onBuild(doc) { var btn = doc.createXULElement("toolbarbutton"); btn.id = this.id; btn.label = btn.tooltipText = "Switch Keyboard Layout"; btn.image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAk1BMVEX///8/Pz8BAQF8fHwJCQkCAgIJCQl8fHx9fX0AAABJSUkBAQENDQ0wMDBVVVUAAABra2t0dHR7e3thYWEBAQEAAAAAAAABAQEAAAAgICABAQEBAQH8/Pzw8PDp6en39/fj4+Pe3t41V9I/YeWKioqDg4N9fX0jRa8wUrVoaGhkhuxWeNx1dXVCZMhvb28kRqsqTL4KidXxAAAAHHRSTlMAAABndwAAAAA0blVZcm1naWhNa6hrcJ8AAKRU4jk/3gAAAHVJREFUeF6FyMUCwjAUBdEbaQupUMOjqMv/fx1dQN6yZ3aDcWnyw6ezoRWNYc15kqKQZCFlgTKQQwgllL/dn5f3+bPb+6P3CpWNw56srdCZOMzDmA61i8O9nKvRaHLVukEryFKIFtnkj7ENYxmNdd5v+5xj1BcJ/w9Kj6K7ZAAAAABJRU5ErkJggg=="; btn.setAttribute("oncommand", "linkedObj.switch(document);"); btn.className = "toolbarbutton-1 chromeclass-toolbar-additional"; btn.linkedObj = this; return btn; }, switch(doc) { var br = doc.activeElement; br && br.localName == "browser" && br.isRemoteBrowser ? br.messageManager.loadFrameScript(this.url, false) : this.keybUtils.switchSelKeybLayout(); }, get url() { delete this.url; return this.url = `data:;charset=utf-8,(${ encodeURIComponent(keybUtils) }).switchSelKeybLayout()`; }, get keybUtils() { delete this.keybUtils; var def = "let{KeyEvent,HTMLInputElement,HTMLTextAreaElement}=Cu.getGlobalForObject(Services);"; var url = `data:;charset=utf-8,${def}%0Athis.keybUtils=${encodeURIComponent(keybUtils)}`; Services.scriptloader.loadSubScript(url, this); var {id} = this; this.keybUtils.getFocusedElement = function(_subCall, _focusFixed) { var window = Services.focus.activeWindow, {document} = window; var button = document.getElementById(id); if( !_focusFixed && "closeMenus" in window && document.commandDispatcher.focusedElement == button ) { window.closeMenus(button); window.setTimeout(function(_this) { _this.switchSelKeybLayout(_subCall, true); }, 0, this); return; } return document.commandDispatcher.focusedElement; } return this.keybUtils; } }))(`{ //== Options noSelBehavior: { // Shift+Home ctrlKey: false, altKey: false, shiftKey: true, metaKey: false, keyCode: KeyEvent.DOM_VK_HOME, charCode: 0 }, // 0 - do nothing // 1 - convert all text // Or use object like following to simulate "keypress" event: convTableForward: { // ru -> en "\\"": "@", ":": "^", ";": "$", "?": "&", ",": "?", "/": "|", ".": "/", "э": "'", "б": ",", "ю": ".", "Ж": ":", "ж": ";", "Б": "<", "Ю": ">", "Э": "\\"", "х": "[", "ъ": "]", "ё": "\`", "Х": "{", "Ъ": "}", "Ё": "~", "№": "#", "Ф": "A", "ф": "a", "И": "B", "и": "b", "С": "C", "с": "c", "В": "D", "в": "d", "У": "E", "у": "e", "А": "F", "а": "f", "П": "G", "п": "g", "Р": "H", "р": "h", "Ш": "I", "ш": "i", "О": "J", "о": "j", "Л": "K", "л": "k", "Д": "L", "д": "l", "Ь": "M", "ь": "m", "Т": "N", "т": "n", "Щ": "O", "щ": "o", "З": "P", "з": "p", "Й": "Q", "й": "q", "К": "R", "к": "r", "Ы": "S", "ы": "s", "Е": "T", "е": "t", "Г": "U", "г": "u", "М": "V", "м": "v", "Ц": "W", "ц": "w", "Ч": "X", "ч": "x", "Н": "Y", "н": "y", "Я": "Z", "я": "z", __proto__: null }, //== End of options get convTableBackward() { var ctb = { __proto__: null }; var ctf = this.convTableForward; for(var c in ctf) ctb[ctf[c]] = c; delete this.convTableBackward; return this.convTableBackward = ctb; }, inPrimaryLayout: function(s) { for(var i = 0, l = s.length; i < l; ++i) { var c = s.charAt(i); if(c in this.convTableForward) return true; if(c in this.convTableBackward) return false; } return false; }, switchKeybLayout: function(s, convTable) { var res = ""; for(var i = 0, l = s.length; i < l; ++i) { var c = s.charAt(i); res += c in convTable ? convTable[c] : c; } return res; }, getFocusedElement: function() { return Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager) .getFocusedElementForWindow(content, true, {}); }, switchSelKeybLayout: function(_subCall, _focusFixed) { var fe = this.getFocusedElement(_subCall, _focusFixed); if(!fe) return; if(fe instanceof HTMLInputElement || fe instanceof HTMLTextAreaElement) { var ta = fe; try { var val = ta.value; var sel = val.substring(ta.selectionStart, ta.selectionEnd); } catch(e) { // Non-text HTMLInputElement return; } if(!sel && val && this.noSelBehavior && !_subCall) { if(this.noSelBehavior == 1) { ta.selectionStart = 0; ta.selectionEnd = val.length; sel = val; } else { this.handleNoSel(ta); return; } } if(!sel) return; var res = this.switchKeybLayout( sel, this.inPrimaryLayout(sel) ? this.convTableForward : this.convTableBackward ); if(res != sel) this.insertText(ta, res); } else if(fe.contentEditable == "true") { var doc = fe.ownerDocument; var docURI = doc.documentURI; if( docURI.substr(0, 5) == "data:" && docURI.indexOf("chrome://browser/skin/devtools/") != -1 ) { //~ todo: seems like we only can use paste from clipboard here... return; } var sel = doc.defaultView.getSelection(); var rng = sel.rangeCount && sel.getRangeAt(0); var tmpNode; if(!rng || rng.collapsed) { if(!this.noSelBehavior || _subCall) return; if(this.noSelBehavior == 1) { var r = doc.createRange(); r.selectNodeContents(fe); sel.removeAllRanges(); sel.addRange(r); tmpNode = fe.cloneNode(true); } else { this.handleNoSel(fe); return; } } else { tmpNode = doc.createElementNS("http://www.w3.org/1999/xhtml", "div"); tmpNode.appendChild(rng.cloneContents()); } var orig = tmpNode.innerHTML; var convTable = this.inPrimaryLayout(tmpNode.textContent) ? this.convTableForward : this.convTableBackward; var _this = this; var parseChildNodes = function(node) { if(node instanceof Element) { var childNodes = node.childNodes; for(var i = childNodes.length - 1; i >= 0; --i) parseChildNodes(childNodes[i]); } else if(node.nodeType == node.TEXT_NODE) { var text = node.nodeValue; var newText = _this.switchKeybLayout(node.nodeValue, convTable); if(newText != text) node.parentNode.replaceChild(doc.createTextNode(newText), node); } } parseChildNodes(tmpNode); var res = tmpNode.innerHTML; if(res != orig) doc.execCommand("insertHTML", false, res); } }, handleNoSel: function(node) { this.select(node); this.switchSelKeybLayout(true); }, select: function(node) { var e = this.noSelBehavior; if(!e || typeof e != "object") return; var evt = node.ownerDocument.createEvent("KeyboardEvent"); evt.initKeyEvent( "keypress", true /*bubbles*/, true /*cancelable*/, node.ownerDocument.defaultView, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.keyCode, e.charCode ); node.dispatchEvent(evt); }, insertText: function(ta, text) { //var editor = ta.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor var editor = ta.editor .QueryInterface(Components.interfaces.nsIPlaintextEditor || Ci.nsIEditor); if(editor.flags & editor.eEditorReadonlyMask) return; var sTop = ta.scrollTop; var sHeight = ta.scrollHeight; var sLeft = ta.scrollLeft; // var sWidth = ta.scrollWidth; if(text) editor.insertText(text); else editor.deleteSelection(0, 0); ta.scrollTop = sTop + (ta.scrollHeight - sHeight); ta.scrollLeft = sLeft; // + (ta.scrollWidth - sWidth); } }`)} catch(ex) {Cu.reportError(ex);}
только сейчас заметил ошибку, она правда не на что не влияет, но все таки - this.parentNode.popupShowing
Поиск в коде: popupShowing
Сколько совпадений? Вывод очевиден.
Отсутствует
Dumby вот переделал , так ничего не ломаю?
// Блокировать повторный запуск функций и обработчиков при открытии настройки панелей ........................ var icon = this.icon ||document.getAnonymousElementByAttribute( this, 'class', 'toolbarbutton-icon'); icon.style.width = '16px', icon.style.height = '16px'; this.bottomPanel = function(aURL) { var prefBranch = "custombuttons.bottomPanel." if(!aURL && aURL != "") { try { aURL = Services.prefs.getCharPref(prefBranch + "url"); } catch(ex) { aURL = ""; } } if(aURL == "") return; if(aURL == gURLBar.value && !aURL.match(/^\w+?\:/)) aURL = "http://" + aURL; var panelID = "bottom-panel"; var gPanel = document.getElementById(panelID); var height; try { height = Services.prefs.getIntPref(prefBranch + "height"); } catch(ex) { height = 400; } if(gPanel) { var src = gPanel.firstChild.nextSibling.getAttribute("src"); if(aURL != src) { gPanel.firstChild.nextSibling.setAttribute("src", aURL); //gPanel.firstChild.nextSibling.loadURI(aURL); } else { Services.prefs.setIntPref(prefBranch + "height", gPanel.height); gPanel.parentNode.removeChild(gPanel.previousSibling); gPanel.parentNode.removeChild(gPanel); } } else { var appContent = document.getElementById("appcontent"); var spl = appContent.appendChild(document.createXULElement("splitter")); spl.setAttribute("collapse", "after"); spl.style.border = "none"; spl.style.borderTop = "1px solid threedhighlight"; spl.setAttribute("onclick", "this.setAttribute('state', '');"); var box = appContent.appendChild(document.createXULElement("vbox")); box.id = panelID; box.height = height; box.orient = "vertical"; var tbr = box.appendChild(document.createXULElement("toolbar")); tbr.setAttribute("fullscreentoolbar", true); var labelButton = tbr.appendChild(document.createXULElement("label")); labelButton.setAttribute("value", "Нижняя панель"); var spr = tbr.appendChild(document.createXULElement("spacer")); spr.setAttribute("flex", 1); var btc = tbr.appendChild(document.createXULElement("toolbarbutton")); btc.className = "tabs-closebutton"; btc.closePanel = function() { var gPanel = document.getElementById("bottom-panel"); gPanel.parentNode.removeChild(gPanel.previousSibling); gPanel.parentNode.removeChild(gPanel); } btc.setAttribute("id", "closeBottomPanel"); btc.style.listStyleImage = "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACt0lEQVQ4jaWSzUtUYRTGn/fcGZ25H+m9Iyne8fpFq4lGCsFFIW21NiKKuHIn4qpazDraabnMTVEh+Af0B0QIIohBowhlkM1MMTre+VLngzv3PW1SKWvVWR0eOL/zcM4jmBn/U4G/iTuzsyK7unoLUl4HABDtdExNbV1fXr60Tfzp4J1h3Dd1/ak1OHhN7+kBiHCaTsPd2NgrlMsP7x4fv/0nYE3XH9ix2GLbzIwQmvYbmCsVHL16xd+3tx/dOTl5dqbTWfPeMIavOs6COT0tmBmyWAS1toJaWyGLRbCUMKemxFXHWXhvGMOXACrw2BwdJYUITX190MbG4O/twf/yBdrYGJr6+6EQwbx3j1QhHv8GWDfNNjUavR3u6ACyWQRjMQRsG+rkJNSJCQRsG8FYDDKbRbi9Harj3F43zbYLB41Gr2bbRIUCFACnS0vwMhkEbBsB24aXyaCcSEDJZiFyOWidnYRGo/f8jQpQp9NTiFwOACCJACEuDsgMeXAAuC7YMECeBwWonwOaLOtT/evXMhTlSs00oS8vI2jbqGcyADOau7pgvHiB8vg4tMND1F233GRZn87pzIwtXX9eiEb5uLubC2/ecC2V4qOhIT4aGuJqKsX516/52HG4EI3ylq4/P5s7z8FHy2qXnvehOxTqDBGhFongiusCAMqWhVA+j5qU+Far/RDB4M2BfP7gUpCSLS03qr7/NiyEExEC6i+9AsBlRpU5FVaU+zdKpeSlHCSTSazOzW0XNW2gCjzZ9/3Pu77Pu77P+77/uQo8cTVt4OXMzM7a2tpFlBOJhFhZWWkulUphz/NUKWWYmUPM3GwCKgBRAKoA6kRUI6JKIBCo6rpeGRkZqQlmRjqdxuLiIm1ublIul6NKpaI0Gg3yfV8AABFxMBiUoVBIRiIRPx6Py/n5eRmPx/ETBvM/dPD/rBwAAAAASUVORK5CYII=)"; btc.setAttribute("oncommand", "this.closePanel()"); var ifr = box.appendChild(document.createXULElement("browser")); ifr.setAttribute("type", "content"); ifr.setAttribute("flex", 1); ifr.setAttribute("src", aURL); ifr.setAttribute("tooltip", "aHTMLTooltip"); ifr.setAttribute("onclick", "return contentAreaClick(event, true)"); ifr.setAttribute("autocompletepopup", "PopupAutoComplete"); ifr.setAttribute("contextmenu", "contentAreaContextMenu"); ifr.setAttribute("contentcontextmenu", "contentAreaContextMenu"); } Services.prefs.setCharPref(prefBranch + "url", aURL); } //------------------------------------ var array = [ { label: "about:about", aURL: "about:about"}, { label: "about:config", aURL: "about:config"}, { label: "about:support", aURL: "about:support"}, { label: "about:memory", aURL: "about:memory"}, { label: "about:cache", aURL: "about:cache"}, { label: "about:networking", aURL: "about:networking"}, { label: "about:plugins", aURL: "about:plugins"}, { label: "about:performance", aURL: "about:performance"}, { separator: ''}, { label: "Менеджер Паролей", aURL: "chrome://passwordmgr/content/passwordManager.xhtml"}, { label: "DOM Inspector", aURL: "chrome://inspector/content/"}, { separator: ''}, { label: "Загрузки", aURL: "about:downloads"}, { label: "Управление закладками", aURL: "chrome://browser/content/places/places.xhtml"}, { label: "Куки", aURL: "chrome://browser/content/preferences/siteDataSettings.xhtml"}, { label: "История", aURL: "chrome://browser/content/places/historySidebar.xhtml"}, { label: "О Firefox", aURL: "chrome://browser/content/aboutDialog.xhtml"}, ]; var menuPopup = self.appendChild(document.createXULElement("menupopup")); array.forEach((m,i)=> { if ("separator" in m) { menuPopup.appendChild(document.createXULElement("menuseparator")); return }; var mItem = menuPopup.appendChild(document.createXULElement("menuitem")); mItem.setAttribute("label", m.label); mItem.setAttribute("oncommand", "bottomPanel('" + m.aURL + "');"); }); menuPopup.setAttribute("onclick", "event.stopPropagation()"); self._handleClick =()=> menuPopup.openPopup(this, "after_start"); function handleKeydown(e) { if ( !e.shiftKey && !e.altKey && !e.ctrlKey && e.keyCode == 27 ) { if ( !document.getElementById('closeBottomPanel') ) return; e.preventDefault(); e.stopPropagation(); document.getElementById('closeBottomPanel').click(); }; } window.addEventListener('keydown', handleKeydown, false);
Отредактировано Andrey_Krropotkin (21-03-2020 14:24:00)
Отсутствует
Dumby
Как-то так, наверно (в custom_script.js)
ничего не произошло, кнопка не появилась...
еще забыл уточнить такой моментик: сама кнопка как таковая мне особо не нужна (редко когда жал на нее), но очень нужно действие исправлялки повесить на клавишу F8
Отсутствует
ничего не произошло, кнопка не появилась...
Не забываем делать перезапуск...
В папке custom_scripts находятся скрипты которые при необходимости можно подключить в настройках
и добавить свой код (после редактирования перезапустить кнопкой Перезагрузка - ПКМ: Отключить загрузку содержимого из кеша и перезапустить).
или вручную очистить startupCache
Отсутствует