Google AI Studio 页面优化

提供护眼样式、元素显隐控制、自动折叠左右侧面板功能、优化输入框体验及宽度,优化 Google AI Studio 使用体验。

// ==UserScript==
// @name             Google AI Studio Optimization
// @name:zh-CN       Google AI Studio 页面优化
// @namespace        http://tampermonkey.net/
// @version          1.0.1
// @description      Eye-Friendly Styles, Element Control, Auto Collapse Panels, Enhanced Input Width.
// @description:zh-CN 提供护眼样式、元素显隐控制、自动折叠左右侧面板功能、优化输入框体验及宽度,优化 Google AI Studio 使用体验。
// @author           Gemini
// @match            https://aistudio.google.com/prompts/*
// @match            https://aistudio.google.com/*/prompts/*
// @grant            GM_addStyle
// @grant            GM_getValue
// @grant            GM_setValue
// @grant            GM_registerMenuCommand
// @grant            GM_unregisterMenuCommand
// @grant            GM_info
// @license          MIT
// ==/UserScript==

(function() {
    'use strict';

    const SCRIPT_PREFIX = '[AI Studio 增强+]';
    console.log(`${SCRIPT_PREFIX} 初始化 v${GM_info.script.version}...`);

    // --- 默认设置 ---
    const defaultSettings = {
        useCustomStyles: true,
        showUserPrompts: true,
        showThinkingProcess: true,
        showAIMessages: true,
        showInputBox: true,
        showTopNavBar: true,
        showChatTitleBar: true,
        showTokenCount: true, // 注意: 此设置目前在脚本中未实际控制任何元素的显隐
        autoCollapseRightPanel: false,
        autoCollapseLeftPanel: false
    };

    // --- 初始化设置 ---
    let settings = {};
    for (const key in defaultSettings) {
        settings[key] = GM_getValue(key, defaultSettings[key]);
        if (GM_getValue(key) === undefined) {
            GM_setValue(key, defaultSettings[key]);
            console.log(`${SCRIPT_PREFIX} 初始化新设置: ${key} = ${defaultSettings[key]}`);
        }
    }
    console.log(`${SCRIPT_PREFIX} 当前设置:`, settings);

    // --- 菜单文本定义 ---
    const MENU_TEXT_ENABLED = "🟢 启用";
    const MENU_TEXT_DISABLED = "🔴 禁用";
    const MENU_TEXT_SHOW_ALL = "🟢 显示所有";
    const MENU_TEXT_HIDE_ALL = "🔴 隐藏所有";

    // --- 菜单定义 ---
    var menu_ALL = [
        [
            "useCustomStyles",
            "自定义样式",
        ],
        [
            "autoCollapseLeftPanel",
            "自动折叠左侧面板",
        ],
        [
            "autoCollapseRightPanel",
            "自动折叠右侧面板",
        ],
        [
            "showTopNavBar",
            "顶部导航栏",
        ],
        [
            "showChatTitleBar",
            "聊天标题栏",
        ],
        [
            "showUserPrompts",
            "用户消息",
        ],
        [
            "showThinkingProcess",
            "AI 思考过程",
        ],
        [
            "showAIMessages",
            "AI 消息",
        ],
        [
            "showInputBox",
            "底部输入框",
        ],
        [
            "toggleAllDisplays", // 特殊键名,用于切换所有可见性设置
            "切换所有显示项", // 这个基础文本在 toggleAllDisplays 中会进一步动态调整
        ],
    ];
    var menu_ID = []; // 用于存储菜单命令ID,以便注销

    // --- CSS 样式 ---
    const customStyles = `
:root {
    /* 主题颜色变量 */
    --enhancer-bg-main: #f8f9fa;
    --enhancer-text-main: #212529;
    --enhancer-bg-user-prompt: #e9ecef;
    --enhancer-text-user-prompt: #343a40;
    --enhancer-bg-model-prompt: #ffffff;
    --enhancer-text-model-prompt: #212529;
    --enhancer-border-color: #dee2e6;
    --enhancer-button-bg: #f1f3f5;
    --enhancer-button-hover-bg: #e9ecef;
    --enhancer-header-bg: #ffffff;
    --enhancer-input-bg: #ffffff; /* 用于输入框区域的背景,可与主背景区分 */
    --enhancer-link-color: #007bff;
    --enhancer-code-bg: #e9ecef;
    --enhancer-code-text: #212529;
    --enhancer-thinking-bg: #f8f9fa;

    /* 字体大小 - 显著缩小 */
    --enhancer-font-size-base: 13px; /* 基础字号调小 */
    --enhancer-font-size-xs: 0.78rem;  /* 约 10px, 用于页脚等辅助文字 */
    --enhancer-font-size-sm: 0.88rem;  /* 约 11.5px, 用于次要文字 */
    --enhancer-font-size-md: 0.94rem;  /* 约 12.2px, 用于正文和主要内容 */
    --enhancer-font-size-lg: 1.0rem;   /* 约 13px, 用于小标题等 */
    --enhancer-line-height-base: 1.45; /* 减小行高 */
}

@media (prefers-color-scheme: dark) {
    :root {
        --enhancer-bg-main: #212529;
        --enhancer-text-main: #e9ecef;
        --enhancer-bg-user-prompt: #343a40;
        --enhancer-text-user-prompt: #f8f9fa;
        --enhancer-bg-model-prompt: #2c3034;
        --enhancer-text-model-prompt: #f8f9fa;
        --enhancer-border-color: #495057;
        --enhancer-button-bg: #495057;
        --enhancer-button-hover-bg: #5a6268;
        --enhancer-header-bg: #2c3034;
        --enhancer-input-bg: #212529; /* 暗黑模式下输入框区域背景,可与主背景一致或稍有区别 */
        --enhancer-link-color: #6cb2eb;
        --enhancer-code-bg: #343a40;
        --enhancer-code-text: #f8f9fa;
        --enhancer-thinking-bg: #2c3034;
    }
}

/* 页面整体字体和背景 */
body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", "思源黑体", "思源黑体 CN", "Microsoft YaHei", "微软雅黑", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !important;
    font-size: var(--enhancer-font-size-md) !important;
    line-height: var(--enhancer-line-height-base) !important;
    color: var(--enhancer-text-main) !important;
    background-color: var(--enhancer-bg-main) !important;
}

.chunk-editor-main {
    background: var(--enhancer-bg-main) !important;
    padding: 8px !important;
}
.chunk-editor-main p {
    font-family: inherit !important;
    margin-bottom: 0.5em !important;
}

/* 用户消息气泡 */
.user-prompt-container .text-chunk {
    background: var(--enhancer-bg-user-prompt) !important;
    color: var(--enhancer-text-user-prompt) !important;
    padding: 7px 10px !important;
    border-radius: 6px !important;
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
    margin-bottom: 6px !important;
}
.user-prompt-container p {
    font-size: var(--enhancer-font-size-md) !important;
    line-height: var(--enhancer-line-height-base) !important;
    color: var(--enhancer-text-user-prompt) !important;
}

/* AI 模型消息气泡 */
.model-prompt-container {
    background: var(--enhancer-bg-model-prompt) !important;
    color: var(--enhancer-text-model-prompt) !important;
    padding: 8px 12px !important;
    border-radius: 8px !important;
    border: 1px solid var(--enhancer-border-color) !important;
    box-shadow: 0 1px 3px rgba(0,0,0,0.06);
    margin-bottom: 10px !important;
}
.model-prompt-container:has(.mat-accordion) {
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    padding: 5px !important;
}
.model-prompt-container p {
    font-size: var(--enhancer-font-size-md) !important;
    line-height: var(--enhancer-line-height-base) !important;
    color: var(--enhancer-text-model-prompt) !important;
}
.model-prompt-container pre, .model-prompt-container code {
    background-color: var(--enhancer-code-bg) !important;
    color: var(--enhancer-code-text) !important;
    padding: 0.15em 0.3em;
    font-size: 0.88em;
    border-radius: 3px;
    font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace !important;
}
.model-prompt-container pre {
    padding: 0.8em !important;
    margin: 0.3em 0 !important;
    overflow-x: auto !important;
}

/* AI 思考过程 / Accordion 折叠内容 */
ms-thought-chunk, .mat-accordion {
    background-color: var(--enhancer-thinking-bg) !important;
    border-radius: 5px !important;
    padding: 6px 8px !important;
    margin-bottom: 6px !important;
}
.mat-accordion p {
    font-size: var(--enhancer-font-size-sm) !important;
    color: var(--enhancer-text-main) !important;
    opacity: 0.85;
}
ms-thought-chunk{
    max-width:1300px !important;
}

/* 每轮对话的页脚 (Token 数量等) */
.turn-footer {
    font-size: var(--enhancer-font-size-xs) !important;
    background: none !important;
    opacity: 0.65;
    color: var(--enhancer-text-main) !important;
    padding-top: 5px !important;
    margin-bottom: 5px !important;
}

/* 顶部导航和头部区域 */
.page-header, .header-container {
    height: auto !important;
    padding: 5px 10px !important;
    background-color: var(--enhancer-header-bg) !important;
    border-bottom: 1px solid var(--enhancer-border-color) !important;
}
.top-nav {
    font-size: var(--enhancer-font-size-sm) !important;
    display: flex;
    align-items: center;
}

/* 聊天区域的工具栏 */
.toolbar-container {
    height: auto !important;
    padding: 5px 10px !important;
    background-color: var(--enhancer-header-bg) !important;
    border-bottom: 1px solid var(--enhancer-border-color) !important;
}

/* 链接样式 */
a {
    color: var(--enhancer-link-color) !important;
    text-decoration: none !important;
}
a:hover {
    text-decoration: underline !important;
}

/* --------------------------------------------------- */
/* Enhanced Input Area Styles (Footer)                 */
/* --------------------------------------------------- */

footer:has(.prompt-input-wrapper) {
    background-color: var(--enhancer-input-bg) !important;
    border-top: 1px solid var(--enhancer-border-color) !important;
    padding: 10px 10px !important; /* MODIFIED: Reduced horizontal padding */
    position: sticky !important;
    bottom: 0 !important;
    z-index: 100 !important;
    box-shadow: 0 -2px 5px rgba(0,0,0,0.05);
}

@media (prefers-color-scheme: dark) {
    footer:has(.prompt-input-wrapper) {
        box-shadow: 0 -2px 8px rgba(0,0,0,0.15) !important;
    }
}

.prompt-input-wrapper {
    display: flex !important;
    align-items: center !important;
    gap: 8px !important; /* MODIFIED: Slightly reduced gap */
}

.prompt-input-wrapper-container {
    flex-grow: 1 !important;
    display: flex !important;
    position: relative !important;
}

.prompt-input-wrapper-container textarea {
    flex-grow: 1 !important;
    background-color: var(--enhancer-bg-main) !important; /* Use main background for textarea */
    color: var(--enhancer-text-main) !important;
    border: 1px solid var(--enhancer-border-color) !important;
    border-radius: 22px !important;
    padding: 10px 18px !important;
    font-size: var(--enhancer-font-size-md) !important;
    line-height: var(--enhancer-line-height-base) !important;
    min-height: 44px !important;
    max-height: 200px !important;
    resize: none !important;
    box-shadow: 0 1px 2px rgba(0,0,0,0.03) inset !important;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.prompt-input-wrapper-container textarea::placeholder {
    color: color-mix(in srgb, var(--enhancer-text-main) 60%, transparent) !important;
    opacity: 1 !important;
}

.prompt-input-wrapper-container textarea:focus {
    outline: none !important;
    border-color: var(--enhancer-link-color) !important;
    background-color: var(--enhancer-bg-main) !important;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--enhancer-link-color) 20%, transparent),
                0 1px 2px rgba(0,0,0,0.03) inset !important;
}

/* Standard Icon Buttons (Mic, Attach, etc.) */
footer .prompt-input-wrapper button.mat-icon-button,
footer .prompt-input-wrapper button[mat-icon-button] {
    background-color: transparent !important;
    color: var(--enhancer-text-main) !important;
    border: none !important;
    border-radius: 50% !important;
    width: 40px !important;
    height: 40px !important;
    padding: 0 !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    flex-shrink: 0;
    transition: background-color 0.2s ease, color 0.2s ease;
}
footer .prompt-input-wrapper button.mat-icon-button:hover,
footer .prompt-input-wrapper button[mat-icon-button]:hover {
    background-color: var(--enhancer-button-hover-bg) !important;
}
footer .prompt-input-wrapper button.mat-icon-button mat-icon,
footer .prompt-input-wrapper button[mat-icon-button] mat-icon,
footer .prompt-input-wrapper button.mat-icon-button svg,
footer .prompt-input-wrapper button[mat-icon-button] svg {
    font-size: 22px !important;
    width: 22px !important;
    height: 22px !important;
    fill: currentColor !important;
}

/* Prominent Action Button (FAB-like: Send, Stop) */
footer .prompt-input-wrapper button.mat-fab,
footer .prompt-input-wrapper button[mat-fab],
footer .prompt-input-wrapper button.mat-flat-button.send-button-class, /* Add .send-button-class to your Send button if it's flat */
footer .prompt-input-wrapper button[mat-flat-button].send-button-class {
    background-color: var(--enhancer-link-color) !important;
    color: white !important;
    border: none !important;
    border-radius: 50% !important;
    width: 44px !important;
    height: 44px !important;
    padding: 0 !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    box-shadow: 0 2px 5px rgba(0,0,0,0.12), 0 1px 3px rgba(0,0,0,0.08) !important;
    flex-shrink: 0;
    transition: background-color 0.2s ease, box-shadow 0.2s ease;
}
footer .prompt-input-wrapper button.mat-fab:hover,
footer .prompt-input-wrapper button[mat-fab]:hover,
footer .prompt-input-wrapper button.mat-flat-button.send-button-class:hover,
footer .prompt-input-wrapper button[mat-flat-button].send-button-class:hover {
    background-color: color-mix(in srgb, var(--enhancer-link-color) 90%, black) !important;
    box-shadow: 0 4px 8px rgba(0,0,0,0.15), 0 2px 4px rgba(0,0,0,0.1) !important;
}
footer .prompt-input-wrapper button.mat-fab mat-icon,
footer .prompt-input-wrapper button[mat-fab] mat-icon,
footer .prompt-input-wrapper button.mat-fab svg,
footer .prompt-input-wrapper button[mat-fab] svg,
footer .prompt-input-wrapper button.mat-flat-button.send-button-class mat-icon,
footer .prompt-input-wrapper button[mat-flat-button].send-button-class svg {
    fill: white !important;
    color: white !important;
    font-size: 24px !important;
    width: 24px !important;
    height: 24px !important;
}

/* Rectangular Flat Button (if used for e.g. a text "Send" or "Run" button and not covered by .send-button-class) */
footer .prompt-input-wrapper button.mat-flat-button:not([class*='mat-fab']):not([class*='mat-icon-button']):not(.send-button-class),
footer .prompt-input-wrapper button[mat-flat-button]:not([class*='mat-fab']):not([class*='mat-icon-button']):not(.send-button-class) {
    background-color: var(--enhancer-button-bg) !important;
    color: var(--enhancer-text-main) !important;
    border-radius: 20px !important;
    padding: 0 12px !important;    /* MODIFIED: Reduced horizontal padding for text buttons */
    height: 40px !important;
    font-size: var(--enhancer-font-size-sm) !important;
    font-weight: 500 !important;
    border: 1px solid var(--enhancer-border-color) !important;
    box-shadow: none !important;
    transition: background-color 0.2s ease, border-color 0.2s ease;
    white-space: nowrap; /* Prevent text like "Ctrl+Enter" from wrapping if it's part of button text */
}
footer .prompt-input-wrapper button.mat-flat-button:not([class*='mat-fab']):not([class*='mat-icon-button']):not(.send-button-class):hover {
    background-color: var(--enhancer-button-hover-bg) !important;
}
footer .prompt-input-wrapper button.mat-flat-button:not([class*='mat-fab']):not([class*='mat-icon-button']):not(.send-button-class) mat-icon,
footer .prompt-input-wrapper button[mat-flat-button]:not([class*='mat-fab']):not([class*='mat-icon-button']):not(.send-button-class) svg {
    margin-right: 6px !important; /* MODIFIED: Reduced margin for icon in text button */
    font-size: 18px !important;
    width: 18px !important;
    height: 18px !important;
}


/* User Avatar (adjust selector if needed: e.g., img.user-avatar or button.avatar-button img) */
footer .prompt-input-wrapper img[src*="googleusercontent.com"],
footer .prompt-input-wrapper .user-avatar-selector { /* Placeholder for more specific avatar selector */
    width: 36px !important;
    height: 36px !important;
    border-radius: 50% !important;
    object-fit: cover !important;
    margin-left: 4px !important; /* MODIFIED: Reduced margin */
    flex-shrink: 0;
    border: 1px solid var(--enhancer-border-color);
}

/* .prompt-chip-button style (for chips like "Add file", usually above or separate from main input actions) */
.prompt-chip-button {
    background: var(--enhancer-button-bg) !important;
    color: var(--enhancer-text-main) !important;
    border: 1px solid var(--enhancer-border-color) !important;
    border-radius: 16px !important; /* Pill-shaped for chips */
    padding: 5px 12px !important;
    font-size: var(--enhancer-font-size-sm) !important;
    transition: background-color 0.15s ease, border-color 0.15s ease;
    margin: 4px !important;
    height: auto !important;
    width: auto !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    text-decoration: none !important;
}
.prompt-chip-button:hover {
    background: var(--enhancer-button-hover-bg) !important;
    text-decoration: none !important;
}
    `;

    const hideUserPromptsStyle = `.chat-turn-container.user { display: none !important; }`;
    const hideThinkingProcessStyle = `.chat-turn-container .thought-container, ms-thought-chunk {display: none !important;}`;
    const hideAIMessagesStyle = `.chat-turn-container.model { display: none !important; }`;
    const hideInputBoxStyle = `footer:has(.prompt-input-wrapper) { display: none !important; }`;
    const hideTopNavBarStyle = `.header-container { display: none !important; }`;
    const hideChatTitleBarStyle = `.page-header > .content > .title-toolbar, .toolbar-container { display: none !important; }`;

    // --- 样式应用函数 ---
    function updateStyles() {
        const existingStyles = document.querySelectorAll('style[data-enhancer-style]');
        existingStyles.forEach(style => style.remove());

        if (settings.useCustomStyles) {
            const styleElement = document.createElement('style');
            styleElement.setAttribute('data-enhancer-style', 'base');
            styleElement.textContent = customStyles;
            document.head.appendChild(styleElement);
        }
        if (!settings.showUserPrompts) {
            const hideUserStyle = document.createElement('style');
            hideUserStyle.setAttribute('data-enhancer-style', 'user-visibility');
            hideUserStyle.textContent = hideUserPromptsStyle;
            document.head.appendChild(hideUserStyle);
        }
        if (!settings.showThinkingProcess) {
            const hideThinkingStyle = document.createElement('style');
            hideThinkingStyle.setAttribute('data-enhancer-style', 'thinking-visibility');
            hideThinkingStyle.textContent = hideThinkingProcessStyle;
            document.head.appendChild(hideThinkingStyle);
        }
        if (!settings.showAIMessages) {
            const hideAIStyle = document.createElement('style');
            hideAIStyle.setAttribute('data-enhancer-style', 'ai-message-visibility');
            hideAIStyle.textContent = hideAIMessagesStyle;
            document.head.appendChild(hideAIStyle);
        }
        if (!settings.showInputBox) {
            const hideInputBox = document.createElement('style');
            hideInputBox.setAttribute('data-enhancer-style', 'input-box-visibility');
            hideInputBox.textContent = hideInputBoxStyle;
            document.head.appendChild(hideInputBox);
        }
        if (!settings.showTopNavBar) {
            const hideTopNav = document.createElement('style');
            hideTopNav.setAttribute('data-enhancer-style', 'top-nav-visibility');
            hideTopNav.textContent = hideTopNavBarStyle;
            document.head.appendChild(hideTopNav);
        }
        if (!settings.showChatTitleBar) {
            const hideChatTitle = document.createElement('style');
            hideChatTitle.setAttribute('data-enhancer-style', 'chat-title-visibility');
            hideChatTitle.textContent = hideChatTitleBarStyle;
            document.head.appendChild(hideChatTitle);
        }
        console.log(`${SCRIPT_PREFIX} 已根据设置更新样式.`);
    }

    // --- 浮动通知函数 ---
    function showNotification(message) {
        const notificationId = 'enhancer-notification';
        let notification = document.getElementById(notificationId);
        if (!notification) {
            notification = document.createElement('div');
            notification.id = notificationId;
            notification.style.cssText = `
                position: fixed;
                bottom: 20px;
                left: 50%;
                transform: translateX(-50%);
                background-color: rgba(40, 40, 40, 0.9);
                color: white;
                padding: 12px 22px;
                border-radius: 8px;
                box-shadow: 0 4px 15px rgba(0,0,0,0.2);
                z-index: 10000;
                opacity: 0;
                transition: opacity 0.4s ease-in-out, bottom 0.4s ease-in-out;
                font-size: 14px;
                text-align: center;
                max-width: 80%;
            `;
            document.body.appendChild(notification);
        }
        if (notification.timeoutId) {
            clearTimeout(notification.timeoutId);
            notification.style.bottom = '0px';
            notification.style.opacity = '0';
        }

        notification.textContent = message;
        setTimeout(() => {
            notification.style.opacity = '1';
            notification.style.bottom = '20px';
        }, 50);


        notification.timeoutId = setTimeout(() => {
            notification.style.opacity = '0';
            notification.style.bottom = '0px';
            setTimeout(() => {
                if (notification.parentNode) {
                    notification.parentNode.removeChild(notification);
                }
                notification.timeoutId = null;
            }, 400);
        }, 2500);
    }


    // --- 菜单命令函数 ---
    function registerMenuCommands() {
        menu_ID.forEach(id => GM_unregisterMenuCommand(id));
        menu_ID = [];

        console.log(`${SCRIPT_PREFIX} 注册(不可用)菜单命令...`);
        menu_ALL.forEach(item => {
            const settingKey = item[0];
            const baseMenuText = item[1];

            if (settingKey === "toggleAllDisplays") {
                const displaySettingsKeys = [
                    "showUserPrompts", "showThinkingProcess", "showAIMessages",
                    "showInputBox", "showTopNavBar", "showChatTitleBar"
                ];
                const allEnabled = displaySettingsKeys.every(key => settings[key]);
                const menuText = `${allEnabled ? MENU_TEXT_HIDE_ALL : MENU_TEXT_SHOW_ALL} (${baseMenuText})`;
                menu_ID.push(GM_registerMenuCommand(menuText, toggleAllDisplays));
            } else {
                if (settings.hasOwnProperty(settingKey)) {
                    const currentSettingValue = settings[settingKey];
                    const menuText = `${currentSettingValue ? MENU_TEXT_DISABLED : MENU_TEXT_ENABLED} ${baseMenuText}`;
                    menu_ID.push(GM_registerMenuCommand(
                        menuText,
                        () => menuSwitch(settingKey)
                    ));
                } else {
                    console.warn(`${SCRIPT_PREFIX} 注册(不可用)菜单时未找到设置键 "${settingKey}".`);
                }
            }
        });
        console.log(`${SCRIPT_PREFIX} 菜单命令已注册(不可用).`);
    }

    function menuSwitch(settingKey) {
        let newValue = !settings[settingKey];
        settings[settingKey] = newValue;
        GM_setValue(settingKey, newValue);
        console.log(`${SCRIPT_PREFIX} 已切换 ${settingKey} 至 ${newValue}`);

        const menuItem = menu_ALL.find(item => item[0] === settingKey);
        if (!menuItem) {
            console.error(`${SCRIPT_PREFIX} 未能找到设置键的菜单项: ${settingKey}`);
            return;
        }
        const baseMenuText = menuItem[1];

        if (['useCustomStyles', 'showUserPrompts', 'showThinkingProcess', 'showAIMessages', 'showInputBox', 'showTopNavBar', 'showChatTitleBar'].includes(settingKey)) {
            updateStyles();
        } else if (settingKey === 'autoCollapseRightPanel') {
            if (newValue) {
                console.log(`${SCRIPT_PREFIX} 自动折叠右侧面板已启用, 尝试初始检查/点击.`);
                setTimeout(triggerAutoCollapseRightPanelIfNeeded, 500);
            }
        } else if (settingKey === 'autoCollapseLeftPanel') {
            if (newValue) {
                console.log(`${SCRIPT_PREFIX} 自动折叠左侧面板已启用, 尝试折叠.`);
                setTimeout(triggerAutoCollapseLeftPanelIfNeeded, 500);
            }
        }

        registerMenuCommands();
        showNotification(`${baseMenuText} ${newValue ? '已启用' : '已禁用'}`);
    }

    function toggleAllDisplays() {
        const displaySettingsKeys = [
            "showUserPrompts", "showThinkingProcess", "showAIMessages",
            "showInputBox", "showTopNavBar", "showChatTitleBar"
        ];
        const enableAll = !displaySettingsKeys.every(key => settings[key]);

        console.log(`${SCRIPT_PREFIX} 切换所有显示项至: ${enableAll ? '显示' : '隐藏'}`);
        displaySettingsKeys.forEach(key => {
            if (settings.hasOwnProperty(key)) {
                settings[key] = enableAll;
                GM_setValue(key, enableAll);
            } else {
                console.warn(`${SCRIPT_PREFIX} 切换所有显示项时未找到设置键 "${key}".`);
            }
        });

        updateStyles();
        registerMenuCommands();
        showNotification(`所有显示项 ${enableAll ? '已启用 (显示)' : '已禁用 (隐藏)'}`);
    }

    // --- 自动折叠右侧面板逻辑 ---
    const RUN_SETTINGS_BUTTON_SELECTOR = '.toggles-container button[aria-label="Run settings"], .toggles-container button[aria-label="运行设置"]';
    const RIGHT_PANEL_TAG_NAME = 'MS-RIGHT-SIDE-PANEL';
    const NGTNS_REGEX = /ng-tns-c\d+-\d+/;

    let lastNgTnsClass = null;
    let clickDebounceTimeoutRight = null;
    let panelObserver = null;

    function clickRunSettingsButton() {
        if (clickDebounceTimeoutRight) {
            clearTimeout(clickDebounceTimeoutRight);
            clickDebounceTimeoutRight = null;
        }
        if (!settings.autoCollapseRightPanel) return;

        const button = document.querySelector(RUN_SETTINGS_BUTTON_SELECTOR);
        if (button) {
            const style = window.getComputedStyle(button);
            const panel = button.closest(RIGHT_PANEL_TAG_NAME);
            if (panel && style.display !== 'none' && style.visibility !== 'hidden' && !button.disabled) {
                if (getNgTnsClass(panel)) {
                    console.log(`${SCRIPT_PREFIX} 自动折叠右侧面板: 点击 "运行设置" 按钮.`);
                    button.click();
                }
            }
        }
    }

    function getNgTnsClass(element) {
        if (!element || !element.classList) return null;
        for (const className of element.classList) {
            if (NGTNS_REGEX.test(className)) {
                return className;
            }
        }
        return null;
    }

    function triggerAutoCollapseRightPanelIfNeeded() {
        if (!settings.autoCollapseRightPanel) return;
        const panel = document.querySelector(RIGHT_PANEL_TAG_NAME);
        if (panel) {
            const currentNgTnsClass = getNgTnsClass(panel);
            if (currentNgTnsClass && (!lastNgTnsClass || currentNgTnsClass !== lastNgTnsClass)) {
                lastNgTnsClass = currentNgTnsClass;
                if (clickDebounceTimeoutRight) clearTimeout(clickDebounceTimeoutRight);
                clickDebounceTimeoutRight = setTimeout(clickRunSettingsButton, 300);
            } else if (!currentNgTnsClass && lastNgTnsClass) {
                lastNgTnsClass = null;
            }
        } else {
            lastNgTnsClass = null;
        }
    }

    const panelObserverCallback = function(mutationsList, observer) {
        if (!settings.autoCollapseRightPanel) return;
        let panelPotentiallyChanged = false;
        for (const mutation of mutationsList) {
            if (mutation.type === 'attributes' &&
                mutation.attributeName === 'class' &&
                mutation.target.tagName === RIGHT_PANEL_TAG_NAME) {
                const targetPanel = mutation.target;
                const currentNgTnsClass = getNgTnsClass(targetPanel);
                if (currentNgTnsClass && currentNgTnsClass !== lastNgTnsClass) {
                    lastNgTnsClass = currentNgTnsClass;
                    panelPotentiallyChanged = true;
                    break;
                } else if (!currentNgTnsClass && lastNgTnsClass) {
                    lastNgTnsClass = null;
                }
            } else if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                for (const node of mutation.addedNodes) {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        let potentialPanel = null;
                        if (node.tagName === RIGHT_PANEL_TAG_NAME) potentialPanel = node;
                        else if (node.querySelector) potentialPanel = node.querySelector(RIGHT_PANEL_TAG_NAME);

                        if (potentialPanel) {
                            const currentNgTnsClass = getNgTnsClass(potentialPanel);
                            if (currentNgTnsClass && (!lastNgTnsClass || currentNgTnsClass !== lastNgTnsClass) ) {
                                lastNgTnsClass = currentNgTnsClass;
                                panelPotentiallyChanged = true;
                            }
                            if (panelPotentiallyChanged) break;
                        }
                    }
                }
                if (panelPotentiallyChanged) break;
            }
        }

        if (panelPotentiallyChanged) {
            if (clickDebounceTimeoutRight) clearTimeout(clickDebounceTimeoutRight);
            clickDebounceTimeoutRight = setTimeout(clickRunSettingsButton, 300);
        }
    };

    function initializePanelObserver() {
        if (panelObserver) panelObserver.disconnect();
        const observerConfig = {
            attributes: true, attributeFilter: ['class'],
            childList: true, subtree: true
        };
        panelObserver = new MutationObserver(panelObserverCallback);
        panelObserver.observe(document.body, observerConfig);
        console.log(`${SCRIPT_PREFIX} 右侧面板 MutationObserver 已启动.`);
    }

    // --- 自动折叠左侧面板逻辑 ---
    const LEFT_PANEL_TOGGLE_BUTTON_SELECTOR = '.navbar-content-wrapper button[aria-label="Expand or collapse navigation menu"], .navbar-content-wrapper button[aria-label="展开或收起导航菜单"]';
    const LEFT_PANEL_EXPANDED_CLASS = 'sidenav-opened';
    let clickDebounceTimeoutLeft = null;

    function clickLeftPanelToggleButton() {
        if (clickDebounceTimeoutLeft) {
            clearTimeout(clickDebounceTimeoutLeft);
            clickDebounceTimeoutLeft = null;
        }
        if (!settings.autoCollapseLeftPanel) {
            return;
        }

        const button = document.querySelector(LEFT_PANEL_TOGGLE_BUTTON_SELECTOR);
        if (button && document.body.classList.contains(LEFT_PANEL_EXPANDED_CLASS)) {
            console.log(`${SCRIPT_PREFIX} 自动折叠左侧面板: 点击切换按钮.`);
            button.click();
        } else if (!button) {
             console.log(`${SCRIPT_PREFIX} 自动折叠左侧: 未找到切换按钮.`);
        }
    }

    function triggerAutoCollapseLeftPanelIfNeeded() {
        if (!settings.autoCollapseLeftPanel) return;
        if (clickDebounceTimeoutLeft) clearTimeout(clickDebounceTimeoutLeft);
        clickDebounceTimeoutLeft = setTimeout(clickLeftPanelToggleButton, 200);
    }

    // --- 脚本初始化 ---
    function initializeScript() {
        console.log(`${SCRIPT_PREFIX} 正在运行初始化...`);
        updateStyles();
        registerMenuCommands();
        initializePanelObserver();

        setTimeout(() => {
            if (settings.autoCollapseLeftPanel) {
                triggerAutoCollapseLeftPanelIfNeeded();
            }
        }, 1500);

        setTimeout(() => {
            if (settings.autoCollapseRightPanel) {
                const panel = document.querySelector(RIGHT_PANEL_TAG_NAME);
                if (panel) {
                    const initialNgTns = getNgTnsClass(panel);
                    if (initialNgTns) {
                        lastNgTnsClass = initialNgTns;
                        triggerAutoCollapseRightPanelIfNeeded();
                    } else {
                        lastNgTnsClass = null;
                    }
                } else {
                     lastNgTnsClass = null;
                }
            }
        }, 1800);


        console.log(`${SCRIPT_PREFIX} 初始化完成.`);
    }

    // --- 启动脚本 ---
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initializeScript);
    } else {
        initializeScript();
    }

    window.addEventListener('unload', () => {
        if (panelObserver) {
            panelObserver.disconnect();
            console.log(`${SCRIPT_PREFIX} 右侧面板 MutationObserver 已断开.`);
        }
        if (clickDebounceTimeoutRight) clearTimeout(clickDebounceTimeoutRight);
        if (clickDebounceTimeoutLeft) clearTimeout(clickDebounceTimeoutLeft);
        const notification = document.getElementById('enhancer-notification');
        if (notification && notification.timeoutId) {
            clearTimeout(notification.timeoutId);
        }
    });

})();

QingJ © 2025

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