Focused YouTube

Remove ads, shorts, and algorithmic suggestions on YouTube (EN/NL/DE/FR)

当前为 2025-06-29 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Focused YouTube
// @version      2025-06-29.7
// @author       Richard B
// @namespace    https://www.365devnet.eu/focusedyoutube
// @description  Remove ads, shorts, and algorithmic suggestions on YouTube (EN/NL/DE/FR)
// @match        *://*.youtube.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @run-at       document-start
// @grant        GM_setValue
// @grant        GM_getValue
// @license      MIT
// ==/UserScript==

// Credits: 
// Originally based on Focused YouTube by Kervyn
// https://github.com/KervynH/Focused-YouTube
// 
// Additional credits: https://github.com/lawrencehook/remove-youtube-suggestions
//
// MIT License
// 
// Copyright (c) 2025 Richard B
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

'use strict';

// Config custom settings here - now with user preferences support
const DEFAULT_SETTINGS = {
  /// homepage redirect ///
  redirectHomepage: false, // Options: 'wl', 'subs', 'lib', false
  hideHomepageButton: false,

  /// homepage suggestions ///
  hideAllSuggestions: false,
  hideAllButOneRow: true,
  hideInfiniteScroll: false,

  /// video player ///
  skipAds: true,
  hideLiveChat: true,
  hideRelatedVideos: true,
  hideMiniPlayerButton: true,
  hidePlayNextButton: true,
  forceCinemaMode: true,

  /// shorts ///
  hideShorts: true,
  redirectShortsPlayer: true,

  /// misc ///
  hideSearchButton: false,
  cleanSearchResults: true,
  hideSponsoredContent: true,
};

// Load user settings with fallback to defaults
const SETTINGS = {};
Object.keys(DEFAULT_SETTINGS).forEach(key => {
  SETTINGS[key] = GM_getValue(key, DEFAULT_SETTINGS[key]);
});

// Performance optimizations
let styleElement = null;
let lastUrl = '';
let observer = null;
const processingQueue = new Set();

// Mark settings in HTML
const HTML = document.documentElement;
Object.keys(SETTINGS).forEach(key => {
  HTML.setAttribute(key, SETTINGS[key]);
});

