Facebook Cleaner & Expand post area.

Remove unnecessary and rarely used feature buttons and elements from Facebook to make the entire page look cleaner and more streamlined, Widen the post area to improve the overall visual experience.

// ==UserScript==
// @name         Facebook Cleaner & Expand post area.
// @name:zh-TW   Facebook 乾淨化 & 加寬貼文區
// @name:zh-CN   Facebook 乾淨化 & 加宽贴文区
// @namespace    http://tampermonkey.net/
// @version      4.2
// @description  Remove unnecessary and rarely used feature buttons and elements from Facebook to make the entire page look cleaner and more streamlined, Widen the post area to improve the overall visual experience.
// @description:zh-TW 刪除FaceBook多餘、不常使用的功能按鈕和要素,使整個頁面看起來更加簡潔,加寬貼文區,讓整體觀感更好
// @description:zh-CN 删除FaceBook多余、不常使用的功能按钮和要素,使整个页面看起来更加简洁,加宽贴文区,让整体观感更好
// @author       chatgpt
// @match        https://www.facebook.com/*
// @grant        none
// @license MIT
// ==/UserScript==

(function () {
  'use strict';

  /***** === 第一階段:Facebook 清爽化(先執行)=== *****/
  (function cleanerPhase() {
    // 需要隱藏的左側選單文字
    const leftKeywords = [
    // 繁體中文
      '動態回顧', '我的珍藏', '我的收藏', 'Marketplace', '兒童版 Messenger',
      '玩遊戲', '近期廣告動態', '訂單和付款', '氣候科學中心', '募款活動', '籌款活動',
      '廣告管理員', 'Meta Quest 3S',
    // 簡體中文
      '那年今天', '收藏夹', '广告管理工具', '气候科学中心',
      '订单与支付', '玩游戏', '近期广告动态', '筹款活动', 'Messenger 少儿版',
    // 英文
      'Memories', 'Saved', 'Messenger Kids',
      'Gaming', 'Play games', 'Recent ad activity', 'Orders and payments',
      'Climate Science Center', 'Fundraisers', 'Ads Manager'
    ];

    // 「顯示更多」與「顯示較少」的相關文字
    const moreKeywords = ['顯示更多', '更多', '展开', 'See more', 'More', 'Show more', 'See More', 'MORE', 'SHOW MORE'];
    const lessKeywords = ['顯示較少', '收起', 'Show less', 'Show Less', 'Less', 'LESS'];

    // 其他要移除的元素選擇器
    const selectors = [
      'footer',
      'div[role="contentinfo"]',
      'div[aria-label="Facebook"] > div:last-child'
    ];

    // 確認是否為有側欄的主要頁面
    function isMainSidebarPage() {
      return !!document.querySelector('nav[role="navigation"], [role=navigation]');
    }

    // 根據文字內容隱藏左側欄目
    function hideLeftSidebarByText() {
      document.querySelectorAll('nav a[role="link"], [role=navigation] a[role="link"]').forEach(a => {
        let match = false;
        a.querySelectorAll('span.x1lliihq').forEach(span => {
          if (span.textContent && leftKeywords.includes(span.textContent.trim()) && span.children.length === 0) {
            match = true;
          }
        });
        if (match) a.style.display = 'none';
      });
    }

    // 根據標題文字隱藏右側欄
    function hideRightSidebarByTitle() {
      const rightKeywords = ['贊助', '聯絡人', '联系人', '群組聊天室', '群聊', 'Sponsored', 'Contacts', 'Group conversations'];
      document.querySelectorAll('h3').forEach(h3 => {
        if (h3.textContent && rightKeywords.some(kw => h3.textContent.includes(kw))) {
          let parent = h3;
          for (let i = 0; i < 6; i++) if (parent.parentElement) parent = parent.parentElement;
          if (parent && parent.offsetWidth > 200) parent.style.display = 'none';
        }
      });
    }

    // 隱藏左側選單中的 Marketplace 按鈕
    function removeMarketplaceButton() {
      document.querySelectorAll('a[aria-label="Marketplace"], a[href="/marketplace/?ref=app_tab"], a[href="/marketplace/"]').forEach(a => {
        let li = a;
        for (let i = 0; i < 5; i++) {
          if (li.parentElement && li.parentElement.tagName === 'LI') {
            li = li.parentElement;
            break;
          }
          if (li.parentElement) li = li.parentElement;
        }
        if (li.tagName === 'LI') li.remove();
      });
    }

    // 隱藏頁尾政策連結(例如隱私權政策、服務條款)
    function hidePolicyLinks() {
      const policyKeywords = ['隱私政策', '服務條款', '廣告', 'Ad Choices', 'Cookie', 'Meta © 2025', 'Privacy Policy', 'Terms'];
      document.querySelectorAll('footer, div[role="contentinfo"]').forEach(container => {
        policyKeywords.forEach(kw => {
          if (container.textContent.includes(kw)) container.style.display = 'none';
        });
      });
    }

    // 隱藏「顯示更多/較少」按鈕
    function removeMoreAndLessButtons() {
      document.querySelectorAll('[role="button"]').forEach(btn => {
        const spans = btn.querySelectorAll('span');
        for (const span of spans) {
          const text = span.textContent.trim().toLowerCase();
          if (moreKeywords.some(kw => text === kw.toLowerCase() || text.includes(kw.toLowerCase()))) {
            btn.style.display = 'none';
            break;
          }
          if (lessKeywords.some(kw => text === kw.toLowerCase() || text.includes(kw.toLowerCase()))) {
            btn.style.display = 'none';
            break;
          }
        }
      });
    }

    // 嘗試自動展開「顯示更多」左欄選單
    function tryExpandOnce() {
      if (!isMainSidebarPage()) return;
      let found = false;
      const btns = Array.from(document.querySelectorAll('nav[role="navigation"] [role="button"], [role=navigation] [role="button"]'));
      for (const btn of btns) {
        if (btn.offsetParent === null) continue;
        const spans = btn.querySelectorAll('span');
        for (const span of spans) {
          const text = span.textContent.trim().toLowerCase();
          if (moreKeywords.some(kw => text === kw.toLowerCase() || text.includes(kw.toLowerCase()))) {
            btn.click(); // 模擬點擊展開
            found = true;
            setTimeout(removeMoreAndLessButtons, 800);
            break;
          }
        }
        if (found) break;
      }
    }

    // 一次執行所有需要隱藏的元素處理
    function hideOtherElements() {
      selectors.forEach(selector => {
        document.querySelectorAll(selector).forEach(el => el.style.display = 'none');
      });
      hideLeftSidebarByText();
      hideRightSidebarByTitle();
      removeMarketplaceButton();
      hidePolicyLinks();
    }

    // 使用 debounce 控制節流,避免太頻繁操作 DOM
    function debounceHideAndExpand() {
      clearTimeout(window.__fbCleanerDebounceTimer);
      window.__fbCleanerDebounceTimer = setTimeout(() => {
        hideOtherElements();
        tryExpandOnce();
      }, 300);
    }

    // 頁面載入完成後自動展開左欄
    window.addEventListener('load', () => {
      if (isMainSidebarPage()) tryExpandOnce();
    });

    // 初次執行清理
    hideOtherElements();

    // 監聽頁面變動,動態移除新增的干擾元素
    const observer = new MutationObserver(debounceHideAndExpand);
    observer.observe(document.body, { childList: true, subtree: true });
  })();

  /***** === 第二階段:加寬貼文顯示區域(後執行)=== *****/
    // 加寬貼文主體容器 (固定寬度 1200px,避免閃爍)
    const styleWiden = document.createElement('style');
    styleWiden.textContent = `
      div.x193iq5w.xvue9z.xq1tmr.x1ceravr {
        width: 1200px !important;
        max-width: 1200px !important;
        box-sizing: border-box !important;
        transition: none !important;
        will-change: width !important;
     }
    `;
    document.head.appendChild(styleWiden);

    // 標記已加寬貼文避免重複操作
    function applyWiden() {
     const posts = document.querySelectorAll('div.x193iq5w.xvue9z.xq1tmr.x1ceravr');
    posts.forEach(post => {
        if (!post.classList.contains('widened')) {
          post.classList.add('widened');
          // 只靠CSS強制固定寬度,不額外更動DOM
        }
     });
    }

    // 初始加寬
    applyWiden();

    // MutationObserver 防抖監控新增貼文
    let debounceTimer = null;
    const observer = new MutationObserver(() => {
     if (debounceTimer) clearTimeout(debounceTimer);
     debounceTimer = setTimeout(() => {
        applyWiden();
     }, 200);
    });

    if (document.body) {
     observer.observe(document.body, { childList: true, subtree: true });
    } else {
      const waitForBody = setInterval(() => {
        if (document.body) {
          observer.observe(document.body, { childList: true, subtree: true });
          clearInterval(waitForBody);
        }
     }, 50);
    }

})();