您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a smart scroll button for easy navigation in AI chat interfaces
当前为
// ==UserScript== // @name ChatGPT/GROK/DEEPSEEK Scroll Navigator // @namespace http://tampermonkey.net/ // @version 0.1 // @description Adds a smart scroll button for easy navigation in AI chat interfaces // @author Lepturus // @match *://chatgpt.com/* // @match *://chat.deepseek.com/* // @match *://grok.com/* // @icon https://chatgpt.com/favicon.ico // @grant GM_addStyle // @license MIT // ==/UserScript== (function() { 'use strict'; // Configuration for different platforms const platformConfig = { chatgpt: { container: '.flex.basis-auto.flex-col.grow.overflow-hidden div.relative.h-full div.overflow-y-auto', name: 'ChatGPT' }, grok: { container: '.scrollbar-gutter-stable', name: 'Grok' }, deepseek: { container: '.scrollable', name: 'DeepSeek' } }; // Main initialization function function initScrollNavigator() { let currentPlatform = null; // Determine current platform if (/chatgpt/.test(location.hostname)) currentPlatform = 'chatgpt'; else if (/grok/.test(location.hostname)) currentPlatform = 'grok'; else if (/deepseek/.test(location.hostname)) currentPlatform = 'deepseek'; if (!currentPlatform) return; const config = platformConfig[currentPlatform]; let scrollButton = null; let chatContainer = null; let isInitialized = false; // Create scroll button function createScrollButton() { if (document.getElementById('scrollNavigatorBtn')) return; scrollButton = document.createElement('div'); scrollButton.id = 'scrollNavigatorBtn'; scrollButton.innerHTML = '⬆'; scrollButton.title = `Scroll to bottom (${config.name})`; // Apply styles Object.assign(scrollButton.style, { position: 'fixed', bottom: '20px', right: '20px', width: '45px', height: '45px', lineHeight: '45px', textAlign: 'center', backgroundColor: 'rgba(0, 0, 0, 0.7)', color: 'white', borderRadius: '50%', fontSize: '24px', cursor: 'pointer', zIndex: '10000', opacity: '0', transition: 'opacity 0.3s, transform 0.2s', transform: 'scale(0.8)', pointerEvents: 'none', boxShadow: '0 2px 10px rgba(0,0,0,0.3)' }); document.body.appendChild(scrollButton); // Button click handler scrollButton.addEventListener('click', handleScrollClick); // Mouse events for showing/hiding scrollButton.addEventListener('mouseenter', () => { scrollButton.style.opacity = '1'; scrollButton.style.transform = 'scale(1)'; }); scrollButton.addEventListener('mouseleave', () => { if (!isMouseNearButton()) { scrollButton.style.opacity = '0'; scrollButton.style.transform = 'scale(0.8)'; } }); // Show button when mouse approaches screen edge document.addEventListener('mousemove', (e) => { const rect = scrollButton.getBoundingClientRect(); const buttonCenterX = rect.left + rect.width / 2; const buttonCenterY = rect.top + rect.height / 2; const distance = Math.sqrt( Math.pow(e.clientX - buttonCenterX, 2) + Math.pow(e.clientY - buttonCenterY, 2) ); if (distance < 120) { scrollButton.style.opacity = '1'; scrollButton.style.transform = 'scale(1)'; scrollButton.style.pointerEvents = 'auto'; } else if (distance > 150 && !scrollButton.matches(':hover')) { scrollButton.style.opacity = '0'; scrollButton.style.transform = 'scale(0.8)'; scrollButton.style.pointerEvents = 'none'; } }); } // Check if mouse is near button function isMouseNearButton() { const rect = scrollButton.getBoundingClientRect(); const buttonCenterX = rect.left + rect.width / 2; const buttonCenterY = rect.top + rect.height / 2; return (event) => { const distance = Math.sqrt( Math.pow(event.clientX - buttonCenterX, 2) + Math.pow(event.clientY - buttonCenterY, 2) ); return distance < 100; }; } // Handle scroll button click function handleScrollClick() { if (!chatContainer) return; const isNearTop = chatContainer.scrollTop < 100; if (isNearTop) { chatContainer.scrollTo({ top: chatContainer.scrollHeight, behavior: 'smooth' }); scrollButton.innerHTML = '⬆'; scrollButton.title = 'Scroll to top'; } else { chatContainer.scrollTo({ top: 0, behavior: 'smooth' }); scrollButton.innerHTML = '⬇'; scrollButton.title = 'Scroll to bottom'; } } // Find chat container function findChatContainer() { try { if (currentPlatform === 'deepseek') { const containers = document.querySelectorAll(config.container); if (containers.length > 1) return containers[1]; return containers[0]; } return document.querySelector(config.container); } catch (error) { console.error('Error finding chat container:', error); return null; } } // Update button state based on scroll position function updateButtonState() { if (!chatContainer || !scrollButton) return; const scrollThreshold = 100; const isNearTop = chatContainer.scrollTop < scrollThreshold; const isNearBottom = chatContainer.scrollHeight - chatContainer.scrollTop - chatContainer.clientHeight < scrollThreshold; if (isNearTop) { scrollButton.innerHTML = '⬇'; scrollButton.title = 'Scroll to bottom'; } else if (isNearBottom) { scrollButton.innerHTML = '⬆'; scrollButton.title = 'Scroll to top'; } else { scrollButton.innerHTML = '⬇'; scrollButton.title = 'Scroll to bottom'; } } // Initialize the script function initialize() { if (isInitialized) return; chatContainer = findChatContainer(); if (!chatContainer) { setTimeout(initialize, 1000); return; } createScrollButton(); // Add scroll listener to update button state chatContainer.addEventListener('scroll', updateButtonState); // Initial update updateButtonState(); isInitialized = true; console.log(`Scroll Navigator initialized for ${config.name}`); } // Start initialization initialize(); // Reinitialize if DOM changes (for SPA navigation) const observer = new MutationObserver(() => { if (!chatContainer || !document.contains(chatContainer)) { isInitialized = false; chatContainer = null; initialize(); } }); observer.observe(document.body, { childList: true, subtree: true }); } // Start when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initScrollNavigator); } else { initScrollNavigator(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址