// Improved CSS selectors with better specificity and modern features
const DESKTOP_BLOCK_LIST = [
  // Ads - More comprehensive coverage
  '#masthead-ad',
  'ytd-mealbar-promo-renderer',
  'ytd-carousel-ad-renderer',
  'ytd-display-ad-renderer',
  'ytd-ad-slot-renderer',
  'ytd-promoted-sparkles-text-search-renderer',
  'div.ytp-ad-overlay-image',
  '.iv-branding.annotation-type-custom.annotation',
  '[class*="ad-showing"]',
  '.ytp-ad-module',

  // Sponsored Content - Comprehensive detection
  'html[hideSponsoredContent="true"] ytd-rich-item-renderer:has(ytd-ad-slot-renderer)',
  'html[hideSponsoredContent="true"] ytd-ad-slot-renderer',
  'html[hideSponsoredContent="true"] ytd-in-feed-ad-layout-renderer',
  'html[hideSponsoredContent="true"] ytd-video-display-full-buttoned-and-button-group-renderer',
  'html[hideSponsoredContent="true"] ytd-ad-inline-playback-meta-block',
  'html[hideSponsoredContent="true"] top-landscape-image-layout-view-model',
  'html[hideSponsoredContent="true"] feed-ad-metadata-view-model',
  'html[hideSponsoredContent="true"] ad-badge-view-model',
  'html[hideSponsoredContent="true"] ad-button-hover-overlay-view-model',
  'html[hideSponsoredContent="true"] ad-button-view-model',
  'html[hideSponsoredContent="true"] ad-image-view-model',
  'html[hideSponsoredContent="true"] ad-details-line-view-model',
  'html[hideSponsoredContent="true"] [class*="ytwAdBadgeViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="ytwFeedAdMetadataViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="ytwTopLandscapeImageLayoutViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="ytwAdButtonHoverOverlayViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="ytwAdButtonViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="ytwAdImageViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="ytwAdDetailsLineViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="badge-style-type-ad"]',
  'html[hideSponsoredContent="true"] [class*="badge-shape-wiz--ad"]',

  // Shorts - Enhanced selectors based on HTML structure
  'html[hideShorts="true"] ytd-rich-section-renderer:has(ytd-rich-shelf-renderer[is-shorts])',
  'html[hideShorts="true"] ytd-rich-shelf-renderer[is-shorts]',
  'html[hideShorts="true"] ytd-rich-shelf-renderer:has(#title:contains("Shorts"))',
  'html[hideShorts="true"] ytd-reel-shelf-renderer',
  'html[hideShorts="true"] ytd-shelf-renderer:has([href*="/shorts/"])',
  'html[hideShorts="true"] ytm-shorts-lockup-view-model-v2',
  'html[hideShorts="true"] ytm-shorts-lockup-view-model',
  'html[hideShorts="true"] [aria-label*="Shorts"]',
  'html[hideShorts="true"] [class*="shortsLockupViewModelHost"]',
  'html[hideShorts="true"] .reel-item-endpoint',

  // Left Bar Navigation - Enhanced Shorts menu removal
  'a[href="/feed/trending"]',
  'a[href="/feed/explore"]',
  'html[hideShorts="true"] ytd-guide-entry-renderer:has([title="Shorts"])',
  'html[hideShorts="true"] ytd-guide-entry-renderer:has(yt-formatted-string:contains("Shorts"))',
  'html[hideShorts="true"] ytd-guide-section-renderer a[title="Shorts"]',
  'html[hideShorts="true"] ytd-mini-guide-entry-renderer[aria-label="Shorts"]',
  'html[hideShorts="true"] ytd-guide-section-renderer a[href*="/shorts"]',
  'ytd-guide-section-renderer.ytd-guide-renderer.style-scope:nth-of-type(4)',
  'ytd-guide-section-renderer.ytd-guide-renderer.style-scope:nth-of-type(3)',

  // Homepage - Better targeting
  'html[hideHomepageButton="true"] a:not(#logo)[href="/"]',
  'html[hideAllSuggestions="true"] ytd-browse[page-subtype="home"] ytd-rich-grid-renderer',
  'html[hideAllButOneRow="true"] ytd-browse[page-subtype="home"] #header',
  'html[hideAllButOneRow="true"] ytd-browse[page-subtype="home"] ytd-rich-grid-renderer > #contents > ytd-rich-grid-row:nth-child(n+2)',
  'html[hideInfiniteScroll="true"] ytd-browse[page-subtype="home"] ytd-rich-grid-renderer > #contents > ytd-continuation-item-renderer',

  // Video Player - Enhanced
  'html[hideRelatedVideos="true"] #secondary',
  'html[hideRelatedVideos="true"] #related',
  'html[hideRelatedVideos="true"] .html5-endscreen',
  'html[hideRelatedVideos="true"] .ytp-endscreen-content',
  'html[hidePlayNextButton="true"] .ytp-next-button',
  'html[hidePlayNextButton="true"] .ytp-prev-button',
  'html[hideLiveChat="true"] #chat',
  'html[hideLiveChat="true"] ytd-live-chat-frame',
  'html[hideMiniPlayerButton="true"] .ytp-miniplayer-button',
  '.ytd-download-button-renderer',

  // Search - Improved
  'div.sbdd_a',
  '#container.ytd-search ytd-search-pyv-renderer',
  'html[hideSearchButton="true"] ytd-searchbox',
  'html[hideSearchButton="true"] #voice-search-button',
];

