Panel Control XFilter 2.4.53 (c) tapeavion

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

目前為 2025-03-31 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Panel Control XFilter 2.4.53 (c) tapeavion
// @namespace    http://tampermonkey.net/
// @version      2.4.53
// @description  Hide posts by keywords with the dashboard and hide posts from verified accounts
// @author       gullampis810
// @match         https://blank.org/*
// @match        https://x.com/*
// @match        https://x.com/i/grok*
// @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àáâãçéêíóôõúü]/,
        persian: /[\u0600-\u06FF\u0750-\u077F]/,
        arabic: /[\u0600-\u06FF]/,
        hebrew: /[\u0590-\u05FF]/,
        thai: /[\u0E00-\u0E7F]/
    };
    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);
            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 (isFavoriteUser) {
                article.style.height = "";
                article.style.opacity = "1";
                article.style.display = "";
                return;
            }

            if (shouldHideVerified || shouldHideNonVerified || shouldHideByLanguage || shouldHideByKeyword) {
                if (article.style.display !== "none") {
                    article.style.transition = "height 0.5s ease, opacity 0.5s ease";
                    article.style.height = article.scrollHeight + "px";
                    article.style.opacity = "1";
                    setTimeout(() => {
                        article.style.height = "0";
                        article.style.opacity = "0";
                    }, 10);
                    article.addEventListener("transitionend", () => {
                        if (article.style.height === "0px") article.style.display = "none";
                    }, { once: true });
                }
            } else {
                if (article.style.display === "none") {
                    article.style.display = "";
                    article.style.transition = "height 0.5s ease, opacity 0.5s ease";
                    article.style.height = "0";
                    article.style.opacity = "0";
                    setTimeout(() => {
                        article.style.height = article.scrollHeight + "px";
                        article.style.opacity = "1";
                    }, 10);
                    article.addEventListener("transitionend", () => {
                        if (article.style.height !== "0px") article.style.height = "";
                    }, { once: true });
                }
            }
        });
    }

    // ===== Создание основной панели ===== //
    const panel = document.createElement("div");
    panel.style.position = "fixed";
    panel.style.bottom = "62px";
    panel.style.right = "180px";
    panel.style.width = "335px";
    panel.style.height = "525px";
    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.53</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;">
        <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 Disable</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="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 counterPanel = document.createElement("div");
    counterPanel.style.marginTop = "10px";
    counterPanel.style.padding = "8px";
    counterPanel.style.border = "2px solid #34506c";
    counterPanel.style.borderRadius = "5px";
    counterPanel.style.backgroundColor = "transparent";
    counterPanel.innerHTML = `
        <div style="font-size: 14px; color: #fff;">Favorite Users: <span id="favoriteUsersCount">${favoriteUsers.length}</span></div>
        <div style="font-size: 14px; color: #fff; margin-top: 5px;">Blocked Keywords: <span id="blockedKeywordsCount">${hiddenKeywords.length}</span></div>
    `;
    panel.appendChild(counterPanel);

    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 = panel.querySelector("#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 wrapper = document.createElement("div");
        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);
        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);

    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 { cursor: text; }
        article { overflow: hidden; }
    `;
    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";
    toggleButton.style.display = window.location.href.startsWith("https://x.com/i/grok") ? "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);

    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);
    document.body.appendChild(toggleButton);

    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 = "525px", 10);
        }
        isPanelVisible = !isPanelVisible;
        localStorage.setItem("panelVisible", isPanelVisible.toString());
    }

    toggleButton.addEventListener("click", togglePanel);
    if (isPanelVisible) {
        panel.style.height = "525px";
        panel.style.display = "block";
    } else {
        panel.style.height = "0px";
        panel.style.display = "none";
    }

    // ===== Элементы управления ===== //
    const addKeywordBtn = panel.querySelector("#addKeyword");
    const clearKeywordsBtn = panel.querySelector("#clearKeywords");
    const exportKeywordsBtn = panel.querySelector("#exportKeywords");
    const importKeywordsBtn = panel.querySelector("#importKeywords");
    const toggleVerifiedBtn = panel.querySelector("#toggleVerifiedPosts");
    const toggleNonVerifiedBtn = panel.querySelector("#toggleNonVerifiedPosts");
    const toggleBlockBtn = panel.querySelector("#toggleBlockKeywords");
    const openLanguagePopupBtn = panel.querySelector("#openLanguagePopup");
    const toggleFavoriteUsersBtn = panel.querySelector("#toggleFavoriteUsers");
    const keywordList = panel.querySelector("#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.textContent = hiddenKeywords.length > 0 ? "Unblock All" : "Block All";
    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();
        }
    });

    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 = keywordList;
        const label = panel.querySelector("#listLabel");
        list.innerHTML = "";

        if (isShowingFavorites) {
            label.textContent = "Favorite Users";
            favoriteUsers.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(index, 1);
                    saveFavoriteUsers();
                    updateKeywordList();
                    hidePosts();
                });
                listItem.appendChild(deleteButton);
                list.appendChild(listItem);
            });
            if (favoriteUsers.length === 0) list.textContent = "Нет";
        } else {
            label.textContent = "List of Keywords";
            hiddenKeywords.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(index, 1);
                    saveKeywords();
                    updateKeywordList();
                    hidePosts();
                });
                listItem.appendChild(deleteButton);
                list.appendChild(listItem);
            });
            if (hiddenKeywords.length === 0) list.textContent = "Нет";
        }
        updateCounters();
    }

    function updateCounters() {
        panel.querySelector("#favoriteUsersCount").textContent = favoriteUsers.length;
        panel.querySelector("#blockedKeywordsCount").textContent = hiddenKeywords.length;
    }

    function debounce(func, wait) {
        let timeout;
        return function (...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }

    const debouncedHidePosts = debounce(hidePosts, 200);

    const observer = new MutationObserver(() => debouncedHidePosts());
    observer.observe(document.body, { childList: true, subtree: true });

    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 isGrokPage() {
        return window.location.href.startsWith("https://x.com/i/grok");
    }

    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 = "525px";
            }
            toggleButton.style.display = "flex";
        }
    }

    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();
})();