您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Hide posts by keywords with the dashboard and hide posts from verified accounts
当前为
// ==UserScript== // @name Panel Control XFilter 2.4.52 (c) tapeavion // @namespace http://tampermonkey.net/ // @version 2.4.52 // @description Hide posts by keywords with the dashboard and hide posts from verified accounts // @author gullampis810 // @match https://x.com/* // @match https://x.com/i/grok* // @match https://blank.org/* // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_setValue // @grant GM_getValue // @license MIT // @icon https://www.pinclipart.com/picdir/big/450-4507608_twitter-circle-clipart.png // ==/UserScript== (function () { "use strict"; // ===== Настройки и инициализация ===== // const STORAGE_KEY = "hiddenKeywords"; const FAVORITE_USERS_KEY = "favoriteUsers"; let hiddenKeywords = JSON.parse(localStorage.getItem(STORAGE_KEY)) || []; let favoriteUsers = JSON.parse(localStorage.getItem(FAVORITE_USERS_KEY)) || []; let unblockedKeywords = JSON.parse(localStorage.getItem("unblockedKeywords")) || []; let hideVerifiedAccounts = false; let hideNonVerifiedAccounts = JSON.parse(localStorage.getItem("hideNonVerifiedAccounts")) || false; let isShowingFavorites = false; const languageFilters = { english: /[a-zA-Z]/, russian: /[А-Яа-яЁё]/, japanese: /[\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Han}]/u, ukrainian: /[А-Яа-яІіЄєЇїҐґ]/, belarusian: /[А-Яа-яЎўЁёІі]/, tatar: /[А-Яа-яӘәӨөҮүҖҗ]/, mongolian: /[\p{Script=Mongolian}]/u, chinese: /[\p{Script=Han}]/u, german: /[a-zA-ZßÄäÖöÜü]/, polish: /[a-zA-ZąćęłńóśźżĄĆĘŁŃÓŚŹŻ]/, french: /[a-zA-Zàâçéèêëîïôûùüÿ]/, swedish: /[a-zA-ZåäöÅÄÖ]/, estonian: /[a-zA-ZäõöüÄÕÖÜ]/, danish: /[a-zA-Z帿ŨÆ]/, turkish: /[a-zA-ZıİçÇğĞöÖşŞüÜ]/, portuguese: /[a-zA-Zàáâãçéêíóôõúü]/, }; let activeLanguageFilters = {}; // ===== Сохранение в localStorage ===== // function saveKeywords() { localStorage.setItem(STORAGE_KEY, JSON.stringify(hiddenKeywords)); } function saveFavoriteUsers() { localStorage.setItem(FAVORITE_USERS_KEY, JSON.stringify(favoriteUsers)); } function saveUnblockedKeywords() { localStorage.setItem("unblockedKeywords", JSON.stringify(unblockedKeywords)); } // ===== Функция для обновления фильтров по языкам ===== // function updateLanguageFilter(language) { if (activeLanguageFilters[language]) { delete activeLanguageFilters[language]; } else { activeLanguageFilters[language] = languageFilters[language]; } hidePosts(); } // ===== Проверка языка текста ===== // function isTextInLanguage(text) { for (const [language, regex] of Object.entries(activeLanguageFilters)) { if (regex.test(text)) { return true; } } return false; } // ===== Функция скрытия постов ===== // function hidePosts() { document.querySelectorAll("article").forEach((article) => { const textContent = article.innerText.toLowerCase(); const isVerifiedAccount = article.querySelector('[data-testid="icon-verified"]'); const usernameElement = article.querySelector('a[href*="/"]'); const username = usernameElement ? usernameElement.getAttribute("href").slice(1).toLowerCase() : ""; const isFavoriteUser = favoriteUsers.includes(username); if (isFavoriteUser) { article.style.display = ""; return; } const matchesKeyword = hiddenKeywords.some((keyword) => { try { return new RegExp(keyword, "i").test(textContent); } catch (e) { return textContent.includes(keyword.toLowerCase()); } }); const shouldHideVerified = hideVerifiedAccounts && isVerifiedAccount; const shouldHideNonVerified = hideNonVerifiedAccounts && !isVerifiedAccount; const shouldHideByLanguage = isTextInLanguage(textContent); const shouldHideByKeyword = matchesKeyword; if (shouldHideVerified || shouldHideNonVerified || shouldHideByLanguage || shouldHideByKeyword) { article.style.display = "none"; } else { article.style.display = ""; } }); } // ===== Debounce для оптимизации ===== // function debounce(func, wait) { let timeout; return function (...args) { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), wait); }; } const debouncedHidePosts = debounce(hidePosts, 200); // ===== Создание панели управления ===== // const panel = document.createElement("div"); panel.style.position = "fixed"; panel.style.bottom = "62px"; panel.style.right = "180px"; panel.style.width = "335px"; panel.style.height = "510px"; panel.style.padding = "8px"; panel.style.fontFamily = "Arial, sans-serif"; panel.style.backgroundColor = "#34506c"; panel.style.color = "#fff"; panel.style.borderRadius = "8px"; panel.style.boxShadow = "0 0 10px rgba(0,0,0,0.5)"; panel.style.zIndex = "9999"; panel.style.overflow = "auto"; panel.style.transition = "height 0.3s ease"; panel.innerHTML = ` <h3 style="margin: 0; font-size: 16px;">Hiding Control</h3> <h4 class="version-text">v2.4.52</h4> <input id="keywordInput" type="text" placeholder="Enter the word or @username" style="width: calc(100% - 95px); height: 30px; padding: 5px; margin: 10px 0; border-radius: 5px; border: none; background: #15202b; "> <div style="display: flex; flex-wrap: wrap; gap: 5px; position: relative;"> <button id="addKeyword" style="flex: 1; min-width: 70px; max-width: 70px; padding: 8px; background: #203142; color: white; border: none; border-radius: 5px; height: 40px;"> Add it </button> <button id="exportKeywords" style="flex: 1; min-width: 60px; max-width: 70px; padding: 8px; background: #203142; color: white; border: none; border-radius: 5px; height: 40px;"> Export </button> <button id="importKeywords" style="flex: 1; min-width: 60px; max-width: 70px; padding: 8px; background: #203142; color: white; border: none; border-radius: 5px; height: 40px;"> Import </button> <button id="toggleBlockKeywords" style="flex: 1; min-width: 80px; max-width: 90px; padding: 8px; background: #203142; color: white; border: none; border-radius: 5px; height: 40px; font-size: 13px; font-weight: bold;"> Unblock All </button> <button id="clearKeywords" style="flex: 1; min-width: 60px; max-width: 80px; padding: 8px; background: #203142; color: white; border: none; border-radius: 5px; height: 40px;"> Clear all </button> <button id="toggleVerifiedPosts" style="width: 242px; padding: 8px; background: #203142; color: white; border: none; border-radius: 5px; height: 40px; font-size: 13px; font-weight: bold;"> Hide verified accounts: Click to Enable </button> <button id="toggleNonVerifiedPosts" style="width: 242px; padding: 8px; background: #203142; color: white; border: none; border-radius: 5px; height: 40px; font-size: 13px; font-weight: bold;"> Hide non-verified accounts: Turn ON </button> <button id="openLanguagePopup" style="width: 80px; padding: 8px; background: #203142; color: white; border: none; border-radius: 5px; height: 40px; font-size: 13px; font-weight: bold;"> Language Filtering </button> <button id="toggleFavoriteUsers" style="width: 80px; padding: 8px; background: #203142; color: white; border: none; border-radius: 5px; height: 40px; font-size: 13px; font-weight: bold;"> Favorite Users </button> </div> <div id="searchWrapper" style="position: relative; margin-top: 10px;"> <input id="searchInput" type="text" placeholder="Search keywords or users" style=" width: 240px; height: 30px; padding: 5px; border-radius: 5px; border: none; background-color: #15202b; color: #fff;"> <span id="clearSearch" style="display: none; position: absolute; right: 92px; top: 50%; transform: translateY(-50%); color: #fff; cursor: pointer;">✖</span> </div> <div id="listLabel" style="margin-top: 10px; font-size: 14px; color: #fff;">List of Keywords</div> <ul id="keywordList" style="list-style: position: relative; inside; padding: 0; margin-top: 5px; font-size: 14px; color: #fff; max-height: 135px; overflow-y: auto; border: 1px solid #ccc; border-radius: 5px; background-color: #15202b; box-shadow: 0 2px 5px rgba(0,0,0,0.3);"></ul> `; document.body.appendChild(panel); const searchInput = document.getElementById("searchInput"); const clearSearch = document.getElementById("clearSearch"); searchInput.addEventListener("input", () => { clearSearch.style.display = searchInput.value.trim() ? "block" : "none"; updateKeywordList(); }); clearSearch.addEventListener("click", () => { searchInput.value = ""; clearSearch.style.display = "none"; updateKeywordList(); }); const lengthFilterInput = document.createElement("input"); lengthFilterInput.type = "number"; lengthFilterInput.placeholder = "Min length"; lengthFilterInput.style.width = "80px"; lengthFilterInput.style.marginTop = "10px"; panel.appendChild(lengthFilterInput); lengthFilterInput.addEventListener("change", () => { debouncedHidePosts(); }); // ===== Предотвращение перетаскивания для поля ввода ===== // const keywordInput = document.getElementById("keywordInput"); keywordInput.addEventListener("mousedown", (event) => { event.stopPropagation(); }); // ===== Перетаскивание панели ===== // let isDragging = false; let offsetX = 0; let offsetY = 0; panel.addEventListener("mousedown", (event) => { isDragging = true; offsetX = event.clientX - panel.offsetLeft; offsetY = event.clientY - panel.offsetTop; panel.style.cursor = "grabbing"; }); document.addEventListener("mousemove", (event) => { if (isDragging) { panel.style.left = event.clientX - offsetX + "px"; panel.style.top = event.clientY - offsetY + "px"; } }); document.addEventListener("mouseup", () => { isDragging = false; panel.style.cursor = "grab"; }); // ===== Создание попапа для языков ===== // const languagePopup = document.createElement("div"); languagePopup.style.display = "none"; languagePopup.style.position = "fixed"; languagePopup.style.top = "460px"; languagePopup.style.right = "65px"; languagePopup.style.transform = "translate(-52%, 7%)"; languagePopup.style.backgroundColor = "#34506c"; languagePopup.style.padding = "20px"; languagePopup.style.borderRadius = "8px"; languagePopup.style.zIndex = "10000"; languagePopup.style.width = "8%"; languagePopup.style.boxShadow = "0 0 10px rgba(0,0,0,0.5)"; languagePopup.style.fontFamily = "Arial, sans-serif"; for (const language in languageFilters) { const checkbox = document.createElement("input"); checkbox.type = "checkbox"; checkbox.id = `lang-${language}`; checkbox.name = language; const label = document.createElement("label"); label.htmlFor = `lang-${language}`; label.textContent = language.charAt(0).toUpperCase() + language.slice(1); const wrapper = document.createElement("div"); wrapper.appendChild(checkbox); wrapper.appendChild(label); languagePopup.appendChild(wrapper); } const closeButton = document.createElement("button"); closeButton.textContent = "X"; closeButton.style.position = "relative"; closeButton.style.width = "40px"; closeButton.style.height = "40px"; closeButton.style.borderRadius = "50%"; closeButton.style.backgroundColor = "#203142"; closeButton.style.color = "#fff"; closeButton.style.border = "none"; closeButton.style.display = "flex"; closeButton.style.alignItems = "center"; closeButton.style.justifyContent = "center"; closeButton.style.cursor = "pointer"; closeButton.style.marginTop = "10px"; closeButton.style.left = "82%"; closeButton.style.top = "56px"; closeButton.addEventListener("click", () => { languagePopup.style.display = "none"; }); languagePopup.appendChild(closeButton); document.body.appendChild(languagePopup); document.getElementById("openLanguagePopup").addEventListener("click", () => { languagePopup.style.display = "block"; }); const warningText = document.createElement("div"); warningText.textContent = "⚠️it may stops working"; warningText.style.color = "#ffcc00"; warningText.style.fontSize = "14px"; warningText.style.marginBottom = "10px"; warningText.style.textAlign = "end"; warningText.style.right = "38px"; warningText.style.position = "relative"; warningText.style.top = "20px"; languagePopup.appendChild(warningText); for (const language in languageFilters) { document.getElementById(`lang-${language}`).addEventListener("change", () => { updateLanguageFilter(language); }); } // ===== Стили для подсветки и скроллбара ===== // const style = document.createElement("style"); style.textContent = ` button { transition: box-shadow 0.3s, transform 0.3s; } button:hover { box-shadow: 0 0 10px rgba(255, 255, 255, 0.7); } button:active { transform: scale(0.95); box-shadow: 0 0 5px rgba(255, 255, 255, 0.7); } #keywordList::-webkit-scrollbar { width: 25px; } #keywordList::-webkit-scrollbar-thumb { background-color: #C1A5EF; border-radius: 8px; border: 3px solid #4F3E6A; height: 80px; } #keywordList::-webkit-scrollbar-thumb:hover { background-color: #C6AEFF; } #keywordList::-webkit-scrollbar-thumb:active { background-color: #B097C9; } #keywordList::-webkit-scrollbar-track { background: #455565; border-radius: 0px 0px 8px 0px; } .version-text { left: 290px; position: relative; bottom: 18px; color: #15202b; margin: 0; font-size: 14px; } #keywordInput, #searchInput { cursor: text; } #searchInput:focus { outline: none; box-shadow: 0 0 5px rgba(255, 255, 255, 0.5); } #clearSearch:hover { color: #ffcc00; } `; document.head.appendChild(style); // ===== Кнопка переключения панели FilterX ===== // let isSwitchOn = localStorage.getItem("isSwitchOn") === "true"; const toggleButton = document.createElement("div"); toggleButton.style.position = "fixed"; toggleButton.style.top = "94%"; toggleButton.style.right = "90px"; toggleButton.style.width = "192px"; toggleButton.style.display = "flex"; toggleButton.style.alignItems = "center"; toggleButton.style.gap = "10px"; toggleButton.style.zIndex = "1"; toggleButton.style.background = "#15202b"; toggleButton.style.border = "4px solid #6c7e8e"; toggleButton.style.borderRadius = "18px"; function isGrokPage() { return window.location.href.startsWith("https://x.com/i/grok"); } toggleButton.style.display = isGrokPage() ? "none" : "flex"; const toggleLabel = document.createElement("label"); toggleLabel.style.display = "inline-block"; toggleLabel.style.width = "50px"; toggleLabel.style.height = "25px"; toggleLabel.style.borderRadius = "25px"; toggleLabel.style.backgroundColor = isSwitchOn ? "#425364" : "#0d1319"; toggleLabel.style.position = "relative"; toggleLabel.style.cursor = "pointer"; toggleLabel.style.transition = "background-color 0.3s"; const toggleSwitch = document.createElement("div"); toggleSwitch.style.position = "absolute"; toggleSwitch.style.width = "21px"; toggleSwitch.style.height = "21px"; toggleSwitch.style.borderRadius = "50%"; toggleSwitch.style.backgroundColor = "#6c7e8e"; toggleSwitch.style.top = "2px"; toggleSwitch.style.left = isSwitchOn ? "calc(100% - 23px)" : "2px"; toggleSwitch.style.transition = "left 0.3s ease"; toggleSwitch.style.boxShadow = "rgb(21, 32, 43) -1px 1px 4px 1px"; function toggleSwitchState() { isSwitchOn = !isSwitchOn; localStorage.setItem("isSwitchOn", isSwitchOn.toString()); toggleSwitch.style.left = isSwitchOn ? "calc(100% - 23px)" : "2px"; toggleLabel.style.backgroundColor = isSwitchOn ? "#425364" : "#0d1319"; } toggleButton.addEventListener("click", toggleSwitchState); toggleLabel.appendChild(toggleSwitch); toggleButton.appendChild(toggleLabel); document.body.appendChild(toggleButton); const toggleText = document.createElement("span"); toggleText.textContent = "Panel FilterX"; toggleText.style.color = "#6c7e8e"; toggleText.style.fontFamily = "Arial, sans-serif"; toggleText.style.fontSize = "16px"; toggleText.style.marginLeft = "10px"; toggleText.style.fontWeight = "bold"; toggleButton.appendChild(toggleText); // ===== Управление высотой панели ===== // let isPanelVisible = localStorage.getItem("panelVisible") === "true"; function togglePanel() { if (isPanelVisible) { panel.style.height = "0px"; setTimeout(() => { panel.style.display = "none"; }, 300); } else { panel.style.display = "block"; setTimeout(() => { panel.style.height = "510px"; }, 10); } isPanelVisible = !isPanelVisible; localStorage.setItem("panelVisible", isPanelVisible.toString()); } toggleButton.addEventListener("click", togglePanel); if (isPanelVisible) { panel.style.height = "510px"; panel.style.display = "block"; } else { panel.style.height = "0px"; panel.style.display = "none"; } // ===== Элементы управления ===== // const addKeywordBtn = document.getElementById("addKeyword"); const clearKeywordsBtn = document.getElementById("clearKeywords"); const exportKeywordsBtn = document.getElementById("exportKeywords"); const importKeywordsBtn = document.getElementById("importKeywords"); const toggleVerifiedBtn = document.getElementById("toggleVerifiedPosts"); const toggleNonVerifiedBtn = document.getElementById("toggleNonVerifiedPosts"); const toggleBlockBtn = document.getElementById("toggleBlockKeywords"); const openLanguagePopupBtn = document.getElementById("openLanguagePopup"); const toggleFavoriteUsersBtn = document.getElementById("toggleFavoriteUsers"); const keywordList = document.getElementById("keywordList"); // ===== Обработчики событий ===== // addKeywordBtn.addEventListener("click", () => { const inputValue = keywordInput.value.trim(); if (inputValue) { if (isShowingFavorites && inputValue.startsWith("@")) { const username = inputValue.slice(1).toLowerCase(); if (!favoriteUsers.includes(username)) { favoriteUsers.push(username); saveFavoriteUsers(); updateKeywordList(); debouncedHidePosts(); } } else if (!isShowingFavorites && !hiddenKeywords.includes(inputValue)) { hiddenKeywords.push(inputValue); saveKeywords(); updateKeywordList(); debouncedHidePosts(); } keywordInput.value = ""; } }); toggleNonVerifiedBtn.textContent = `Hide non-verified accounts: ${hideNonVerifiedAccounts ? "Turn OFF" : "Turn ON"}`; toggleNonVerifiedBtn.addEventListener("click", () => { hideNonVerifiedAccounts = !hideNonVerifiedAccounts; localStorage.setItem("hideNonVerifiedAccounts", JSON.stringify(hideNonVerifiedAccounts)); toggleNonVerifiedBtn.textContent = `Hide non-verified accounts: ${hideNonVerifiedAccounts ? "Turn OFF" : "Turn ON"}`; hidePosts(); }); clearKeywordsBtn.addEventListener("click", () => { if (confirm("Are you sure you want to clear the list?")) { if (isShowingFavorites) { favoriteUsers = []; saveFavoriteUsers(); } else { hiddenKeywords = []; unblockedKeywords = []; saveKeywords(); saveUnblockedKeywords(); } updateKeywordList(); hidePosts(); } }); exportKeywordsBtn.addEventListener("click", () => { const data = isShowingFavorites ? favoriteUsers : hiddenKeywords; const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(data))}`; const downloadAnchor = document.createElement("a"); downloadAnchor.setAttribute("href", dataStr); downloadAnchor.setAttribute("download", isShowingFavorites ? "favorite_users.json" : "hidden_keywords.json"); document.body.appendChild(downloadAnchor); downloadAnchor.click(); document.body.removeChild(downloadAnchor); }); importKeywordsBtn.addEventListener("click", () => { const input = document.createElement("input"); input.type = "file"; input.accept = "application/json"; input.addEventListener("change", (event) => { const file = event.target.files[0]; const reader = new FileReader(); reader.onload = () => { try { const importedData = JSON.parse(reader.result); if (Array.isArray(importedData)) { if (isShowingFavorites) { favoriteUsers = [...new Set([...favoriteUsers, ...importedData.map(u => u.startsWith("@") ? u.slice(1).toLowerCase() : u.toLowerCase())])]; saveFavoriteUsers(); } else { hiddenKeywords = [...new Set([...hiddenKeywords, ...importedData])]; saveKeywords(); } updateKeywordList(); hidePosts(); } else { alert("Incorrect file format."); } } catch (e) { alert("Error reading the file."); } }; reader.readAsText(file); }); input.click(); }); toggleBlockBtn.addEventListener("click", () => { if (!isShowingFavorites) { if (hiddenKeywords.length > 0) { unblockedKeywords = [...hiddenKeywords]; hiddenKeywords = []; toggleBlockBtn.textContent = "Block All"; } else { hiddenKeywords = [...unblockedKeywords]; unblockedKeywords = []; toggleBlockBtn.textContent = "Unblock All"; } saveKeywords(); saveUnblockedKeywords(); updateKeywordList(); hidePosts(); } }); toggleBlockBtn.textContent = hiddenKeywords.length > 0 ? "Unblock All" : "Block All"; toggleVerifiedBtn.addEventListener("click", () => { hideVerifiedAccounts = !hideVerifiedAccounts; toggleVerifiedBtn.textContent = `Hide verified accounts: ${hideVerifiedAccounts ? "Turn OFF" : "Turn ON"}`; hidePosts(); }); toggleFavoriteUsersBtn.addEventListener("click", () => { isShowingFavorites = !isShowingFavorites; toggleFavoriteUsersBtn.textContent = isShowingFavorites ? "Keywords" : "Favorite Users"; keywordInput.placeholder = isShowingFavorites ? "Enter @username" : "Enter the word"; updateKeywordList(); }); openLanguagePopupBtn.addEventListener("click", () => { const panelRect = panel.getBoundingClientRect(); languagePopup.style.top = `${panelRect.top - 320}px`; languagePopup.style.left = `${panelRect.right - 10}px`; languagePopup.style.display = "block"; }); // ===== Обновление списка ключевых слов или избранных пользователей ===== // function updateKeywordList() { const list = document.getElementById("keywordList"); const label = document.getElementById("listLabel"); const searchInput = document.getElementById("searchInput"); const searchQuery = searchInput ? searchInput.value.trim().toLowerCase() : ""; list.innerHTML = ""; if (isShowingFavorites) { label.textContent = "Favorite Users"; const filteredUsers = favoriteUsers.filter(user => user.toLowerCase().includes(searchQuery)); if (filteredUsers.length === 0) { list.textContent = searchQuery ? "No matches found" : "Нет"; } else { filteredUsers.forEach((user, index) => { const listItem = document.createElement("li"); listItem.textContent = `@${user}`; listItem.style.marginBottom = "5px"; const deleteButton = document.createElement("button"); deleteButton.textContent = "❌"; deleteButton.style.marginLeft = "10px"; deleteButton.style.backgroundColor = "#f44336"; deleteButton.style.color = "#fff"; deleteButton.style.border = "none"; deleteButton.style.borderRadius = "3px"; deleteButton.style.cursor = "pointer"; deleteButton.addEventListener("click", () => { favoriteUsers.splice(favoriteUsers.indexOf(user), 1); saveFavoriteUsers(); updateKeywordList(); hidePosts(); }); listItem.appendChild(deleteButton); list.appendChild(listItem); }); } } else { label.textContent = "List of Keywords"; const filteredKeywords = hiddenKeywords.filter(keyword => keyword.toLowerCase().includes(searchQuery)); if (filteredKeywords.length === 0) { list.textContent = searchQuery ? "No matches found" : "Нет"; } else { filteredKeywords.forEach((keyword, index) => { const listItem = document.createElement("li"); listItem.textContent = keyword; listItem.style.marginBottom = "5px"; const deleteButton = document.createElement("button"); deleteButton.textContent = "❌"; deleteButton.style.marginLeft = "10px"; deleteButton.style.backgroundColor = "#f44336"; deleteButton.style.color = "#fff"; deleteButton.style.border = "none"; deleteButton.style.borderRadius = "3px"; deleteButton.style.cursor = "pointer"; deleteButton.addEventListener("click", () => { hiddenKeywords.splice(hiddenKeywords.indexOf(keyword), 1); saveKeywords(); updateKeywordList(); hidePosts(); }); listItem.appendChild(deleteButton); list.appendChild(listItem); }); } } } // ===== Автоматическое скрытие панели при открытии фото ===== // function isPhotoViewerOpen() { const currentUrl = window.location.href; const isPhotoOpen = /\/photo\/\d+$/.test(currentUrl); const photoModal = document.querySelector('div[aria-label="Image"]') || document.querySelector('div[data-testid="imageViewer"]'); return isPhotoOpen || !!photoModal; } function updateToggleButtonVisibility() { toggleButton.style.display = isGrokPage() ? "none" : "flex"; } function toggleElementsVisibility() { const isPhotoOpen = isPhotoViewerOpen(); if (isPhotoOpen || isGrokPage()) { panel.style.display = "none"; toggleButton.style.display = "none"; } else { if (isPanelVisible) { panel.style.display = "block"; panel.style.height = "510px"; } toggleButton.style.display = "flex"; } } // ===== Наблюдение за изменениями DOM ===== // const observer = new MutationObserver(() => { debouncedHidePosts(); }); observer.observe(document.body, { childList: true, subtree: true }); toggleElementsVisibility(); window.addEventListener("popstate", () => { updateToggleButtonVisibility(); toggleElementsVisibility(); }); const urlObserver = new MutationObserver(() => { updateToggleButtonVisibility(); toggleElementsVisibility(); }); urlObserver.observe(document.body, { childList: true, subtree: true }); document.addEventListener("click", (event) => { if (event.target.closest('div[aria-label="Close"]') || event.target.closest('div[data-testid="imageViewer-close"]')) { setTimeout(toggleElementsVisibility, 100); } }); // ===== Инициализация ===== // updateKeywordList(); hidePosts(); })();