const MOBILE_BLOCK_LIST = [
  // Ads 
  'ytm-companion-ad-renderer',
  'ytm-promoted-sparkles-web-renderer',
  '[class*="ad-showing"]',

  // Sponsored Content (Mobile) - Comprehensive
  'html[hideSponsoredContent="true"] ytm-rich-item-renderer:has([class*="ad"])',
  'html[hideSponsoredContent="true"] ytm-ad-slot-renderer',
  'html[hideSponsoredContent="true"] [class*="ytwAdBadgeViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="ytwTopLandscapeImageLayoutViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="ytwAdButtonViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="ytwAdImageViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="sponsored"]',
  'html[hideSponsoredContent="true"] [class*="badge-style-type-ad"]',
  'html[hideSponsoredContent="true"] [class*="badge-shape-wiz--ad"]',

  // Shorts - Enhanced mobile targeting
  'html[hideShorts="true"] ytm-reel-shelf-renderer',
  'html[hideShorts="true"] ytm-shorts-lockup-view-model-v2',
  'html[hideShorts="true"] ytm-shorts-lockup-view-model',
  'html[hideShorts="true"] [aria-label*="Shorts"]',
  'html[hideShorts="true"] [class*="shortsLockupViewModelHost"]',
  'html[hideShorts="true"] .reel-item-endpoint',

  // Homepage 
  'html[hideHomepageButton="true"] div[tab-identifier="FEwhat_to_watch"]',
  'html[hideSearchButton="true"] #header-bar > header > div > button',
  'html[hideSearchButton="true"] #center.style-scope.ytd-masthead',

  // Video Player 
  'html[hideRelatedVideos="true"] ytm-item-section-renderer[section-identifier="related-items"]',
  'html[hidePlayNextButton="true"] .player-controls-middle-core-buttons > div:nth-child(1)',
  'html[hidePlayNextButton="true"] .player-controls-middle-core-buttons > div:nth-child(5)',
  'html[hideLiveChat="true"] ytm-live-chat-frame',

  // Navigation Bar - Enhanced Shorts menu removal
  'html[hideHomepageButton="true"] ytm-pivot-bar-item-renderer:nth-child(1)',
  'html[hideShorts="true"] ytm-pivot-bar-item-renderer:nth-child(2)',
  'html[hideShorts="true"] ytm-guide-entry-renderer:has([title="Shorts"])',
  'html[hideShorts="true"] ytm-guide-entry-renderer:has([aria-label*="Shorts"])',
  'ytm-chip-cloud-chip-renderer[chip-style="STYLE_EXPLORE_LAUNCHER_CHIP"]',
];

// Improved style injection with error handling
function addStyle(css) {
  try {
    if (!styleElement) {
      styleElement = document.createElement('style');
      styleElement.id = 'focused-youtube-styles';
      document.head.appendChild(styleElement);
    }
    styleElement.textContent = css;
  } catch (error) {
    console.warn('Focused YouTube: Failed to inject styles:', error);
  }
}

// Apply styles based on platform
function applyStyles() {
  const isDesktop = location.hostname.startsWith('www.');
  const isMobile = location.hostname.startsWith('m.');
  
  if (isDesktop) {
    const styles = DESKTOP_BLOCK_LIST.map(e => `${e} { display: none !important; }`).join('\n');
    addStyle(styles);
  } else if (isMobile) {
    const styles = MOBILE_BLOCK_LIST.map(e => `${e} { display: none !important; }`).join('\n');
    addStyle(styles);
  }
}

// Improved URL change detection
function detectUrlChange() {
  const currentUrl = location.href;
  if (currentUrl !== lastUrl) {
    lastUrl = currentUrl;
    handleUrlChange();
  }
}

function handleUrlChange() {
  // Re-apply settings when navigating
  setTimeout(() => {
    runDynamicSettings();
  }, 100);
}

// Enhanced MutationObserver for better performance
function setupObserver() {
  if (observer) observer.disconnect();
  
  observer = new MutationObserver((mutations) => {
    let shouldProcess = false;
    let hasAdContent = false;
    
    for (const mutation of mutations) {
      if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
        for (const node of mutation.addedNodes) {
          if (node.nodeType === Node.ELEMENT_NODE) {
            const tagName = node.tagName?.toLowerCase();
            // Check for any YouTube or ad-related elements
            if (tagName?.includes('ytd-') || tagName?.includes('ytm-') || 
                tagName?.includes('ad-') || node.classList?.toString().includes('ad') ||
                node.querySelector?.('ytd-ad-slot-renderer, [class*="ad"]')) {
              shouldProcess = true;
              // Special handling for ad content - process immediately
              if (tagName?.includes('ad-') || node.classList?.toString().includes('ad') ||
                  node.querySelector?.('ytd-ad-slot-renderer')) {
                hasAdContent = true;
              }
            }
          }
        }
      }
      if (shouldProcess) break;
    }
    
    if (shouldProcess) {
      // Process ad content immediately, others with short delay
      const delay = hasAdContent ? 0 : 50;
      clearTimeout(window.focusedYTTimeout);
      window.focusedYTTimeout = setTimeout(runDynamicSettings, delay);
      
      // Force additional cleanup for ads
      if (hasAdContent) {
        setTimeout(() => {
          if (SETTINGS.hideSponsoredContent) hideSponsoredContent();
          if (SETTINGS.hideShorts) hideShortsVideos();
        }, 100);
      }
    }
  });
  
  observer.observe(document.body, {
    childList: true,
    subtree: true,
    attributes: false,
    characterData: false
  });
}

