您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在Gemini对话页面添加导航按钮:上下切换AI回答,一键到顶部/底部
// ==UserScript== // @name Gemini - Quick Navigation for AI Conversations // @name:zh-CN Gemini - AI对话快速导航 // @namespace http://tampermonkey.net/ // @version 5.1 // @description Add navigation buttons to the Gemini conversation page: switch up and down between AI answers, and jump to the top/bottom with one click // @description:zh-CN 在Gemini对话页面添加导航按钮:上下切换AI回答,一键到顶部/底部 // @author Epodak // @match https://gemini.google.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=gemini.google.com // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // 创建样式 const style = document.createElement('style'); style.textContent = ` .nav-buttons-container { position: fixed; right: 20px; top: 50%; transform: translateY(-50%); z-index: 10000; display: flex; flex-direction: column; gap: 10px; } .nav-button { width: 48px; height: 48px; border-radius: 50%; border: 2px solid #4285f4; background: white; color: #4285f4; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: bold; transition: all 0.3s ease; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .extreme-button { width: 40px; height: 40px; font-size: 16px; border-color: #ea4335; } .extreme-button:hover { background: #ea4335; color: white; } .nav-button:hover { background: #4285f4; color: white; transform: scale(1.1); } .nav-button.disabled { opacity: 0.5; pointer-events: none; } `; document.head.appendChild(style); // 创建按钮 const navContainer = document.createElement('div'); navContainer.className = 'nav-buttons-container'; const topButton = document.createElement('div'); topButton.className = 'nav-button extreme-button'; topButton.innerHTML = '⤴'; topButton.title = '跳转到顶部'; const upButton = document.createElement('div'); upButton.className = 'nav-button'; upButton.innerHTML = '↑'; upButton.title = '上一个AI回答'; const downButton = document.createElement('div'); downButton.className = 'nav-button'; downButton.innerHTML = '↓'; downButton.title = '下一个AI回答'; const bottomButton = document.createElement('div'); bottomButton.className = 'nav-button extreme-button'; bottomButton.innerHTML = '⤵'; bottomButton.title = '跳转到底部'; navContainer.append(topButton, upButton, downButton, bottomButton); document.body.appendChild(navContainer); // 获取所有AI回答 function getAllResponses() { return Array.from(document.querySelectorAll('model-response')); } // 获取当前中心的AI回答 function getCurrentResponse() { const responses = getAllResponses(); if (!responses.length) return null; const center = window.innerHeight / 2; let closest = responses[0]; let minDistance = Infinity; for (const response of responses) { const rect = response.getBoundingClientRect(); const distance = Math.abs(rect.top + rect.height / 2 - center); if (distance < minDistance) { minDistance = distance; closest = response; } } return closest; } // 跳转到指定回答 function scrollTo(response) { if (response) { response.scrollIntoView({ behavior: 'smooth', block: 'start' }); } } // 上一个回答 function goPrevious() { const responses = getAllResponses(); if (!responses.length) return; const current = getCurrentResponse(); const index = responses.indexOf(current); if (index > 0) { scrollTo(responses[index - 1]); } else { window.scrollTo({ top: 0, behavior: 'smooth' }); } } // 下一个回答 function goNext() { const responses = getAllResponses(); if (!responses.length) return; const current = getCurrentResponse(); const index = responses.indexOf(current); if (index < responses.length - 1) { scrollTo(responses[index + 1]); } } // 查找实际的滚动容器 function findScrollContainer() { // 从model-response元素向上查找有滚动的父容器 const firstResponse = document.querySelector('model-response'); if (firstResponse) { let element = firstResponse.parentElement; while (element && element !== document.body) { const hasScroll = element.scrollHeight > element.clientHeight; const overflowY = window.getComputedStyle(element).overflowY; if (hasScroll && (overflowY === 'auto' || overflowY === 'scroll')) { return element; } element = element.parentElement; } } return null; } // 跳转到顶部 function goTop() { const scrollContainer = findScrollContainer(); if (scrollContainer) { scrollContainer.scrollTop = 0; } else { window.scrollTo({ top: 0, behavior: 'auto' }); } } // 跳转到底部(优化版:先快速到底部,再定位到最后AI回答) function goBottom() { // 1. 先快速跳转到页面最底部(模拟End键) const scrollContainer = findScrollContainer(); if (scrollContainer) { scrollContainer.scrollTop = scrollContainer.scrollHeight; } else { window.scrollTo({ top: document.body.scrollHeight, behavior: 'auto' }); } // 2. 等待一下让内容加载,然后定位到最后一个AI回答 setTimeout(() => { const responses = getAllResponses(); if (responses.length > 0) { scrollTo(responses[responses.length - 1]); } }, 200); } // 更新按钮状态 function updateButtons() { const responses = getAllResponses(); const current = getCurrentResponse(); if (!responses.length || !current) { upButton.classList.add('disabled'); downButton.classList.add('disabled'); return; } const index = responses.indexOf(current); // 只有在页面顶部且是第一个回答时禁用上一个按钮 upButton.classList.toggle('disabled', window.scrollY <= 10 && index === 0); // 下一个按钮基本不禁用 downButton.classList.remove('disabled'); // TOP和BOTTOM按钮始终可用 topButton.classList.remove('disabled'); bottomButton.classList.remove('disabled'); } // 事件监听 topButton.onclick = goTop; upButton.onclick = goPrevious; downButton.onclick = goNext; bottomButton.onclick = goBottom; // 滚动监听 let timer; window.addEventListener('scroll', () => { clearTimeout(timer); timer = setTimeout(updateButtons, 100); }); // DOM变化监听 new MutationObserver(() => { setTimeout(updateButtons, 200); }).observe(document.body, { childList: true, subtree: true }); // 键盘快捷键 document.addEventListener('keydown', (e) => { if (e.target.matches('input, textarea, [contenteditable="true"]')) return; if ((e.ctrlKey || e.metaKey) && e.key === 'ArrowUp') { e.preventDefault(); goPrevious(); } if ((e.ctrlKey || e.metaKey) && e.key === 'ArrowDown') { e.preventDefault(); goNext(); } // 移除Ctrl+Home快捷键,因为它在Gemini中不工作 // 保留Ctrl+End是为了与goBottom功能一致 if ((e.ctrlKey || e.metaKey) && e.key === 'End') { e.preventDefault(); goBottom(); } }); // 初始化 setTimeout(updateButtons, 1000); })();