Panel Control XFilter 2.4.56 (c) tapeavion

Hide posts by keywords with the dashboard and hide posts from verified accounts

// ==UserScript==
// @name         Panel Control XFilter 2.4.56 (c) tapeavion
// @namespace    http://tampermonkey.net/
// @version      2.4.56
// @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.56</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;">
            
            <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>
        <button id="addKeyword" style="flex: 1;min-width: 79px;max-width: 70px;padding: 8px;background: #203142;color: white;border: none;border-radius: 5px;height: 40px;position: relative;bottom: 50px;left: 0px;">
                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;position: relative;bottom: 180px;left: 256px;">
                Favorite Users
            </button>
        </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();
})();