// Start initialization with aggressive timing
function initialize() {
  applyStyles();
  setupObserver();
  
  // URL change detection
  setInterval(detectUrlChange, 250);
  
  // Multiple initialization runs to catch dynamic content
  setTimeout(runDynamicSettings, 100);   // Very early
  setTimeout(runDynamicSettings, 500);   // Early
  setTimeout(runDynamicSettings, 1000);  // Medium
  setTimeout(runDynamicSettings, 2000);  // Late
  
  // Aggressive ad blocking - run every 3 seconds for first 30 seconds
  let aggressiveCount = 0;
  const aggressiveInterval = setInterval(() => {
    if (SETTINGS.hideSponsoredContent) hideSponsoredContent();
    if (SETTINGS.hideShorts) hideShortsVideos();
    aggressiveCount++;
    if (aggressiveCount >= 10) { // 10 * 3 = 30 seconds
      clearInterval(aggressiveInterval);
    }
  }, 3000);
  
  // Continuous monitoring for ad content
  setInterval(() => {
    if (SETTINGS.hideSponsoredContent) {
      const adElements = document.querySelectorAll(
        'ytd-ad-slot-renderer, ytd-in-feed-ad-layout-renderer, ' +
        'top-landscape-image-layout-view-model, [class*="ytwTopLandscapeImageLayoutViewModelHost"]'
      );
      if (adElements.length > 0) {
        hideSponsoredContent();
      }
    }
  }, 1000);
}

// Wait for DOM to be ready with immediate execution
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', initialize);
  // Also run immediately in case DOM loads before listener is set
  setTimeout(initialize, 0);
} else {
  initialize();
}

// Force immediate style application
setTimeout(() => {
  applyStyles();
  runDynamicSettings();
}, 0);

/***** Core Functions *****/

function runDynamicSettings() {
  try {
    if (SETTINGS.redirectHomepage && SETTINGS.redirectHomepage !== 'false') redirectHomepage();
    if (SETTINGS.redirectShortsPlayer) redirectShortsPlayer();
    if (SETTINGS.hideShorts) hideShortsVideos();
    if (SETTINGS.cleanSearchResults) cleanSearchResults();
    if (SETTINGS.skipAds) skipVideoAds();
    if (SETTINGS.hideRelatedVideos) disableRelatedAutoPlay();
    if (SETTINGS.forceCinemaMode) enableCinemaMode();
    if (SETTINGS.hideSponsoredContent) hideSponsoredContent();
  } catch (error) {
    console.warn('Focused YouTube: Error in runDynamicSettings:', error);
  }
}

function redirectHomepage() {
  if (location.pathname === '/' && !location.search) {
    const redirectMap = {
      'wl': '/playlist?list=WL',
      'subs': '/feed/subscriptions',
      'lib': '/feed/library'
    };
    
    const redirect = redirectMap[SETTINGS.redirectHomepage];
    if (redirect) {
      location.replace(redirect);
    }
  }
}

function redirectShortsPlayer() {
  if (location.pathname.startsWith('/shorts/')) {
    const videoId = location.pathname.replace('/shorts/', '');
    const newUrl = `/watch?v=${videoId}${location.search ? '&' + location.search.slice(1) : ''}`;
    location.replace(newUrl);
  }
}

function disableRelatedAutoPlay() {
  // Desktop autoplay
  const autoplayButtons = document.querySelectorAll('.ytp-autonav-toggle-button[aria-checked="true"]');
  autoplayButtons.forEach(button => {
    if (button.offsetParent && !processingQueue.has(button)) {
      processingQueue.add(button);
      button.click();
      setTimeout(() => processingQueue.delete(button), 1000);
    }
  });
  
  // Mobile autoplay
  const mobileAutoplayButtons = document.querySelectorAll('.ytm-autonav-toggle-button-container[aria-pressed="true"]');
  mobileAutoplayButtons.forEach(button => {
    if (button.offsetParent && !processingQueue.has(button)) {
      processingQueue.add(button);
      button.click();
      setTimeout(() => processingQueue.delete(button), 1000);
    }
  });
}

