虎牙页面优化

虎牙精简版,移除首页直播,移除直播礼物特效等不必要元素,还你纯粹的直播体验

// ==UserScript==
// @name         虎牙页面优化
// @namespace    http://tampermonkey.net/
// @version      1.6
// @description  虎牙精简版,移除首页直播,移除直播礼物特效等不必要元素,还你纯粹的直播体验
// @author       You
// @match        https://www.huya.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=huya.com
// @grant        none
// @license      MIT
// ==/UserScript==

class ControlPanel {
    $panel = null;
    storageKey = 'controlPanelState'; // 用于 localStorage 的键名

    constructor() {
        this.isCollapsed = false;
        this.initPanel();
        this.loadState(); // 加载保存的状态
        this.bindEvents();
    }

    initPanel() {
        this.$panel = $(`
            <div class="control-panel" style="position: fixed; width: 300px; background: #f0f0f0; border: 1px solid #ccc; border-radius: 5px; z-index: 9999;">
                <div class="panel-header" style="padding: 5px; background: #ddd; cursor: move; user-select: none;">
                    <span>控制面板</span>
                    <button class="toggle-btn" style="float: right; border: none; background: none; cursor: pointer;">-</button>
                </div>
                <div class="panel-content" style="padding: 10px; max-height: 200px; overflow-y: auto;">
                    <div class="log-area"></div>
                </div>
            </div>
        `);
        $('#root').append(this.$panel);
    }

    loadState() {
        try {
            const savedState = localStorage.getItem(this.storageKey);
            if (savedState) {
                const { position, isCollapsed } = JSON.parse(savedState);
                
                // 应用保存的位置
                if (position) {
                    this.$panel.css({
                        left: position.left || 'auto',
                        top: position.top || 'auto',
                        right: position.right || 'auto',
                        bottom: position.bottom || 'auto'
                    });
                } else {
                    this.$panel.css({
                        bottom: '10px',
                        right: '10px'
                    });
                }

                // 应用保存的收缩状态
                this.isCollapsed = !!isCollapsed;
                this.$panel.find('.panel-content').toggle(!this.isCollapsed);
                this.$panel.find('.toggle-btn').text(this.isCollapsed ? '+' : '-');
            } else {
                this.$panel.css({
                    bottom: '10px',
                    right: '10px'
                });
            }
        } catch (e) {
            console.error('Failed to load panel state:', e);
        }
    }

    // 保存当前状态
    saveState() {
        try {
            const state = {
                position: {
                    left: this.$panel.css('left'),
                    top: this.$panel.css('top'),
                    right: this.$panel.css('right'),
                    bottom: this.$panel.css('bottom')
                },
                isCollapsed: this.isCollapsed
            };
            localStorage.setItem(this.storageKey, JSON.stringify(state));
        } catch (e) {
            console.error('Failed to save panel state:', e);
        }
    }

    bindEvents() {
        const $header = this.$panel.find('.panel-header');
        const $toggleBtn = this.$panel.find('.toggle-btn');
        const $content = this.$panel.find('.panel-content');

        // 拖拽功能
        $header.on('mousedown', (e) => {
            e.preventDefault();
            const startX = e.clientX - parseInt(this.$panel.css('left') || 0);
            const startY = e.clientY - parseInt(this.$panel.css('top') || 0);

            const onMouseMove = (moveE) => {
                this.$panel.css({
                    left: moveE.clientX - startX,
                    top: moveE.clientY - startY,
                    right: 'auto',
                    bottom: 'auto'
                });
            };

            const onMouseUp = () => {
                $(document).off('mousemove', onMouseMove).off('mouseup', onMouseUp);
                this.saveState(); // 拖拽结束后保存状态
            };

            $(document).on('mousemove', onMouseMove).on('mouseup', onMouseUp);
        });

        // 收缩/展开功能
        $toggleBtn.on('click', () => {
            this.isCollapsed = !this.isCollapsed;
            $content.toggle(!this.isCollapsed);
            $toggleBtn.text(this.isCollapsed ? '+' : '-');
            this.saveState(); // 切换收缩状态后保存
        });
    }

    log(data) {
        const $logArea = this.$panel.find('.log-area');
        const timestamp = new Date().toLocaleTimeString();
        const logEntry = `<div style="border-bottom: 1px solid #eee; padding: 2px 0;">[${timestamp}] ${JSON.stringify(data)}</div>`;
        $logArea.append(logEntry);
        $logArea.scrollTop($logArea[0].scrollHeight);
    }
}

