Hide For You (schedule)

Hides the 'For You' tab and auto-switches to 'Following' on X.com during configured time windows

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Hide For You (schedule)
// @namespace    f_d
// @version      1.2
// @description  Hides the 'For You' tab and auto-switches to 'Following' on X.com during configured time windows
// @author       GPT-5
// @match        https://x.com/*
// @match        https://twitter.com/*
// @icon         https://abs.twimg.com/favicons/twitter.ico
// @grant        none
// ==/UserScript==

/*** ──────────────────────────────────────────────────────────────
 * SCHEDULE CONFIG
 *
 * Time is local browser time, 24h "HH:MM".
 * Days: 0=Sun, 1=Mon, ..., 6=Sat
 * The filter is ACTIVE if the current time falls into ANY range
 * listed for the current day. "default" applies when a day has no
 * explicit entry. Overnight ranges are supported (e.g. 22:00–03:00).
 *
 * My Settings:
 *   - Mon–Fri: block active all day
 *   - Sat & Sun: active until 16:00
 * ───────────────────────────────────────────────────────────────*/
const SCHEDULE = {
  // Sunday
  0: [{ start: "00:00", end: "16:00" }],
  // Monday–Friday
  1: [{ start: "00:00", end: "24:00" }],
  2: [{ start: "00:00", end: "24:00" }],
  3: [{ start: "00:00", end: "24:00" }],
  4: [{ start: "00:00", end: "24:00" }],
  5: [{ start: "00:00", end: "24:00" }],
  // Saturday
  6: [{ start: "00:00", end: "16:00" }],
  // Fallback if a day is not listed
  default: [{ start: "00:00", end: "24:00" }],
};
/*** ─────────────────────────────────────────────────────────── ***/

(function () {
  'use strict';

  // Match both English and German labels, fall back to exact text match
  const LABELS_FOR_YOU = new Set(["For you", "Für dich"]);
  const LABELS_FOLLOWING = new Set(["Following", "Folge ich"]);

  const HIDDEN_ATTR = "data-hidden-by-userscript-for-you";

  function timeToMinutes(t) {
    const [h, m] = t.split(":").map(Number);
    return h * 60 + (m || 0);
  }

  function inRange(nowMin, startMin, endMin) {
    // Handles normal and overnight (wrap-around) ranges
    if (startMin === endMin) return false; // empty range
    if (startMin < endMin) return nowMin >= startMin && nowMin < endMin;
    return nowMin >= startMin || nowMin < endMin;
  }

  function isFeatureActiveNow() {
    const now = new Date();
    const day = now.getDay(); // 0..6
    const minutes = now.getHours() * 60 + now.getMinutes();
    const ranges = SCHEDULE.hasOwnProperty(day) ? SCHEDULE[day] : SCHEDULE.default;

    if (!ranges || ranges.length === 0) return false;
    return ranges.some(({ start, end }) => inRange(minutes, timeToMinutes(start), timeToMinutes(end)));
  }

  function getTabs() {
    const tabs = Array.from(document.querySelectorAll('[role="tab"]'));
    let forYouTab = null, followingTab = null;

    tabs.forEach(tab => {
      const text = (tab.textContent || "").trim();
      if (LABELS_FOR_YOU.has(text)) forYouTab = tab;
      if (LABELS_FOLLOWING.has(text)) followingTab = tab;
    });

    return { forYouTab, followingTab };
  }

  function hideForYouAndSwitch() {
    const { forYouTab, followingTab } = getTabs();
    if (!forYouTab) return;

    // Hide the "For you" tab
    if (forYouTab.style.display !== "none") {
      forYouTab.style.display = "none";
      forYouTab.setAttribute(HIDDEN_ATTR, "true");
    }

    // If "For you" was active, switch to "Following"
    if (forYouTab.getAttribute('aria-selected') === 'true' && followingTab) {
      // Some builds require a mouse event to trigger navigation properly
      followingTab.click();
    }
  }

  function unhideForYou() {
    const { forYouTab } = getTabs();
    if (!forYouTab) return;
    if (forYouTab.getAttribute(HIDDEN_ATTR) === "true") {
      forYouTab.style.display = "";
      forYouTab.removeAttribute(HIDDEN_ATTR);
    }
  }

  function applyBehavior() {
    if (isFeatureActiveNow()) {
      hideForYouAndSwitch();
    } else {
      unhideForYou();
    }
  }

  // Run immediately
  applyBehavior();

  // Observe DOM changes (tabs re-render frequently)
  const observer = new MutationObserver(() => applyBehavior());
  observer.observe(document.body, { childList: true, subtree: true });

  // Re-check schedule every minute in case the hour changes without DOM mutations
  const intervalId = setInterval(applyBehavior, 60 * 1000);

  // Cleanup on unload
  window.addEventListener('unload', () => {
    observer.disconnect();
    clearInterval(intervalId);
  }, false);
})();