function hideShortsVideos() {
  // Remove sidebar Shorts menu item first
  const shortsMenuItems = document.querySelectorAll(
    'ytd-guide-entry-renderer:has([title="Shorts"]), ' +
    'ytd-guide-entry-renderer:has(yt-formatted-string), ' +
    'ytm-guide-entry-renderer:has([title="Shorts"]), ' +
    'ytm-guide-entry-renderer:has([aria-label*="Shorts"])'
  );
  shortsMenuItems.forEach(item => {
    const titleElement = item.querySelector('yt-formatted-string, [title], [aria-label]');
    const text = titleElement?.innerText || titleElement?.textContent || 
                 titleElement?.getAttribute('title') || titleElement?.getAttribute('aria-label');
    
    if (text && text.toLowerCase().includes('shorts')) {
      if (!processingQueue.has(item)) {
        processingQueue.add(item);
        item.remove();
      }
    }
  });

  // Remove shorts containers - Enhanced detection
  const shortsContainers = document.querySelectorAll(
    'ytd-rich-section-renderer:has(ytd-rich-shelf-renderer[is-shorts]), ' +
    'ytd-rich-section-renderer:has([id="title"]:is([innerText*="Shorts"], [textContent*="Shorts"]))'
  );
  shortsContainers.forEach(container => {
    if (!processingQueue.has(container)) {
      processingQueue.add(container);
      container.remove();
    }
  });

  // Remove shorts shelf renderers
  const shortsShelves = document.querySelectorAll('ytd-rich-shelf-renderer[is-shorts]');
  shortsShelves.forEach(shelf => {
    if (!processingQueue.has(shelf)) {
      processingQueue.add(shelf);
      shelf.remove();
    }
  });

  // Remove by title detection
  const shortsHeaders = document.querySelectorAll('#title');
  shortsHeaders.forEach(title => {
    const text = title.innerText || title.textContent;
    if (text && text.toLowerCase().includes('shorts')) {
      const container = title.closest('ytd-rich-section-renderer, ytd-rich-shelf-renderer');
      if (container && !processingQueue.has(container)) {
        processingQueue.add(container);
        container.remove();
      }
    }
  });

  // Remove shorts lockup components
  const shortsLockups = document.querySelectorAll(
    'ytm-shorts-lockup-view-model-v2, ytm-shorts-lockup-view-model, ' +
    '[class*="shortsLockupViewModelHost"], .reel-item-endpoint'
  );
  shortsLockups.forEach(lockup => {
    const parent = lockup.closest('ytd-rich-item-renderer, ytd-rich-section-renderer');
    if (parent && !processingQueue.has(parent)) {
      processingQueue.add(parent);
      parent.remove();
    }
  });

  // Fallback: Remove by shorts links
  const shortsLinks = document.querySelectorAll('a[href*="/shorts/"]');
  shortsLinks.forEach(link => {
    const containers = [
      link.closest('ytd-rich-item-renderer'),
      link.closest('ytd-rich-section-renderer'),
      link.closest('ytm-item-section-renderer'),
      link.closest('ytd-video-renderer'),
      link.closest('ytm-video-with-context-renderer')
    ].filter(Boolean);
    
    containers.forEach(container => {
      if (!processingQueue.has(container)) {
        processingQueue.add(container);
        container.remove();
      }
    });
  });

  // Remove shorts tabs on channel pages
  if (location.pathname.startsWith('/@') || location.pathname.startsWith('/c/') || location.pathname.startsWith('/channel/')) {
    const shortsTabs = document.querySelectorAll('[role="tab"], div.tab-content');
    shortsTabs.forEach(tab => {
      const text = tab.innerText?.toUpperCase();
      const shortsTerms = ['SHORTS', 'COURTS', 'KURZ', 'KORT']; // EN, FR, DE, NL
      
      if (shortsTerms.some(term => text?.includes(term)) && !processingQueue.has(tab)) {
        processingQueue.add(tab);
        (tab.parentElement || tab).remove();
      }
    });
  }
}

function skipVideoAds() {
  if (!location.pathname.startsWith('/watch')) return;
  
  // Skip ad buttons
  const skipButtons = document.querySelectorAll('.ytp-ad-skip-button-slot button, .ytp-ad-overlay-close-button, .ytp-ad-skip-button');
  skipButtons.forEach(button => {
    if (button.offsetParent && !processingQueue.has(button)) {
      processingQueue.add(button);
      button.click();
      setTimeout(() => processingQueue.delete(button), 500);
    }
  });

  // Fast-forward through ads
  const adVideo = document.querySelector('.ad-showing');
  if (adVideo) {
    const video = document.querySelector('.html5-main-video');
    if (video && video.duration && !isNaN(video.duration) && video.duration > 0) {
      video.currentTime = video.duration - 0.1;
    }
  }
}

