Greasy Fork

Greasy Fork is available in English.

Twitter (X) 片思い表示

Twitter (X) で片思いフォロー中のアカウントのみを表示できます。また、両思いフォロー中のアカウントは強調表示できます。

当前为 2024-03-15 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Twitter (X) 片思い表示
// @namespace    https://kuds.win/
// @version      1.1
// @description  Twitter (X) で片思いフォロー中のアカウントのみを表示できます。また、両思いフォロー中のアカウントは強調表示できます。
// @author       KUDs
// @match        https://twitter.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=twitter.com
// @grant        none
// @license      GPL-3.0-or-later
// ==/UserScript==

(function () {
  "use strict";

  // デフォルトは非表示&ハイライト無し
  let isHiding = false;
  let isHighlighting = false;

  // ボタン作成時に共通スタイル適用
  function createStyledButton(text, clickHandler) {
    const button = document.createElement("button");
    button.textContent = text;

    // 共通スタイル
    Object.assign(button.style, {
      border: "none",
      borderRadius: "20px",
      padding: "10px 20px",
      marginTop: "10px",
      cursor: "pointer",
      transition: "filter 0.3s, transform 0.3s",
    });

    button.addEventListener("mouseover", () => {
      Object.assign(button.style, {
        filter: "brightness(1.25)",
        transform: "scale(1.05)",
      });
    });

    button.addEventListener("mouseout", () => {
      Object.assign(button.style, {
        filter: "brightness(1)",
        transform: "scale(1)",
      });
    });

    button.addEventListener("click", clickHandler);
    return button;
  }

  // hide button click ハンドラ
  function handleHideButtonClick() {
    isHiding = !isHiding;
    hideButton.textContent = isHiding ? "片思い ONLY: ON" : "片思い ONLY: OFF";
    hideButton.style.backgroundColor = isHiding ? "skyblue" : "gray";
    updateDOM();
  }

  // highlight button click ハンドラ
  function handleHighlightButtonClick() {
    isHighlighting = !isHighlighting;
    highlightButton.textContent = isHighlighting
      ? "両思い HIGHLIGHT: ON"
      : "両思い HIGHLIGHT: OFF";
    highlightButton.style.backgroundColor = isHighlighting ? "pink" : "gray";
    updateDOM();
  }

  const hideButton = createStyledButton(
    "片思い ONLY: OFF",
    handleHideButtonClick
  );
  hideButton.style.backgroundColor = "gray";

  const highlightButton = createStyledButton(
    "両思い HIGHLIGHT: OFF",
    handleHighlightButtonClick
  );
  highlightButton.style.backgroundColor = "gray";
  highlightButton.style.display = "none";

  // ボタン配置の初期化
  function initializeButtons() {
    const targetNavElement = document.querySelector(
      '[data-testid="SideNav_NewTweet_Button"]'
    );
    if (targetNavElement) {
      const parentNavElement = targetNavElement.parentNode;
      if (parentNavElement && !hideButton.parentNode) {
        parentNavElement.appendChild(hideButton);
        parentNavElement.appendChild(highlightButton);
      }
    }
  }

  // UserCellの表示/非表示の更新
  function updateUserCellVisibility(node) {
    if (
      node.textContent.includes("フォローされています") ||
      node.textContent.includes("両思いです♡")
    ) {
      node.style.display = isHiding ? "none" : "";
    }
  }

  // userFollowIndicatorの表示の更新
  function updateFollowIndicator(node) {
    if (
      node.textContent.trim() === "フォローされています" ||
      node.textContent.trim() === "両思いです♡"
    ) {
      const spanElement = node.querySelector("span");
      if (isHighlighting) {
        node.style.backgroundColor = "pink";
        spanElement.textContent = "両思いです♡";
      } else {
        node.style.backgroundColor = "";
        spanElement.textContent = "フォローされています";
      }
    }
  }

  // DOMのアップデート
  function updateDOM(mutationsList = []) {
    // 既存のDOMノードに対する更新を追加
    const userCells = document.querySelectorAll('div[data-testid="UserCell"]');
    userCells.forEach(updateUserCellVisibility);

    const userFollowIndicators = document.querySelectorAll(
      '[data-testid="userFollowIndicator"]'
    );
    userFollowIndicators.forEach(updateFollowIndicator);

    for (let mutation of mutationsList) {
      if (mutation.addedNodes && mutation.addedNodes.length > 0) {
        mutation.addedNodes.forEach((node) => {
          // SideNavへのボタン追加
          if (
            node.matches &&
            node.matches('[data-testid="SideNav_NewTweet_Button"]')
          ) {
            initializeButtons();
          }

          // UserCellとuserFollowIndicatorの処理
          if (node.matches && node.matches('div[data-testid="UserCell"]')) {
            updateUserCellVisibility(node);
          }
          if (
            node.matches &&
            node.matches('[data-testid="userFollowIndicator"]')
          ) {
            updateFollowIndicator(node);
          }
        });
      }
    }

    // highlightButtonの表示/非表示
    highlightButton.style.display = isHiding ? "none" : "";

    // ボタン配置を再確認
    initializeButtons();
  }

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

  // スクリプトの最後で初期化関数を実行
  initializeButtons();
})();