(function () {
    "use strict";
    $(document).ready(main);

    function main() {
        const style = document.createElement("style");
        style.innerHTML = `
        /* 侧边悬浮菜单栏 */
        a[href="//www.huya.com/download/"],
        a[href="https://hd.huya.com/pc/2019zhubo/pages/index.html"],
        a[href="https://hd.huya.com/web/about/index.html#contact"],
        a[href="https://wan.huya.com/"] {
        display: none !important;
        }

        .helperbar--cpOuG7OGer2wWrNst9OwG > * {
        display: none;
        }

        .helperbar--cpOuG7OGer2wWrNst9OwG > .helper-nav--1yz7uIycIDu_3rI5oz1pJr {
        display: block;
        }

        /* 顶部菜单栏 */
        .NavKaiBo--3_pcnDZbeaycODmpgNFBtt,
        .NavDownload--14eln2LYTFMgF_MZOue4Gu,
        #J_hyNavItemYouliao,
        #J_hyHdNavItemGame {
        display: none;
        }

        /* 直播特效(ad与特效弹幕) */
        #player-marquee-wrap,
        #huya-ab-fixed,
        #huya-ab {
        display: none;
        }

        /* 订阅按钮一列 */
        #J_roomHdR > div > div {
        display: none !important;
        }
        #J_roomHdR > div > .subscribe-entrance {
        display: block !important;
        }


        /* 特效弹幕 */
        /* 礼物通知 */
        /* 大家都在发 */
        /* 事件通知 */
        .player-banner-gift,
        #player-danmu-plus-one-banner,
        #player-mouse-event-wrap,
        .player-fans-banner {
        display: none !important;
        }
        `;
        document.querySelector("body").append(style);
        
        try {
            window.panel = new ControlPanel();
        } catch (error) {
            alert(error);
        }

        const url = location.href;
        if (/^(https?:\/\/)([a-zA-Z0-9-\.]+)\/?$/.test(url)) {
            home();
        }
        if (/^(https?:\/\/)([a-zA-Z0-9-\.]+)(\/[a-zA-Z0-9-]+\/?)$/.test(url)) {
            player();
        }
    }

    function home() {
        document.querySelector("#duya-header").style.backgroundColor =
            "rgb(167 167 167)";
        const banner = document.querySelector("#banner");
        banner.innerHTML = "";
        $(banner).css({
            position: "inherit",
            height: "60px",
            "background-image": "url()",
            "background-color": "#ffffff",
        });
        // 暂停直播
        document.querySelector("#player-btn")?.click();
        // 移除直播
        document.querySelector(".mod-index-main")?.remove();
    }

    function player() {
        // 免登录
        if (VPlayer.prototype.checkLogin) VPlayer.prototype.checkLogin(true);

        $(document.querySelector("#J_mainWrap")).css({
            "padding-left": "0px",
            display: "flex",
            "justify-content": "center",
            "align-items": "center",
        });

        document.querySelector(".mod-sidebar")?.remove();
        const main = document.querySelector("#main_col");
        const videoBox = main.querySelector("#J_mainRoom");
        // 净化直播容器
        const core = videoBox.querySelector(".room-core");
        videoBox.replaceChildren(core);
        // 移除右侧弹幕
        core.replaceChildren(core.querySelector(".room-core-l"));
        // 净化主容器
        main.replaceChildren(videoBox);
        videoBox.style.margin = 0;
        // 订阅按钮一列
        const a = document.querySelector(".host-control.J_roomHdCtrl");
        a.replaceChildren(a.querySelector(".subscribe-entrance"));

        (() => {
            // 优化视频布局
            $(document.querySelector("#main_col")).css({
                display: "flex",
                "justify-content": "center",
                "align-items": "center",
            });
            $(document.querySelector("#J_mainRoom")).css({
                padding: "0 0 0 0",
                "min-width": "0",
                width: "calc((100vmin - 20px - 60px) * 1.4)",
            });
            $(document.querySelector(".room-core .room-core-l")).css({
                "margin-right": "0",
            });
        })();

        (function() {
            const observer = new MutationObserver((mutations, observer) => {
                const data = $(".player-videotype-list li")?.data("data");
                if (!data) {
                    return;
                }
                observer.disconnect();
                data.sDisplayName = "蓝光不是20M";
                data.sTagText = "无需扫码";
                data.iEnable = 1;
                alert("解锁成功");
                window.panel.log(data);
            });
            observer.observe(document.body, {
                childList: true,
                subtree: true,
            });
        })();
    }
})();