function cleanSearchResults() {
  if (!location.pathname.startsWith('/results')) return;
  
  const relatedTerms = [
    // English
    'Related', 'People also watched', 'For you', 'Recommended', 'You might also like',
    'Similar videos', 'More like this', 'Suggested', 'Because you watched',
    
    // Dutch
    'Gerelateerd', 'Anderen bekeken ook', 'Voor jou', 'Aanbevolen', 'Misschien vind je dit ook leuk',
    'Vergelijkbare video\'s', 'Meer zoals dit', 'Voorgesteld', 'Omdat je keek naar',
    
    // German  
    'Ähnlich', 'Andere sahen auch', 'Für dich', 'Empfohlen', 'Das könnte dir auch gefallen',
    'Ähnliche Videos', 'Mehr davon', 'Vorgeschlagen', 'Weil du dir angesehen hast',
    
    // French
    'Connexe', 'D\'autres ont aussi regardé', 'Pour vous', 'Recommandé', 'Vous aimerez peut-être aussi',
    'Vidéos similaires', 'Plus comme ça', 'Suggéré', 'Parce que vous avez regardé'
  ];
  
  const badges = document.querySelectorAll('ytm-badge, .badge-style-type-simple');
  
  badges.forEach(badge => {
    const text = badge.innerText || badge.textContent;
    if (relatedTerms.some(term => text?.includes(term))) {
      const container = badge.closest('ytm-video-with-context-renderer, ytd-video-renderer');
      if (container && !processingQueue.has(container)) {
        processingQueue.add(container);
        container.remove();
      }
    }
  });
}

function enableCinemaMode() {
  if (!location.pathname.startsWith('/watch')) return;
  
  // Check if we're in fullscreen mode
  const isFullscreen = document.fullscreenElement || 
                      document.webkitFullscreenElement || 
                      document.mozFullScreenElement || 
                      document.msFullscreenElement;
  
  if (isFullscreen) return; // Don't force cinema mode if already in fullscreen
  
  // Find the cinema mode button
  const cinemaButton = document.querySelector('.ytp-size-button');
  
  if (cinemaButton && !processingQueue.has(cinemaButton)) {
    // Check if cinema mode is already active by looking for the expanded state
    const player = document.querySelector('#movie_player');
    const isAlreadyCinema = player?.classList.contains('ytp-big-mode') || 
                           document.querySelector('ytd-watch-flexy[theater]');
    
    if (!isAlreadyCinema) {
      processingQueue.add(cinemaButton);
      cinemaButton.click();
      setTimeout(() => processingQueue.delete(cinemaButton), 1000);
    }
  }
}

