Panel Control XFilter 2.4.3 (c) tapeavion

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

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

您需要先安裝使用者腳本管理器擴展,如 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.3 (c) tapeavion
// @namespace    http://tampermonkey.net/
// @version      2.4.3
// @description  Hide posts by keywords with the dashboard and hide posts from verified accounts
// @author       gullampis810
// @match        https://x.com/*
// @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";
    console.log("STORAGE_KEY =", STORAGE_KEY);
    let hiddenKeywords = JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
    let hideVerifiedAccounts = false; // Скрывать подтвержденные аккаунты
    let hideNonVerifiedAccounts = JSON.parse(localStorage.getItem("hideNonVerifiedAccounts")) || 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() {
      console.log("saveKeywords called with", ...arguments);

      localStorage.setItem(STORAGE_KEY, JSON.stringify(hiddenKeywords));
    }

    // ===== Функция для обновления отображения по языкам ===== //
    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; // Возвращаем true, если текст на этом языке
        }
      }
      return false;
    }

  // ===== Функция Скрытия постов ===== //
function hidePosts() {
    document.querySelectorAll("article").forEach((article) => {
        const textContent = article.innerText.toLowerCase();
        const isVerifiedAccount = article.querySelector('[data-testid="icon-verified"]');

        const matchesKeyword = hiddenKeywords.some((keyword) => {
            try {
                return new RegExp(keyword, "i").test(textContent);
            } catch (e) {
                return textContent.includes(keyword.toLowerCase()); // Фallback на обычное совпадение
            }
        });

        // Проверяем, нужно ли скрывать пост
        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 = ""; // Показываем пост, если ни одно условие не выполнено
        }
    });
}

    // ===== Создание панели управления ===== //
    const panel = document.createElement("div");
    panel.style.position = "fixed";
    panel.style.bottom = "62px";
    panel.style.right = "180px";
    panel.style.width = "335px";
    panel.style.height = "310px";
    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>
     <input id="keywordInput" type="text" placeholder="Enter the word" 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="clearKeywords" style="flex: 1; min-width: 60px; max-width: 80px; padding: 8px; background: #203142; color: white; border: none; border-radius: 5px; height: 40px; bottom: 0px; position: relative; left: 1px;">
             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; display: flex; align-content: center; flex-wrap: wrap; padding: 8px; background: #203142; color: white; border: none; border-radius: 5px; height: 40px; font-size: 13px; font-weight: bold;">
             Language Filtering
         </button>
     </div>

     <ul id="keywordList" style="list-style: position: relative; inside; padding: 0; margin-top: 10px; font-size: 14px; color: #fff;"></ul>
