Twitch聊天室自動展開

自動展開聊天室

// ==UserScript==
// @name         Twitch聊天室自動展開
// @version      1.5
// @description  自動展開聊天室
// @author      BaconEgg
// @match        https://www.twitch.tv/*
// @grant        none
// @namespace https://gf.qytechs.cn/users/735944
// ==/UserScript==

(() => {
    'use strict';

    // 取得聊天室狀態 按鈕標籤
    const isChatCollapsed = () => {
        const label = state.button?.getAttribute('aria-label');
        return label && label.indexOf('展開') >= 0;
    };

    // 常數定義
    const BUTTON_SELECTOR = '[data-a-target="right-column__toggle-collapse-btn"]';
    const CHAT_CONTAINER_SELECTOR = '[data-a-target="right-column"]';
    const THROTTLE_DELAY = 500;

    // 狀態管理
    const state = {
        button: null,
        chatContainer: null,
        observer: null,
        pendingRAF: null
    };

    // 快取按鈕元素
    const getButton = () => {
        if (state.button?.isConnected) return state.button;
        const chat = getChatContainer();
        if (chat) {
            state.button = chat.querySelector(BUTTON_SELECTOR);
            if (state.button?.isConnected) return state.button;
        }
        state.button = document.querySelector(BUTTON_SELECTOR);
        return state.button;
    };

    // 快取聊天室區塊
    const getChatContainer = () => {
        if (state.chatContainer?.isConnected) return state.chatContainer;
        state.chatContainer = document.querySelector(CHAT_CONTAINER_SELECTOR);
        return state.chatContainer;
    };

    // 主要功能:只要聊天室是摺疊就展開
    const updateChatVisibility = () => {
        try {
            const btn = getButton();
            if (!btn) return;
            if (isChatCollapsed()) {
                if (state.pendingRAF) cancelAnimationFrame(state.pendingRAF);
                state.pendingRAF = requestAnimationFrame(() => {
                    btn.click();
                    state.pendingRAF = null;
                });
            }
        } catch (err) {
            console.error('[Twitch] Error updating chat visibility:', err);
        }
    };

    // 節流版本
    const throttle = (fn, delay) => {
        let lastCall = 0;
        let scheduled = null;
        return (...args) => {
            const now = Date.now();
            if (now - lastCall >= delay) {
                lastCall = now;
                fn(...args);
            } else if (!scheduled) {
                scheduled = setTimeout(() => {
                    lastCall = Date.now();
                    scheduled = null;
                    fn(...args);
                }, delay - (now - lastCall));
            }
        };
    };
    const throttledUpdateChatVisibility = throttle(updateChatVisibility, THROTTLE_DELAY);

    // 觀察器:監控聊天室按鈕狀態
    const startObserver = () => {
        if (state.observer) return;
        const chat = getChatContainer();
        const target = chat || document.body;
        state.observer = new MutationObserver(() => {
            state.button = null;
            throttledUpdateChatVisibility();
        });
        state.observer.observe(target, {
            childList: true,
            subtree: true,
            attributes: true,
            attributeFilter: ['aria-label']
        });
    };

    // 初始化
    const init = () => {
        setTimeout(() => {
            const btn = getButton();
            if (btn) {
                throttledUpdateChatVisibility();
                startObserver();
            } else {
                // 如果按鈕不存在,設置一次性 MutationObserver 等待按鈕出現
                const tempObserver = new MutationObserver((mutations, observer) => {
                    if (getButton()) {
                        observer.disconnect();
                        init();
                    }
                });
                tempObserver.observe(document.body, {
                    childList: true,
                    subtree: true
                });
            }
        }, 500);
    };

    window.addEventListener('load', () => {
        init();
    }, { passive: true });
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址