function hideSponsoredContent() {
  // Remove sponsored/ad containers - Most comprehensive detection
  const sponsoredContainers = document.querySelectorAll(
    'ytd-rich-item-renderer:has(ytd-ad-slot-renderer), ' +
    'ytd-rich-item-renderer:has(ytd-in-feed-ad-layout-renderer), ' +
    'ytd-rich-item-renderer:has(ytd-video-display-full-buttoned-and-button-group-renderer), ' +
    'ytd-rich-item-renderer:has(top-landscape-image-layout-view-model), ' +
    'ytd-rich-item-renderer:has(feed-ad-metadata-view-model), ' +
    'ytd-rich-item-renderer:has([class*="ytwTopLandscapeImageLayoutViewModelHost"]), ' +
    'ytd-rich-item-renderer:has([class*="ytwAdBadgeViewModelHost"]), ' +
    'ytd-rich-item-renderer:has([class*="ytwFeedAdMetadataViewModelHost"])'
  );
  sponsoredContainers.forEach(container => {
    if (!processingQueue.has(container)) {
      processingQueue.add(container);
      container.remove();
    }
  });

  // Remove all ad-related components directly
  const adComponents = document.querySelectorAll(
    'ytd-ad-slot-renderer, ' +
    'ytd-in-feed-ad-layout-renderer, ' +
    'ytd-video-display-full-buttoned-and-button-group-renderer, ' +
    'ytd-ad-inline-playback-meta-block, ' +
    'top-landscape-image-layout-view-model, ' +
    'feed-ad-metadata-view-model, ' +
    'ad-badge-view-model, ' +
    'ad-button-hover-overlay-view-model, ' +
    'ad-button-view-model, ' +
    'ad-image-view-model, ' +
    'ad-details-line-view-model'
  );
  adComponents.forEach(component => {
    const container = component.closest('ytd-rich-item-renderer, ytm-rich-item-renderer');
    if (container && !processingQueue.has(container)) {
      processingQueue.add(container);
      container.remove();
    }
  });

  // Remove elements with ad-related class patterns
  const adClassElements = document.querySelectorAll(
    '[class*="ytwAdBadgeViewModelHost"], ' +
    '[class*="ytwFeedAdMetadataViewModelHost"], ' +
    '[class*="ytwTopLandscapeImageLayoutViewModelHost"], ' +
    '[class*="ytwAdButtonHoverOverlayViewModelHost"], ' +
    '[class*="ytwAdButtonViewModelHost"], ' +
    '[class*="ytwAdImageViewModelHost"], ' +
    '[class*="ytwAdDetailsLineViewModelHost"], ' +
    '[class*="badge-style-type-ad"], ' +
    '[class*="badge-shape-wiz--ad"]'
  );
  adClassElements.forEach(element => {
    const container = element.closest('ytd-rich-item-renderer, ytm-rich-item-renderer');
    if (container && !processingQueue.has(container)) {
      processingQueue.add(container);
      container.remove();
    }
  });

  // Remove by sponsored text content - Enhanced with more variations
  const sponsoredTerms = [
    // English
    'Sponsored', 'Ad', 'Promoted', 'Advertisement',
    
    // Dutch
    'Gesponsord', 'Advertentie', 'Gepromoot', 'Reclame',
    
    // German
    'Gesponsert', 'Anzeige', 'Werbung', 'Gesponsort',
    
    // French
    'Sponsorisé', 'Publicité', 'Annonce', 'Promo'
  ];

  // Check all possible badge and text elements
  const textElements = document.querySelectorAll(
    'badge-shape, .badge-shape-wiz, [class*="badge"], ' +
    'ytd-badge-supported-renderer, .badge-style-type-ad, ' +
    '[aria-label*="Sponsored"], [title*="Sponsored"], ' +
    '.badge-shape-wiz__text, [class*="ytwFeedAdMetadataViewModelHost"] span, ' +
    '[class*="yt-core-attributed-string"]'
  );
  textElements.forEach(element => {
    const text = element.innerText || element.textContent || 
                 element.getAttribute('aria-label') || element.getAttribute('title');
    if (text && sponsoredTerms.some(term => text.toLowerCase().includes(term.toLowerCase()))) {
      const container = element.closest('ytd-rich-item-renderer, ytm-rich-item-renderer');
      if (container && !processingQueue.has(container)) {
        processingQueue.add(container);
        container.remove();
      }
    }
  });

  // Check for googleadservices links (ad links) - Enhanced
  const adLinks = document.querySelectorAll(
    'a[href*="googleadservices.com"], ' +
    'a[href*="doubleclick.net"], ' +
    'a[href*="googlesyndication.com"], ' +
    'a[rel="nofollow"][target="_blank"]'
  );
  adLinks.forEach(link => {
    // Additional check for ad-like URLs
    const href = link.getAttribute('href');
    if (href && (href.includes('gclid=') || href.includes('&num=') || href.includes('pagead'))) {
      const container = link.closest('ytd-rich-item-renderer, ytm-rich-item-renderer');
      if (container && !processingQueue.has(container)) {
        processingQueue.add(container);
        container.remove();
      }
    }
  });

  // Ultimate fallback: Remove any rich-item-renderer containing "Visit site" button
  const visitSiteButtons = document.querySelectorAll('[aria-label="Visit site"], [title*="Visit site"]');
  visitSiteButtons.forEach(button => {
    const container = button.closest('ytd-rich-item-renderer, ytm-rich-item-renderer');
    if (container && !processingQueue.has(container)) {
      processingQueue.add(container);
      container.remove();
    }
  });
}

// Settings management (for future UI)
function updateSetting(key, value) {
  SETTINGS[key] = value;
  GM_setValue(key, value);
  HTML.setAttribute(key, value);
  applyStyles();
  runDynamicSettings();
}

// Export for potential external use
window.FocusedYouTube = {
  settings: SETTINGS,
  updateSetting,
  runDynamicSettings
};