`;



  document.body.appendChild(panel);
  console.log("panel =", panel);

  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", () => {
    const minLength = parseInt(lengthFilterInput.value) || 0;
    debouncedHidePosts();
  });


  // ===== Перетаскивание панели ===== //
  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";
  });

    document.body.appendChild(panel);
    console.log("panel =", panel);

    // Создаем попап для выбора языков
    const languagePopup = document.createElement("div");
    console.log("languagePopup =", languagePopup);
    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 = "rgb(52, 80, 108)";
    languagePopup.style.padding = "20px";
    languagePopup.style.borderRadius = "8px";
    languagePopup.style.zIndex = "10000";
    languagePopup.style.width = "8%";
    languagePopup.style.boxShadow = "rgba(0, 0, 0, 0.5) 0px 0px 10px";
    languagePopup.style.fontFamily = "Arial, sans-serif"; // Устанавливаем шрифт Arial

    // Добавляем чекбоксы для каждого языка
    for (const language in languageFilters) {
      const checkbox = document.createElement("input");
      console.log("checkbox =", checkbox);
      checkbox.type = "checkbox";
      checkbox.id = `lang-${language}`;
      checkbox.name = language;

      const label = document.createElement("label");
      console.log("label =", label);
      label.htmlFor = `lang-${language}`;
      label.textContent = language.charAt(0).toUpperCase() + language.slice(1);

      const wrapper = document.createElement("div");
      console.log("wrapper =", wrapper);
      wrapper.appendChild(checkbox);
      wrapper.appendChild(label);

      languagePopup.appendChild(wrapper);
    }

    // Добавляем кнопку закрытия попапа
    const closeButton = document.createElement("button");
    console.log("closeButton =", closeButton);
    closeButton.textContent = "X";

    // Стили для круглой кнопки
    closeButton.style.position = "relative";
    closeButton.style.width = "40px";
    closeButton.style.height = "40px";
    closeButton.style.borderRadius = "50%";
    closeButton.style.backgroundColor = "rgb(32, 49, 66)";
    closeButton.style.color = "rgb(255, 255, 255)";
    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.boxShadow = "rgba(0, 0, 0, 0.1) 0px 4px 6px";
    closeButton.style.transition = "background-color 0.3s";
    closeButton.style.fontFamily = "Arial, sans-serif";
    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");
    console.log("warningText =", warningText);
    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"; // Сдвигаем вправо на 50px
    warningText.style.position = "relative"; // Устанавливаем позиционирование
    warningText.style.top = "20px"; // Сдвигаем вниз на 15px

    languagePopup.appendChild(warningText);

    // Обработчики для чекбоксов
    for (const language in languageFilters) {
      document
        .getElementById(`lang-${language}`)
        .addEventListener("change", (event) => {
          updateLanguageFilter(language);
        });
    }



    // Стили для подсветки
    const style = document.createElement("style");
    console.log("style =", 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);
      }

::-webkit-scrollbar {
  width: 25px; /* Ширина скроллбара */
}

::-webkit-scrollbar-thumb {
  background-color: #C1A5EF; /* Цвет бегунка */
  border-radius: 8px; /* Скругление бегунка */
  border: 3px solid #4F3E6A; /* Внутренний отступ (цвет трека) */
  height: 80px; /* Высота бегунка */
}

::-webkit-scrollbar-thumb:hover {
  background-color: #C6AEFF; /* Цвет бегунка при наведении */
}

::-webkit-scrollbar-thumb:active {
  background-color: #B097C9; /* Цвет бегунка при активном состоянии */
}

::-webkit-scrollbar-track {
  background:rgba(69, 85, 101, 0); /* Цвет трека */
  border-radius: 0px 0px 8px 0px; /* Скругление только нижнего правого угла */
}

::-webkit-scrollbar-track:hover {
  background-color:rgba(69, 85, 101, 0); /* Цвет трека при наведении */
}

::-webkit-scrollbar-track:active {
  background-color:rgba(69, 85, 101, 0); /* Цвет трека при активном состоянии */
}


  `;
    document.head.appendChild(style);
