MilkyWayIdle 公屏聊天全屏

聊天全屏 + 多栏布局 + 自动调整消息数量 + 显示/隐藏按钮文本(带小眼睛图标) + 截图功能

Versión del día 27/05/2025. Echa un vistazo a la versión más reciente.

// ==UserScript==
// @name         MilkyWayIdle 公屏聊天全屏
// @namespace    http://tampermonkey.net/
// @version      2.4
// @description  聊天全屏 + 多栏布局 + 自动调整消息数量 + 显示/隐藏按钮文本(带小眼睛图标) + 截图功能
// @match        https://www.milkywayidle.com/*
// @grant        none
// @license MIT
// ==/UserScript==

(function () {
    'use strict';

    // 小眼睛图标配置(请确保图片链接可公开访问)
    const EYE_ICON_VISIBLE = 'https://imgur.la/images/2025/05/27/Screenshot-2025-05-27-012424.png'; // 显示文本时的图标
    const EYE_ICON_HIDDEN = 'https://imgur.la/images/2025/05/27/Screenshot-2025-05-27-012424.png'; // 隐藏文本时的图标(如需不同状态可替换)

    let layoutMode = 2; // 1: 一栏, 2: 两栏, 3: 三栏
    let messageCount = 44; // 默认两栏显示44条
    let fullscreenMode = false;
    let observer = null;
    let firstLoad = true;
    let allMessages = []; // 存储所有消息的副本
    let showButtonText = true; // 控制按钮文本是否显示

    function createFullscreenButton() {
        const button = document.createElement('button');
        button.id = 'fullscreen-chat-toggle-btn';
        button.innerHTML = `
            <span class="btn-text">聊天全屏</span>
            <img class="btn-icon" src="${EYE_ICON_VISIBLE}" alt="切换文本"
                 style="margin-left: 8px; width: 20px; height: 20px; vertical-align: middle;">
        `;
        button.style.cssText = `
            position: fixed; top: 10px; right: 10px; z-index: 9999;
            padding: 10px 12px; background-color: #007bff; color: white;
            border: none; border-radius: 8px; cursor: pointer; font-size: 14px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); transition: background-color 0.3s;
            display: flex; align-items: center; gap: 6px;
        `;

        button.addEventListener('mouseenter', () => button.style.backgroundColor = '#0056b3');
        button.addEventListener('mouseleave', () => button.style.backgroundColor = '#007bff');
        button.addEventListener('click', (e) => {
            const isIconClick = e.target.classList.contains('btn-icon') || e.target.closest('.btn-icon');
            if (isIconClick) {
                toggleButtonText(button);
            } else {
                toggleChatFullscreen();
            }
        });

        if (!document.getElementById('fullscreen-chat-toggle-btn')) {
            document.body.appendChild(button);
        }
    }

    function toggleButtonText(button) {
        showButtonText = !showButtonText;
        const textSpan = button.querySelector('.btn-text');
        const iconImg = button.querySelector('.btn-icon');

        if (showButtonText) {
            textSpan.style.display = 'inline';
            iconImg.src = EYE_ICON_VISIBLE;
            button.style.paddingRight = '15px'; // 恢复右侧内边距
        } else {
            textSpan.style.display = 'none';
            iconImg.src = EYE_ICON_HIDDEN; // 可替换为闭眼图标
            button.style.paddingRight = '12px'; // 隐藏文本后调整内边距
        }
    }

    function createScreenshotButton() {
        const button = document.createElement('button');
        button.textContent = '截图';
        button.id = 'fullscreen-chat-screenshot-btn';
        button.style.cssText = `
            position: fixed; top: 60px; right: 10px; z-index: 9999;
            padding: 10px 15px; background-color: #28a745; color: white;
            border: none; border-radius: 8px; cursor: pointer; font-size: 14px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); transition: background-color 0.3s;
            display: none;
        `;

        button.addEventListener('mouseenter', () => button.style.backgroundColor = '#1e7e34');
        button.addEventListener('mouseleave', () => button.style.backgroundColor = '#28a745');
        button.addEventListener('click', captureScreenshot);

        if (!document.getElementById('fullscreen-chat-screenshot-btn')) {
            document.body.appendChild(button);
        }
    }

    function createLayoutButton() {
        const button = document.createElement('button');
        button.textContent = '布局: 两栏';
        button.id = 'fullscreen-chat-layout-btn';
        button.style.cssText = `
            position: fixed; top: 110px; right: 10px; z-index: 9999;
            padding: 10px 15px; background-color: #6c757d; color: white;
            border: none; border-radius: 8px; cursor: pointer; font-size: 14px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); transition: background-color 0.3s;
            display: none;
        `;

        button.addEventListener('mouseenter', () => button.style.backgroundColor = '#5a6268');
        button.addEventListener('mouseleave', () => button.style.backgroundColor = '#6c757d');
        button.addEventListener('click', toggleLayout);

        if (!document.getElementById('fullscreen-chat-layout-btn')) {
            document.body.appendChild(button);
        }
    }

    function toggleLayout() {
        layoutMode = (layoutMode % 3) + 1;
        updateLayout();
    }

    function updateLayout() {
        const chat = document.querySelector('[class^="ChatHistory_chatHistory"]');
        const layoutBtn = document.getElementById('fullscreen-chat-layout-btn');

        if (!chat || !chat.classList.contains('fullscreen-chat')) return;

        messageCount = layoutMode * 22; // 一栏22条,两栏44条,三栏66条
        const layoutNames = ['一栏', '两栏', '三栏'];
        layoutBtn.textContent = `布局: ${layoutNames[layoutMode - 1]}`;
        chat.style.columnCount = layoutMode;
        applyMessageLimit();
    }

    function applyMessageLimit() {
        const chat = document.querySelector('[class^="ChatHistory_chatHistory"]');
        if (!chat) return;

        allMessages = Array.from(chat.children);
        allMessages.forEach(msg => msg.style.display = 'none');
        const recentMessages = allMessages.slice(-messageCount);
        recentMessages.forEach(msg => msg.style.display = 'block');
    }

    function toggleChatFullscreen() {
        const chat = document.querySelector('[class^="ChatHistory_chatHistory"]');
        const toggleBtn = document.getElementById('fullscreen-chat-toggle-btn');
        const screenshotBtn = document.getElementById('fullscreen-chat-screenshot-btn');
        const layoutBtn = document.getElementById('fullscreen-chat-layout-btn');

        if (!chat) {
            alert('❗ 找不到聊天区域');
            return;
        }

        fullscreenMode = !chat.classList.contains('fullscreen-chat');

        if (fullscreenMode) {
            chat.classList.add('fullscreen-chat');
            toggleBtn.querySelector('.btn-text').textContent = '退出全屏';
            screenshotBtn.style.display = 'block';
            layoutBtn.style.display = 'block';
            chat.offsetHeight; // 强制回流
            setupMessageObserver(chat);
            updateLayout();
            firstLoad = false;
        } else {
            chat.classList.remove('fullscreen-chat');
            toggleBtn.querySelector('.btn-text').textContent = '聊天全屏';
            screenshotBtn.style.display = 'none';
            layoutBtn.style.display = 'none';
            disconnectMessageObserver();
            allMessages.forEach(msg => msg.style.display = 'block');
            allMessages = [];
            firstLoad = true;
        }
    }

    function setupMessageObserver(chat) {
        disconnectMessageObserver();
        observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                    allMessages = Array.from(chat.children);
                    applyMessageLimit();
                }
            });
        });
        observer.observe(chat, { childList: true });
    }

    function disconnectMessageObserver() {
        if (observer) {
            observer.disconnect();
            observer = null;
        }
    }

    function injectStyles() {
        const style = document.createElement('style');
        style.textContent = `
            [class^="ChatHistory_chatHistory"] > div {
                margin-bottom: 6px; padding-bottom: 2px; font-size: 14px;
                line-height: 1.4; word-wrap: break-word; white-space: pre-wrap;
                word-break: break-word; user-select: text;
            }

            .fullscreen-chat {
                position: fixed !important; top: 0 !important; left: 0 !important;
                width: 100vw !important; height: 100vh !important;
                background-color: #fff !important; z-index: 9998 !important;
                overflow-y: auto !important; padding: 20px; box-sizing: border-box;
                color: #333 !important; column-gap: 40px;
            }

            .fullscreen-chat > div {
                color: #111 !important; break-inside: avoid; margin-bottom: 10px;
                transition: opacity 0.3s ease;
            }

            #fullscreen-chat-toggle-btn {
                transition: all 0.3s ease;
            }

            .btn-icon {
                border-radius: 4px;
                transition: opacity 0.3s ease;
            }

            .btn-icon:hover {
                opacity: 0.8;
            }

            #fullscreen-chat-screenshot-btn,
            #fullscreen-chat-layout-btn {
                position: fixed; top: 60px; right: 10px; z-index: 9999;
                padding: 10px 15px; background-color: #28a745; color: white;
                border: none; border-radius: 8px; cursor: pointer; font-size: 14px;
                box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); transition: background-color 0.3s;
            }

            #fullscreen-chat-layout-btn {
                background-color: #6c757d;
                top: 110px;
            }

            .screenshot-overlay {
                position: fixed; top: 0; left: 0; width: 100%; height: 100%;
                background-color: rgba(0, 0, 0, 0.5); z-index: 99999;
                display: flex; align-items: center; justify-content: center;
                opacity: 0; pointer-events: none; transition: opacity 0.3s ease;
            }

            .screenshot-overlay.active {
                opacity: 1; pointer-events: auto;
            }

            .screenshot-message {
                background-color: white; padding: 20px; border-radius: 10px;
                box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); font-size: 18px;
                text-align: center;
            }
        `;
        document.head.appendChild(style);
    }

    function createScreenshotOverlay() {
        const overlay = document.createElement('div');
        overlay.className = 'screenshot-overlay';
        overlay.innerHTML = `
            <div class="screenshot-message">
                <div id="screenshot-status">正在准备截图...</div>
            </div>
        `;

        if (!document.querySelector('.screenshot-overlay')) {
            document.body.appendChild(overlay);
        }

        return overlay;
    }

    function captureScreenshot() {
        const chat = document.querySelector('[class^="ChatHistory_chatHistory"]');
        const overlay = createScreenshotOverlay();
        const status = document.getElementById('screenshot-status');

        if (!chat || !chat.classList.contains('fullscreen-chat')) {
            alert('请先进入聊天全屏模式');
            return;
        }

        overlay.classList.add('active');
        status.textContent = '正在准备截图...';

        requestAnimationFrame(() => {
            html2canvas(chat, { useCORS: true }).then(canvas => {
                status.textContent = '正在复制到剪贴板...';

                canvas.toBlob(blob => {
                    const item = new ClipboardItem({ 'image/png': blob });

                    navigator.clipboard.write([item]).then(() => {
                        status.textContent = '截图已复制到剪贴板!';
                        setTimeout(() => overlay.classList.remove('active'), 1500);
                    }).catch(err => {
                        console.error('复制失败:', err);
                        status.textContent = '复制失败,请重试';
                        setTimeout(() => overlay.classList.remove('active'), 2000);
                    });
                });
            }).catch(err => {
                console.error('截图失败:', err);
                status.textContent = '截图失败,请重试';
                setTimeout(() => overlay.classList.remove('active'), 2000);
            });
        });
    }

    function waitForChatWithObserver() {
        const observer = new MutationObserver((mutations, obs) => {
            const chat = document.querySelector('[class^="ChatHistory_chatHistory"]');
            if (chat) {
                injectStyles();
                createFullscreenButton();
                createScreenshotButton();
                createLayoutButton();
                obs.disconnect();
            }
        });

        observer.observe(document.body, { childList: true, subtree: true });
    }

    window.addEventListener('resize', () => {
        const chat = document.querySelector('[class^="ChatHistory_chatHistory"]');
        if (chat && chat.classList.contains('fullscreen-chat')) {
            applyMessageLimit();
        }
    });

    function loadHtml2Canvas() {
        if (window.html2canvas) return Promise.resolve();

        return new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.src = 'https://html2canvas.hertzen.com/dist/html2canvas.min.js';
            script.onload = resolve;
            script.onerror = reject;
            document.head.appendChild(script);
        });
    }

    (async function init() {
        try {
            await loadHtml2Canvas();
            waitForChatWithObserver();
        } catch (err) {
            console.error('截图功能加载失败:', err);
            alert('截图功能加载失败,请刷新页面重试');
        }
    })();
})();
长期地址
遇到问题?请前往 GitHub 提 Issues。