Greasy Fork

YouTube 新标签页打开

功能:1.新标签页打开视频 2.屏蔽首页Shorts 3.屏蔽首页精选 4.主页内容刷新 5.非主页自动关闭 (所有功能可在右下角设置)

// ==UserScript==
// @name         YouTube 新标签页打开
// @namespace    http://tampermonkey.net/
// @version      1.3.3
// @description  功能:1.新标签页打开视频 2.屏蔽首页Shorts 3.屏蔽首页精选 4.主页内容刷新 5.非主页自动关闭 (所有功能可在右下角设置)
// @author       YourName
// @match        *://www.youtube.com/*
// @grant        none
// @license      MIT
// @icon         https://www.google.com/s2/favicons?domain=youtube.com
// ==/UserScript==

(function() {
    'use strict';

    // 从localStorage读取设置,默认全部开启
    var newTabEnabled = localStorage.getItem('yt_new_tab_enabled') !== null ? 
        (localStorage.getItem('yt_new_tab_enabled') === 'true') : true;
    var shortsBlockingEnabled = localStorage.getItem('yt_shorts_blocking_enabled') !== null ? 
        (localStorage.getItem('yt_shorts_blocking_enabled') === 'true') : true;
    var exploreBlockingEnabled = localStorage.getItem('yt_explore_blocking_enabled') !== null ? 
        (localStorage.getItem('yt_explore_blocking_enabled') === 'true') : true;

    // 监听链接点击事件
    document.addEventListener('click', function(e) {
        if (e.button !== 0 || e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) return;

        var anchor = e.target.closest('a');
        if (!anchor) return;

        try {
            var url = new URL(anchor.href, window.location.origin);

            // 处理视频链接
            if (newTabEnabled && url.pathname === '/watch' && url.searchParams.has('v')) {
                e.preventDefault();
                e.stopPropagation();
                window.open(anchor.href, '_blank');
                return;
            }

            // 处理Shorts链接
            if (shortsBlockingEnabled && url.pathname.startsWith('/shorts')) {
                e.preventDefault();
                e.stopPropagation();
                return;
            }
        } catch (error) {
            return;
        }
    }, true);

    // 创建悬浮控制容器
    var controlContainer = document.createElement('div');
    controlContainer.style.position = 'fixed';
    controlContainer.style.bottom = '10px';
    controlContainer.style.right = '10px';
    controlContainer.style.zIndex = '9999';
    controlContainer.style.display = 'flex';
    controlContainer.style.flexDirection = 'row';
    controlContainer.style.alignItems = 'flex-end';

    // 创建设置菜单
    var menu = document.createElement('div');
    menu.style.display = 'none';
    menu.style.flexDirection = 'column';
    menu.style.backgroundColor = 'white';
    menu.style.border = '1px solid #ccc';
    menu.style.borderRadius = '4px';
    menu.style.padding = '10px';
    menu.style.position = 'fixed';
    menu.style.bottom = '60px';
    menu.style.right = '10px';
    menu.style.boxShadow = '0 2px 6px rgba(0,0,0,0.2)';
    menu.style.zIndex = '10000';

    // 创建功能开关
    var newTabDiv = document.createElement('div');
    var newTabCheckbox = document.createElement('input');
    newTabCheckbox.type = 'checkbox';
    newTabCheckbox.checked = newTabEnabled;
    newTabCheckbox.id = 'newTabToggle';
    var newTabLabel = document.createElement('label');
    newTabLabel.htmlFor = 'newTabToggle';
    newTabLabel.textContent = ' 新标签页打开';
    newTabDiv.appendChild(newTabCheckbox);
    newTabDiv.appendChild(newTabLabel);

    var shortsDiv = document.createElement('div');
    var shortsCheckbox = document.createElement('input');
    shortsCheckbox.type = 'checkbox';
    shortsCheckbox.checked = shortsBlockingEnabled;
    shortsCheckbox.id = 'shortsToggle';
    var shortsLabel = document.createElement('label');
    shortsLabel.htmlFor = 'shortsToggle';
    shortsLabel.textContent = ' Shorts 屏蔽';
    shortsDiv.appendChild(shortsCheckbox);
    shortsDiv.appendChild(shortsLabel);

    var exploreDiv = document.createElement('div');
    var exploreCheckbox = document.createElement('input');
    exploreCheckbox.type = 'checkbox';
    exploreCheckbox.checked = exploreBlockingEnabled;
    exploreCheckbox.id = 'exploreToggle';
    var exploreLabel = document.createElement('label');
    exploreLabel.htmlFor = 'exploreToggle';
    exploreLabel.textContent = ' 精选屏蔽';
    exploreDiv.appendChild(exploreCheckbox);
    exploreDiv.appendChild(exploreLabel);

    menu.appendChild(newTabDiv);
    menu.appendChild(shortsDiv);
    menu.appendChild(exploreDiv);

    // 创建保存按钮
    var saveButton = document.createElement('button');
    saveButton.textContent = '保存';
    saveButton.style.marginTop = '10px';
    saveButton.style.padding = '5px 10px';
    saveButton.style.border = 'none';
    saveButton.style.backgroundColor = '#0073e6';
    saveButton.style.color = '#fff';
    saveButton.style.cursor = 'pointer';
    saveButton.style.borderRadius = '4px';
    menu.appendChild(saveButton);
    
    saveButton.addEventListener('click', function() {
        location.reload();
    });

    // 绑定设置变更事件
    newTabCheckbox.addEventListener('change', function() {
        newTabEnabled = newTabCheckbox.checked;
        localStorage.setItem('yt_new_tab_enabled', newTabEnabled);
    });

    shortsCheckbox.addEventListener('change', function() {
        shortsBlockingEnabled = shortsCheckbox.checked;
        localStorage.setItem('yt_shorts_blocking_enabled', shortsBlockingEnabled);
    });

    exploreCheckbox.addEventListener('change', function() {
        exploreBlockingEnabled = exploreCheckbox.checked;
        localStorage.setItem('yt_explore_blocking_enabled', exploreBlockingEnabled);
    });

    // 创建刷新/关闭按钮
    var refreshButton = document.createElement('div');
    refreshButton.textContent = '刷新内容';
    refreshButton.style.fontSize = '15px';
    refreshButton.style.fontWeight = 'bold';
    refreshButton.style.width = 'auto';
    refreshButton.style.height = '40px';
    refreshButton.style.borderRadius = '20px';
    refreshButton.style.backgroundColor = '#FF9EB5';
    refreshButton.style.color = 'white';
    refreshButton.style.display = 'flex';
    refreshButton.style.justifyContent = 'center';
    refreshButton.style.alignItems = 'center';
    refreshButton.style.cursor = 'pointer';
    refreshButton.style.userSelect = 'none';
    refreshButton.style.marginRight = '10px';
    refreshButton.style.boxShadow = '0 2px 6px rgba(0,0,0,0.1)';
    refreshButton.style.whiteSpace = 'nowrap';
    refreshButton.style.padding = '0 15px';
    refreshButton.style.transition = 'all 0.2s ease';
    refreshButton.style.position = 'relative';
    refreshButton.style.top = '0';

    // 添加点击事件处理
    refreshButton.addEventListener('click', function() {
        if (window.location.pathname === '/') {
            const ytLogo = document.querySelector('#logo-icon');
            if (ytLogo) {
                ytLogo.click();
            }
        } else {
            window.close();
        }
    });

    // 按钮悬停效果
    refreshButton.addEventListener('mouseenter', function() {
        this.style.boxShadow = '0 4px 12px rgba(0,0,0,0.2)';
        this.style.top = '-2px';
    });
    refreshButton.addEventListener('mouseleave', function() {
        this.style.boxShadow = '0 2px 6px rgba(0,0,0,0.1)';
        this.style.top = '0';
    });

    // 更新按钮文字
    function updateButtonText() {
        refreshButton.textContent = window.location.pathname === '/' ? '刷新内容' : '关闭页面';
    }
    updateButtonText();

    // 创建设置按钮
    var ball = document.createElement('div');
    ball.textContent = '⚙';
    ball.style.fontSize = '24px';
    ball.style.width = '40px';
    ball.style.height = '40px';
    ball.style.borderRadius = '50%';
    ball.style.backgroundColor = '#0073e6';
    ball.style.color = 'white';
    ball.style.display = 'flex';
    ball.style.justifyContent = 'center';
    ball.style.alignItems = 'center';
    ball.style.cursor = 'pointer';
    ball.style.userSelect = 'none';
    ball.style.lineHeight = '40px';
    ball.style.textAlign = 'center';
    ball.style.transition = 'all 0.2s ease';
    ball.style.position = 'relative';
    ball.style.top = '0';
    ball.style.boxShadow = '0 2px 6px rgba(0,0,0,0.1)';

    ball.addEventListener('mouseenter', function() {
        this.style.boxShadow = '0 4px 12px rgba(0,0,0,0.2)';
        this.style.top = '-2px';
    });
    ball.addEventListener('mouseleave', function() {
        this.style.boxShadow = '0 2px 6px rgba(0,0,0,0.1)';
        this.style.top = '0';
    });

    // 监听URL变化
    var urlObserver = new MutationObserver(updateButtonText);
    if (document.querySelector('title')) {
        urlObserver.observe(document.querySelector('title'), {
            subtree: true,
            characterData: true,
            childList: true
        });
    }

    // 组装界面元素
    controlContainer.appendChild(refreshButton);
    controlContainer.appendChild(ball);
    document.body.appendChild(controlContainer);
    document.body.appendChild(menu);

    // 全屏状态检测
    function handleFullscreen() {
        if (document.fullscreenElement) {
            controlContainer.style.display = 'none';
            menu.style.display = 'none';
        } else {
            controlContainer.style.display = 'flex';
        }
    }

    // 监听全屏状态变化
    document.addEventListener('fullscreenchange', handleFullscreen);
    document.addEventListener('webkitfullscreenchange', handleFullscreen);
    document.addEventListener('mozfullscreenchange', handleFullscreen);
    document.addEventListener('MSFullscreenChange', handleFullscreen);

    // 处理设置菜单的显示/隐藏
    ball.addEventListener('click', function(e) {
        e.stopPropagation();
        menu.style.display = (menu.style.display === 'none') ? 'flex' : 'none';
    });

    // 点击外部关闭菜单
    document.addEventListener('click', function(e) {
        if (!menu.contains(e.target) && e.target !== ball) {
            menu.style.display = 'none';
        }
    });

    // 移除Shorts和精选内容
    if (window.location.pathname === "/" && (shortsBlockingEnabled || exploreBlockingEnabled)) {
        function removeContent() {
            var shelves = document.querySelectorAll("ytd-rich-shelf-renderer, ytd-reel-shelf-renderer");
            shelves.forEach(function(shelf) {
                var titleElement = shelf.querySelector('h2');
                if (titleElement) {
                    var titleText = titleElement.textContent.trim().toLowerCase();
                    // 移除Shorts内容
                    if (shortsBlockingEnabled && titleText.includes('shorts')) {
                        shelf.remove();
                        return;
                    }
                    // 移除精选内容
                    if (exploreBlockingEnabled && (titleText.includes('精选') || titleText.includes('explore'))) {
                        shelf.remove();
                        return;
                    }
                }
                // 备用检测:移除包含shorts链接的内容
                if (shortsBlockingEnabled && shelf.querySelector("a[href^='/shorts']")) {
                    shelf.remove();
                }
            });
        }

        removeContent();
        // 监听DOM变化,动态移除新增内容
        var observer = new MutationObserver(removeContent);
        observer.observe(document.body, { childList: true, subtree: true });
    }
})();