// ==UserScript== // @name ChatGPT长对话加速 // @namespace npm/chatgpt-conversation-speedup // @version 1.0 // @description 通过智能隐藏旧对话节点,显著降低 ChatGPT 长对话页面的内存占用与渲染卡顿。提供“加速”开关,开启后仅保留最近的对话内容,关闭后瞬间恢复全部历史。安全无损,不修改网页内容。 // @match https://chatgpt.com/* // @grant none // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/564338/ChatGPT%E9%95%BF%E5%AF%B9%E8%AF%9D%E5%8A%A0%E9%80%9F.user.js // @updateURL https://update.greasyfork.icu/scripts/564338/ChatGPT%E9%95%BF%E5%AF%B9%E8%AF%9D%E5%8A%A0%E9%80%9F.meta.js // ==/UserScript== (function () { 'use strict'; /** * Configuration Constants * 可动态修改的状态参数 */ let KEEP_VISIBLE = 8; let HIDE_BEYOND = 10; let IS_OPTIMIZED = true; // 默认开启优化 const BOOT_CHECK_INTERVAL = 500; /** * LocalStorage Key * UI 状态持久化键名 */ const UI_STATE_KEY = 'cgpt_pruner_ui_state_v2'; /** * Get Conversation Turns * 获取当前页面所有的对话节点DOM */ function getTurns() { return Array.from( document.querySelectorAll('article[data-testid^="conversation-turn"]') ); } /** * Prune / Optimize Logic * 核心优化逻辑:通过 display:none 隐藏非活跃区的对话节点 */ function prune() { const turns = getTurns(); const total = turns.length; // 如果未开启优化,或者数量未达到阈值,则全部显示 if (!IS_OPTIMIZED || total <= HIDE_BEYOND) { turns.forEach(el => { if (el.style.display === 'none') el.style.display = ''; }); return; } // 开启优化:隐藏旧消息 const hideBefore = total - KEEP_VISIBLE; for (let i = 0; i < total; i++) { const el = turns[i]; if (i < hideBefore) { if (el.style.display !== 'none') el.style.display = 'none'; } else { if (el.style.display === 'none') el.style.display = ''; } } } /** * Start Observer * 启动 DOM 监听,当新消息出现时触发优化 */ function startObserver() { const observer = new MutationObserver(prune); observer.observe(document.body, { childList: true, subtree: true }); console.log('[ChatGPT Speedup] Observer started'); } /** * Wait for Chat Load * 等待对话加载完成后初始化 */ function waitForChat() { const timer = setInterval(() => { if (getTurns().length > 0) { clearInterval(timer); prune(); startObserver(); } }, BOOT_CHECK_INTERVAL); } /** * Create Settings Panel * 创建配置面板 (Shadow DOM isolated) */ function createPanel() { const host = document.createElement('div'); host.style.position = 'fixed'; host.style.bottom = '20px'; host.style.right = '20px'; host.style.zIndex = '10000'; // Ensure visibility document.body.appendChild(host); const shadow = host.attachShadow({ mode: 'open' }); shadow.innerHTML = `
加速开关
保留最近
优化阈值
`; const $ = (id) => shadow.getElementById(id); function setMinimized(minimized) { $('panel').classList.toggle('hidden', minimized); $('mini').classList.toggle('hidden', !minimized); updateMiniDot(); saveState(); } function updateMiniDot() { if (IS_OPTIMIZED) $('miniDot').classList.remove('off'); else $('miniDot').classList.add('off'); } function saveState() { const state = { minimized: $('panel').classList.contains('hidden'), optimized: IS_OPTIMIZED, keep: KEEP_VISIBLE, threshold: HIDE_BEYOND }; localStorage.setItem(UI_STATE_KEY, JSON.stringify(state)); } function loadState() { try { const raw = localStorage.getItem(UI_STATE_KEY); if (raw) { const state = JSON.parse(raw); setMinimized(state.minimized); IS_OPTIMIZED = state.optimized; KEEP_VISIBLE = state.keep; HIDE_BEYOND = state.threshold; } else { setMinimized(false); // Default open first time } } catch (e) { console.error('Load state failed', e); } } // Apply Logic function applySettings() { IS_OPTIMIZED = $('masterToggle').checked; KEEP_VISIBLE = parseInt($('keepVisible').value, 10) || 8; HIDE_BEYOND = parseInt($('hideBeyond').value, 10) || 10; prune(); updateMiniDot(); saveState(); } // Events $('masterToggle').onchange = applySettings; // Instant toggle $('keepVisible').onchange = applySettings; // Auto apply $('hideBeyond').onchange = applySettings; // Auto apply $('minBtn').onclick = () => setMinimized(true); $('mini').onclick = () => setMinimized(false); // Init loadState(); // Sync UI with loaded state $('masterToggle').checked = IS_OPTIMIZED; $('keepVisible').value = KEEP_VISIBLE; $('hideBeyond').value = HIDE_BEYOND; updateMiniDot(); // Initial Prune prune(); } waitForChat(); createPanel(); })();