// скроллбар for Twitter X com //

    // ======== Кнопка iOS-переключатель Panel FilterX ========= //

    // Проверяем сохраненное состояние переключателя в localStorage
    let isSwitchOn = localStorage.getItem("isSwitchOff") === "true"; // Начальное состояние переключателя из localStorage

    // Создание элементов панели
    const toggleButton = document.createElement("div");
    console.log("toggleButton =", toggleButton);
    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.boxSizing = "border-box";

    // Создаем label для переключателя
    const toggleLabel = document.createElement("label");
    console.log("toggleLabel =", toggleLabel);
    toggleLabel.style.display = "inline-block";
    toggleLabel.style.width = "50px";
    toggleLabel.style.height = "25px";
    toggleLabel.style.borderRadius = "25px";
    toggleLabel.style.backgroundColor = "#0d1319";
    toggleLabel.style.position = "relative";
    toggleLabel.style.cursor = "pointer";
    toggleLabel.style.transition = "background-color 0.3s";

    // Создаем кружок переключателя
    const toggleSwitch = document.createElement("div");
    console.log("toggleSwitch =", toggleSwitch);
    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";

    // Устанавливаем начальное состояние фона
    toggleLabel.style.backgroundColor = isSwitchOn ? "#425364" : "#0d1319";

    // Функция для изменения состояния переключателя
    function toggleSwitchState() {
      isSwitchOn = !isSwitchOn;
      localStorage.setItem("isSwitchOn", isSwitchOn.toString()); // Сохраняем состояние в localStorage (как строку)

      // Обновляем стиль переключателя
      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");
    console.log("toggleText =", toggleText);
    toggleText.style.position = "relative";
    toggleText.style.right = "5px";
    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") === "truefalse"; // По умолчанию скрыта, если в localStorage не сохранено другое значение

    function togglePanel() {
      if (isPanelVisible) {
        panel.style.height = "0px"; // Сворачиваем панель
        setTimeout(() => {
          panel.style.display = "none"; // Скрываем панель после анимации
        }, 300);
      } else {
        panel.style.display = "block"; // Показываем панель
        setTimeout(() => {
          panel.style.height = "310px"; // Разворачиваем панель
        }, 10);
      }

      isPanelVisible = !isPanelVisible; // Переключаем состояние
      localStorage.setItem("panelVisible", isPanelVisible.toString()); // Сохраняем состояние
    }

    toggleButton.addEventListener("click", togglePanel);

    // При загрузке восстанавливаем состояние панели
    if (isPanelVisible) {
      panel.style.height = "310px"; // Разворачиваем панель
      panel.style.display = "block";
    } else {
      panel.style.height = "0px"; // Сворачиваем панель
      panel.style.display = "none";
    }

    const keywordInput = document.getElementById("keywordInput");
  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 openLanguagePopupBtn = document.getElementById("openLanguagePopup");
  const keywordList = document.getElementById("keywordList");


    // ===== Обработчики событий ===== //
    addKeywordBtn.addEventListener("click", () => {
      const keyword = keywordInput.value.trim();
      if (keyword && !hiddenKeywords.includes(keyword)) {
        hiddenKeywords.push(keyword);
        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(); // Перепроверяем все посты с новыми настройками
});



    document.getElementById("clearKeywords").addEventListener("click", () => {
      if (confirm("Are you sure you want to clear the list?")) {
        hiddenKeywords = [];
        saveKeywords();
        updateKeywordList();
        hidePosts();
      }
    });

    document.getElementById("exportKeywords").addEventListener("click", () => {
      const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(
        JSON.stringify(hiddenKeywords)
      )}`;
      console.log('dataStr =', dataStr); // Лог вне строки
      const downloadAnchor = document.createElement("a");
      console.log("downloadAnchor =", downloadAnchor);
      downloadAnchor.setAttribute("href", dataStr);
      downloadAnchor.setAttribute("download", "hidden_keywords.json");
      document.body.appendChild(downloadAnchor);
      downloadAnchor.click();
      document.body.removeChild(downloadAnchor);
    });

    document.getElementById("importKeywords").addEventListener("click", () => {
      const input = document.createElement("input");
      console.log("input =", input);
      input.type = "file";
      input.accept = "application/json";
      input.addEventListener("change", (event) => {
        const file = event.target.files[0];
        console.log("file =", file);
        const reader = new FileReader();
        console.log("reader =", reader);
        reader.onload = () => {
          try {
            const importedKeywords = JSON.parse(reader.result);
            console.log("importedKeywords =", importedKeywords);
            if (Array.isArray(importedKeywords)) {
              hiddenKeywords = [
                ...new Set([...hiddenKeywords, ...importedKeywords]),
              ];
              saveKeywords();
              updateKeywordList();
              hidePosts();
            } else {
              alert("Incorrect file format.");
            }
          } catch (e) {
            alert("Error reading the file.");
          }
        };
        reader.readAsText(file);
      });
      input.click();
    });


    document.getElementById("openLanguagePopup").addEventListener("click", () => {
      const panelRect = panel.getBoundingClientRect();
      languagePopup.style.top = `${panelRect.top - 320}px`; // Чуть выше панели
      languagePopup.style.left = `${panelRect.right - 10}px`; // Справа от панели
      languagePopup.style.display = "block";
    });


  // Переменная для отслеживания клика на кнопку "Перевести пост"
  let isTranslateButtonClicked = false;

  // Функция для отслеживания клика по кнопке "Перевести пост"
  function handleTranslateButtonClick(event) {
    isTranslateButtonClicked = true;
    setTimeout(() => { isTranslateButtonClicked = false; }, 500); // Сбросить флаг через 500 мс
  }

  // ===== Наблюдатель за кнопками "Перевести пост" ===== //
  function observeTranslateButton() {
    document.querySelectorAll('button[aria-expanded="false"]').forEach(button => {
      button.removeEventListener('click', handleTranslateButtonClick); // Убираем старые обработчики
      button.addEventListener('click', handleTranslateButtonClick); // Добавляем новый обработчик
    });
  }



    // ===== Кнопка для включения/выключения скрытия подтвержденных аккаунтов ===== //
    document
      .getElementById("toggleVerifiedPosts")
      .addEventListener("click", () => {
        hideVerifiedAccounts = !hideVerifiedAccounts;
        document.getElementById("toggleVerifiedPosts").textContent =
          `Hide verified accounts: ${
            hideVerifiedAccounts ? "Turn OFF" : "Turn ON"
          }`;
        hidePosts(); // Перепроверка всех постов с новыми настройками
      });

    // ===== Функция для применения кастомного скроллбара ===== //
    function applyCustomScrollbar() {
      const style = document.createElement("style");
      style.id = "custom-scrollbar-style";
      style.innerHTML = `
        #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; /* Скругление только нижнего правого угла */
}

#keywordList::-webkit-scrollbar-track:hover {
  background-color: #455565; /* Цвет трека при наведении */
}

#keywordList::-webkit-scrollbar-track:active {
  background-color: #455565; /* Цвет трека при активном состоянии */
}
      `;
      if (!document.getElementById("custom-scrollbar-style")) {
        document.head.appendChild(style);
      }
    }

    // ===== Функция для наблюдения за изменениями в списке ===== //
    function observeKeywordList() {
      const list = document.getElementById("keywordList");
      if (!list) return;

      const observer = new MutationObserver(() => {
        console.log(
          "Обнаружены изменения в списке ключевых слов, обновляем стили...",
        );
        applyCustomScrollbar();
      });

      observer.observe(list, { childList: true, subtree: true });
    }

    // ===== Обновление списка ключевых слов ===== //
    function updateKeywordList() {
      const list = document.getElementById("keywordList");
      console.log("list =", list);
      list.style.listStyle = "inside";
      list.style.padding = "0px 10px 0px 0px";
      list.style.marginTop = "10px";
      list.style.fontSize = "14px";
      list.style.color = "rgb(255, 255, 255)";
      list.style.maxHeight = "135px";
      list.style.overflowY = "auto";
      list.style.border = "1px solid rgb(204, 204, 204)";
      list.style.borderRadius = "5px";
      list.style.backgroundColor = "rgb(21, 32, 43)";
      list.style.boxShadow = "rgba(0, 0, 0, 0.3) 0px 2px 5px";
      list.style.position = "relative";
      list.style.width = "315px";
      list.innerHTML = "";

      hiddenKeywords.forEach((keyword, index) => {
        const listItem = document.createElement("li");
        console.log("listItem =", listItem);
        listItem.textContent = keyword;
        listItem.style.marginBottom = "5px";

        const deleteButton = document.createElement("button");
        console.log("deleteButton =", deleteButton);
        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 = "Нет";
      }

      applyCustomScrollbar(); // Применяем кастомный скроллбар
      observeKeywordList(); // Повторно запускаем наблюдатель
    }

    // Запуск кастомного скролла и наблюдателя при загрузке страницы
    applyCustomScrollbar();
    observeKeywordList();

    // ===== Инициализация ===== //
    updateKeywordList(); // Обновление списка при загрузке страницы
    hidePosts();

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

    const debouncedHidePosts = debounce(hidePosts, 200); // 200 мс задержки


    // ===== Наблюдатель для динамического контента ===== //
    // Используем debounced версию
  const observer = new MutationObserver(() => {
    debouncedHidePosts();
    observeTranslateButton();
  });

  observer.observe(document.body, { childList: true, subtree: true });









// ==== автоматического скрытия панели управления и кнопки переключателя (при открытии просмотра фото  ======= //



        // Функция для проверки, открыто ли модальное окно с фото
function isPhotoViewerOpen() {
    // Проверяем URL на наличие /photo/
    const currentUrl = window.location.href;
    const isPhotoOpen = /\/photo\/\d+$/.test(currentUrl);

    // Дополнительно проверяем наличие модального окна (если URL-метод ненадежен)
    const photoModal = document.querySelector('div[aria-label="Image"]') || document.querySelector('div[data-testid="imageViewer"]');
    return isPhotoOpen || !!photoModal;
}

// Функция для скрытия/показа панели и кнопки
function toggleElementsVisibility() {
    const isPhotoOpen = isPhotoViewerOpen();
    if (isPhotoOpen) {
        // Скрываем панель и кнопку
        panel.style.display = "none";
        toggleButton.style.display = "none";
    } else {
        // Восстанавливаем видимость, если панель должна быть видима
        if (isPanelVisible) {
            panel.style.display = "block";
            panel.style.height = "310px";
        }
        toggleButton.style.display = "flex"; // Возвращаем кнопку
    }
}

// Начальная проверка при загрузке
toggleElementsVisibility();

// Отслеживание изменений URL через popstate (для навигации вперед/назад)
window.addEventListener("popstate", () => {
    toggleElementsVisibility();
});

// Отслеживание изменений в DOM (для динамической загрузки контента)
const urlObserver = new MutationObserver(() => {
    toggleElementsVisibility();
});

// Наблюдаем за изменениями в document.body
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); // Небольшая задержка, чтобы дождаться закрытия модального окна
    }
});
  })();