logo NodeSeekbeta

(脚本分享)我套我自己之套娃专家:让Gemini写了一个油猴脚本,让Gemini更好用。

一开始用Gemini的时候发现回车键只能发送,让我习惯了ctrl+回车发送的微信打工人深恶痛绝。
遂用Gemini写了一个油猴的脚本用来更好的使用Gemini(师夷长技以制夷)。 xhj001
搞了20个版本的迭代和修复,现在比较稳定,分享给各位大佬,也请多提出宝贵意见可以增加功能。
xhj009 xhj009

【核心功能】

1. 📜 智能滚动系统

  • 自动滚动 (Auto-Scroll):检测到 AI 正在生成内容时,屏幕瞬间锁定底部,解放双手,不用再疯狂滑滚轮了。
  • 回到最下:一键直达对话底部(采用全覆盖算法,兼容所有 Gemini 页面结构)。

2. ⌨️ 输入体验增强

  • 回车 (Enter):强制换行(拒绝误触发送)。
  • Ctrl + Enter:发送消息。
  • Tab 重命名:标签页标题自动变更为当前对话主题,多开不迷路。

3. 🎨 颜值与交互

  • 多主题切换:下拉选择 ⬜极简🤖赛博朋克🧸糖果卡通🖌️水墨中国 四大主题。
  • 水滴悬浮球:面板最小化后变成一颗炫酷的“水滴球”,支持全屏拖动,位置自动记忆。
  • 磨砂玻璃:UI 采用高级毛玻璃特效,视觉舒适。

4. 🚀 效率工具

  • 纯净复制:一键提取 AI 回复,自动去除 **## 等 Markdown 符号,文案直接用。
  • 宽屏模式:一键隐藏侧边栏,将对话区拉伸至 90%,看代码极爽。
  • 智能大纲:自动提取长回复的标题(H1-H3),生成可折叠的目录导航。
  • 护眼模式:内置豆沙绿、护眼黄、夜间灰三种滤镜。

【安装方式】

  1. 安装 Tampermonkey 插件。
  2. 新建脚本,粘贴代码保存即可。
// ==UserScript==
// @name         Gemni GG-BOOM V.20.0 (滚动终极版)
// @namespace    http://tampermonkey.net/
// @version      20.0
// @description  V20里程碑:全覆盖滚动算法,确保自动滚动生效。含多主题、下拉切换、大纲、纯净复制。
// @author       cshaizhihao
// @match        https://gemini.google.com/*
// @grant        GM_addStyle
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';
	
    console.log("🌊 GG-BOOM V20.0: 滚动引擎已升级");

    // --- 1. CSS 样式 (保持 V19 美学) ---
    const css = `
        :root { --gg-bg:#111; --gg-border:#333; --gg-text:#eee; --gg-accent:#fff; --gg-btn-bg:#222; --gg-btn-hover:#333; --gg-radius:4px; --gg-shadow:0 0 0 1px #333; --gg-font:sans-serif; --gg-title-grad:#fff; --gg-blur:0px; --gg-pattern:none; --gg-glow:none; }

        [data-gg-theme="minimal"] { --gg-bg:#1a1a1a; --gg-border:#333; --gg-text:#ccc; --gg-accent:#fff; --gg-btn-bg:#262626; --gg-btn-hover:#333; --gg-radius:6px; --gg-shadow:0 10px 30px rgba(0,0,0,0.5); --gg-font:-apple-system,system-ui,sans-serif; --gg-title-grad:#eee; --gg-blur:0px; }
        [data-gg-theme="cyber"] { --gg-bg:rgba(5,10,20,0.92); --gg-border:#0ff; --gg-text:#0ff; --gg-accent:#f0f; --gg-btn-bg:rgba(0,255,255,0.05); --gg-btn-hover:rgba(0,255,255,0.2); --gg-radius:2px; --gg-shadow:0 0 15px rgba(0,255,255,0.3),inset 0 0 20px rgba(0,0,0,0.8); --gg-font:"Courier New",monospace; --gg-title-grad:linear-gradient(90deg,#f0f,#0ff); --gg-blur:4px; --gg-glow:0 0 5px #0ff; --gg-pattern:linear-gradient(0deg,transparent 24%,rgba(0,255,255,0.05) 25%,rgba(0,255,255,0.05) 26%,transparent 27%,transparent 74%,rgba(0,255,255,0.05) 75%,rgba(0,255,255,0.05) 76%,transparent 77%,transparent); background-size:50px 50px; }
        [data-gg-theme="cartoon"] { --gg-bg:rgba(255,245,248,0.95); --gg-border:#FFB7B2; --gg-text:#666; --gg-accent:#FF9A9E; --gg-btn-bg:#fff; --gg-btn-hover:#FFF0F5; --gg-radius:20px; --gg-shadow:5px 5px 0px rgba(255,183,178,0.6); --gg-font:"Varela Round","幼圆",sans-serif; --gg-title-grad:linear-gradient(45deg,#FF9A9E,#FECFEF); --gg-blur:0px; --gg-pattern:radial-gradient(#FFB7B2 20%,transparent 20%) 0 0,radial-gradient(#FFB7B2 20%,transparent 20%) 8px 8px; background-size:16px 16px; }
        [data-gg-theme="ink"] { --gg-bg:rgba(250,249,246,0.95); --gg-border:#666; --gg-text:#2c2c2c; --gg-accent:#B22222; --gg-btn-bg:rgba(0,0,0,0.03); --gg-btn-hover:rgba(0,0,0,0.08); --gg-radius:4px; --gg-shadow:0 10px 40px rgba(0,0,0,0.2); --gg-font:"Kaiti","STKaiti","楷体",serif; --gg-title-grad:#000; --gg-blur:8px; --gg-pattern:url('data:image/svg+xml;utf8,<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><g fill="%23000" fill-opacity="0.03"><circle cx="50" cy="50" r="40"/><circle cx="20" cy="20" r="10"/></g></svg>'); }

        #gg-panel-v20 { position:fixed; width:300px; background-color:var(--gg-bg); background-image:var(--gg-pattern); backdrop-filter:blur(var(--gg-blur)); -webkit-backdrop-filter:blur(var(--gg-blur)); border:1px solid var(--gg-border); border-radius:var(--gg-radius); padding:15px; z-index:2147483647; box-shadow:var(--gg-shadow); font-family:var(--gg-font); color:var(--gg-text); display:flex; flex-direction:column; gap:10px; transition:all 0.3s ease; user-select:none; }
        .gg-header { display:flex; justify-content:space-between; align-items:center; border-bottom:1px solid var(--gg-border); padding-bottom:10px; cursor:move; }
        .gg-title { font-size:15px; font-weight:900; background:var(--gg-title-grad); -webkit-background-clip:text; -webkit-text-fill-color:transparent; text-shadow:var(--gg-glow); pointer-events:none; }
        .gg-min-btn { cursor:pointer; padding:2px 8px; font-size:16px; color:var(--gg-text); opacity:0.6; } .gg-min-btn:hover { opacity:1; transform:scale(1.1); }
        .gg-select { width:100%; padding:6px; border-radius:var(--gg-radius); background:var(--gg-btn-bg); border:1px solid var(--gg-border); color:var(--gg-text); font-family:var(--gg-font); font-size:12px; cursor:pointer; outline:none; margin-top:5px; } .gg-select option { background:#222; color:#fff; } [data-gg-theme="cartoon"] .gg-select option, [data-gg-theme="ink"] .gg-select option { background:#fff; color:#333; }
        .gg-label { font-size:11px; color:var(--gg-text); opacity:0.7; font-weight:bold; pointer-events:none; margin-top:8px; }
        .gg-grid { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:5px; }
        .gg-btn { background:var(--gg-btn-bg); border:1px solid var(--gg-border); color:var(--gg-text); padding:8px; border-radius:var(--gg-radius); cursor:pointer; font-size:12px; text-align:center; display:flex; align-items:center; justify-content:center; transition:0.2s; } .gg-btn:hover { background:var(--gg-btn-hover); transform:translateY(-1px); border-color:var(--gg-accent); } .gg-btn.active { border-color:var(--gg-accent); color:var(--gg-accent); font-weight:bold; box-shadow:inset 0 0 5px var(--gg-accent); }
        #gg-outline-box { background:rgba(0,0,0,0.03); border:1px solid var(--gg-border); border-radius:var(--gg-radius); padding:5px; max-height:120px; overflow-y:auto; list-style:none; margin-top:5px; font-size:12px; color:var(--gg-text); display:block; }
        .gg-outline-item { padding:4px; border-radius:4px; cursor:pointer; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; opacity:0.8; } .gg-outline-item:hover { background:var(--gg-btn-hover); opacity:1; color:var(--gg-accent); }
        .gg-chip-area { display:flex; flex-wrap:wrap; gap:5px; margin-top:5px; }
        .gg-chip { background:var(--gg-btn-bg); border:1px solid var(--gg-border); padding:4px 10px; border-radius:20px; font-size:13px; cursor:pointer; color:var(--gg-text); opacity:0.9; } .gg-chip:hover { border-color:var(--gg-accent); color:var(--gg-accent); transform:scale(1.05); }
        #gg-float-ball { position:fixed; width:50px; height:50px; border-radius:50%; z-index:2147483647; cursor:pointer; display:none; align-items:center; justify-content:center; font-weight:900; font-size:12px; color:#fff; background:var(--gg-accent); box-shadow:0 4px 15px var(--gg-accent); border:2px solid rgba(255,255,255,0.3); opacity:0.8; transition:opacity 0.3s, transform 0.2s; } #gg-float-ball:hover { opacity:1; transform:scale(1.1); } #gg-float-ball.dragging { opacity:1; cursor:move; }
        .gg-footer { font-size:10px; color:var(--gg-text); opacity:0.5; text-align:center; margin-top:10px; border-top:1px solid var(--gg-border); padding-top:8px; }
        body.gg-wide-mode sidenav { display:none !important; } body.gg-wide-mode .input-area-container, body.gg-wide-mode .conversation-container, body.gg-wide-mode .bottom-container { max-width:90% !important; margin:0 auto !important; }
        #gg-eye-overlay { position:fixed; top:0; left:0; width:100vw; height:100vh; pointer-events:none; z-index:2147483646; display:none; transition:background 0.3s; }
    `;
    const style = document.createElement('style'); style.innerText = css; document.head.appendChild(style);

    // --- 状态 ---
    let isHidden = false;
    let eyeMode = 0;
    let autoScroll = false;
    let outlineCollapsed = false;
    let currentTheme = localStorage.getItem('gg_theme_v20') || 'minimal';
    const themes = { 'minimal': '⬜ 极简主义 (Minimal)', 'cyber': '🤖 赛博朋克 (Cyberpunk)', 'cartoon': '🧸 糖果卡通 (Cartoon)', 'ink': '🖌️ 水墨中国 (Ink)' };

    // --- 滚动核心 (全覆盖算法) ---
    function forceScrollBottom(smooth) {
        // 1. 寻找所有可能的滚动容器
        const candidates = [
            document.querySelector('infinite-scroller'),
            document.querySelector('main'),
            document.querySelector('.conversation-container')?.parentElement,
            document.documentElement,
            document.body
        ];
        // 过滤出真正能滚动的元素
        const scrollers = candidates.filter(el => el && el.scrollHeight > el.clientHeight);

        if (scrollers.length > 0) {
            scrollers.forEach(el => {
                // 如果是平滑滚动(手动点击),用 smooth
                // 如果是自动跟手(Auto),用 instant (防止抖动)
                el.scrollTo({ top: el.scrollHeight, behavior: smooth ? 'smooth' : 'instant' });
            });
        }
    }

    // --- 拖动 ---
    function makeDraggable(el, handle = el) {
        let isDragging=false, startX, startY, initLeft, initTop, hasMoved=false;
        const saved = JSON.parse(localStorage.getItem('gg_pos_'+el.id));
        if(saved) { el.style.left=saved.left; el.style.top=saved.top; el.style.bottom='auto'; el.style.right='auto'; }
        else { el.style.bottom='30px'; el.style.right='30px'; }
        
        handle.addEventListener('mousedown', e=>{
            if(e.button!==0)return; isDragging=true; hasMoved=false;
            if(el.id==='gg-float-ball')el.classList.add('dragging');
            startX=e.clientX; startY=e.clientY;
            initLeft=el.getBoundingClientRect().left; initTop=el.getBoundingClientRect().top;
            el.style.transition='none';
        });
        window.addEventListener('mousemove', e=>{
            if(!isDragging)return; e.preventDefault();
            const dx=e.clientX-startX; const dy=e.clientY-startY;
            if(Math.abs(dx)>3||Math.abs(dy)>3)hasMoved=true;
            el.style.left=(initLeft+dx)+'px'; el.style.top=(initTop+dy)+'px';
            el.style.bottom='auto'; el.style.right='auto';
        });
        window.addEventListener('mouseup', ()=>{
            if(!isDragging)return; isDragging=false;
            if(el.id==='gg-float-ball')el.classList.remove('dragging');
            el.style.transition='';
            localStorage.setItem('gg_pos_'+el.id, JSON.stringify({left:el.style.left, top:el.style.top}));
            if(el.id==='gg-float-ball' && !hasMoved) togglePanel();
        });
    }

    // --- 交互 ---
    function togglePanel() {
        const p = document.getElementById('gg-panel-v20');
        const b = document.getElementById('gg-float-ball');
        isHidden = !isHidden;
        if(isHidden) {
            p.style.opacity='0'; p.style.transform='scale(0.9)'; setTimeout(()=>p.style.display='none',200);
            b.style.display='flex'; setTimeout(()=>b.style.transform='scale(1)',10);
        } else {
            b.style.transform='scale(0)'; setTimeout(()=>b.style.display='none',200);
            p.style.display='flex'; setTimeout(()=>{p.style.opacity='1'; p.style.transform='scale(1)';},10);
        }
    }

    // --- 功能 ---
    function switchTheme(k) {
        currentTheme = k; localStorage.setItem('gg_theme_v20', k);
        const p = document.getElementById('gg-panel-v20');
        if(p) {
            p.setAttribute('data-gg-theme', k);
            const b = document.getElementById('gg-float-ball');
            if(k==='minimal'||k==='ink') b.style.background='#333';
            else if(k==='cyber') b.style.background='#f0f';
            else if(k==='cartoon') b.style.background='#FF9A9E';
        }
    }
    function toggleWide(btn) {
        document.body.classList.toggle('gg-wide-mode');
        const v = document.body.classList.contains('gg-wide-mode');
        btn.innerText = v ? '🖥️ 宽屏: 开' : '🖥️ 宽屏: 关';
        if(v) btn.classList.add('active'); else btn.classList.remove('active');
    }
    function toggleEye(btn) {
        eyeMode=(eyeMode+1)%4;
        let ov=document.getElementById('gg-eye-overlay');
        if(!ov){ov=document.createElement('div');ov.id='gg-eye-overlay';document.body.appendChild(ov);}
        const m = [{t:'👁️ 护眼: 关',d:'none',c:''},{t:'👁️ 豆沙绿',d:'block',c:'#e8f5e9',x:'multiply'},{t:'👁️ 护眼黄',d:'block',c:'#fff3e0',x:'multiply'},{t:'👁️ 夜间灰',d:'block',c:'rgba(0,0,0,0.7)',x:'normal'}];
        const c=m[eyeMode]; btn.innerText=c.t; ov.style.display=c.d; ov.style.backgroundColor=c.c; ov.style.mixBlendMode=c.x||'normal';
    }
    function cleanCopy(btn) {
        const msgs = document.querySelectorAll('.model-response-text');
        if(msgs.length===0) return;
        let t = msgs[msgs.length-1].innerText;
        t = t.replace(/\*\*(.*?)\*\*/g,'$1').replace(/##\s?/g,'').replace(/`{3,}/g,'').replace(/\[\d+\]/g,'');
        navigator.clipboard.writeText(t).then(()=>{
            const old=btn.innerText; btn.innerText='✅'; setTimeout(()=>btn.innerText=old,1000);
        });
    }
    function toggleOutline(btn) {
        outlineCollapsed=!outlineCollapsed;
        const b=document.getElementById('gg-outline-box');
        if(b) b.style.display=outlineCollapsed?'none':'block';
        btn.innerText=outlineCollapsed?'▶':'▼';
    }
    function refreshOutline() {
        const box=document.getElementById('gg-outline-box'); if(!box)return;
        while(box.firstChild) box.removeChild(box.firstChild);
        const hs=document.querySelectorAll('.model-response-text h1, .model-response-text h2, .model-response-text h3');
        if(hs.length===0) { const d=document.createElement('div');d.innerText='暂无目录';d.style.textAlign='center';d.style.padding='5px';box.appendChild(d);return; }
        hs.forEach(h=>{
            if(h.innerText.length>50||h.innerText.length<2)return;
            const li=document.createElement('li'); li.className='gg-outline-item'; li.innerText=h.innerText;
            if(h.tagName==='H2')li.style.paddingLeft='10px'; if(h.tagName==='H3')li.style.paddingLeft='20px';
            li.onclick=()=>h.scrollIntoView({behavior:"smooth",block:"center"});
            box.appendChild(li);
        });
    }
    function mkBtn(t,fn) { const b=document.createElement('div');b.className='gg-btn';b.innerText=t;b.onclick=fn;return b; }

    // --- UI 构建 ---
    function buildUI() {
        if(document.getElementById('gg-panel-v20')) return;
        const ball=document.createElement('div'); ball.id='gg-float-ball'; ball.innerText='GG爆'; document.body.appendChild(ball); makeDraggable(ball);
        const p=document.createElement('div'); p.id='gg-panel-v20'; p.setAttribute('data-gg-theme', currentTheme);
        
        // Header
        const h=document.createElement('div'); h.className='gg-header';
        const t=document.createElement('span'); t.className='gg-title'; t.innerText='GG-BOOM V20.0';
        const m=document.createElement('span'); m.className='gg-min-btn'; m.innerText='—'; m.title='最小化';
        m.onclick=(e)=>{e.stopPropagation();togglePanel();};
        h.appendChild(t); h.appendChild(m); p.appendChild(h);

        // Theme
        const lT=document.createElement('div'); lT.className='gg-label'; lT.innerText='主题风格'; p.appendChild(lT);
        const sel=document.createElement('select'); sel.className='gg-select';
        Object.keys(themes).forEach(k=>{const opt=document.createElement('option');opt.value=k;opt.innerText=themes[k];if(k===currentTheme)opt.selected=true;sel.appendChild(opt);});
        sel.onchange=(e)=>switchTheme(e.target.value); p.appendChild(sel);

        // Tools
        const l1=document.createElement('div'); l1.className='gg-label'; l1.innerText='小工具'; p.appendChild(l1);
        const g=document.createElement('div'); g.className='gg-grid';
        const bCopy=mkBtn('📄 纯净复制',()=>cleanCopy(bCopy));
        const bWide=mkBtn('🖥️ 宽屏: 关',()=>toggleWide(bWide));
        const bEye=mkBtn('👁️ 护眼: 关',()=>toggleEye(bEye));
        const bScr=mkBtn('📜 自动滚动',function(){autoScroll=!autoScroll; this.classList.toggle('active'); if(autoScroll)forceScrollBottom(true);});
        const bBot=mkBtn('⬇️ 回到最下',()=>forceScrollBottom(true));
        const bExp=mkBtn('💾 导出MD',()=>{const b=new Blob([document.body.innerText],{type:'text/markdown'});const a=document.createElement('a');a.href=URL.createObjectURL(b);a.download='Gemini.md';a.click();});
        g.appendChild(bCopy); g.appendChild(bWide); g.appendChild(bEye); g.appendChild(bScr); g.appendChild(bBot); g.appendChild(bExp); p.appendChild(g);

        // Outline
        const l2=document.createElement('div'); l2.className='gg-section-header'; l2.style.marginTop='8px';
        const lb2=document.createElement('span'); lb2.className='gg-label'; lb2.innerText='大纲';
        const ctrls=document.createElement('div');
        const cCol=document.createElement('span'); cCol.className='gg-icon-btn'; cCol.innerText='▼'; cCol.onclick=()=>toggleOutline(cCol);
        const cRef=document.createElement('span'); cRef.className='gg-icon-btn'; cRef.innerText='🔄'; cRef.onclick=refreshOutline;
        ctrls.appendChild(cCol); ctrls.appendChild(cRef); l2.appendChild(lb2); l2.appendChild(ctrls); p.appendChild(l2);
        const ol=document.createElement('ul'); ol.id='gg-outline-box'; p.appendChild(ol);

        // Prompts
        const l3=document.createElement('div'); l3.className='gg-label'; l3.style.marginTop='8px'; l3.innerText='快捷提示字'; p.appendChild(l3);
        const chips=document.createElement('div'); chips.className='gg-chip-area';
        let pm=JSON.parse(localStorage.getItem('gg_v20_pm'))||['继续','详细解释','翻译','润色','总结'];
        const renderPm=()=>{
            while(chips.firstChild)chips.removeChild(chips.firstChild);
            pm.forEach((txt,i)=>{
                const c=document.createElement('span'); c.className='gg-chip'; c.innerText=txt;
                c.onclick=()=>{const e=document.querySelector('div[contenteditable="true"]');if(e){e.focus();document.execCommand('insertText',false,txt);}};
                c.oncontextmenu=(e)=>{e.preventDefault();if(confirm('Del?')){pm.splice(i,1);localStorage.setItem('gg_v20_pm',JSON.stringify(pm));renderPm();}};
                chips.appendChild(c);
            });
            const add=document.createElement('span'); add.className='gg-chip'; add.innerText='+'; add.style.color='var(--gg-accent)';
            add.onclick=()=>{const n=prompt('New:');if(n){pm.push(n);localStorage.setItem('gg_v20_pm',JSON.stringify(pm));renderPm();}};
            chips.appendChild(add);
        };
        renderPm(); p.appendChild(chips);

        // Footer
        const f=document.createElement('div'); f.className='gg-footer'; f.innerText='Enter 换行 | Ctrl+Enter 发送'; p.appendChild(f);
        document.body.appendChild(p); makeDraggable(p,h); switchTheme(currentTheme); setTimeout(refreshOutline,1000);
    }

    // --- Loop ---
    setInterval(()=>{
        buildUI();
        // 自动滚动核心逻辑
        if(autoScroll) {
            const stop = document.querySelector('button[aria-label*="Stop"]') || document.querySelector('button[aria-label*="停止"]');
            if(stop) forceScrollBottom(false); // 瞬时滚动
        }
        const q=document.querySelector('.user-query-text'); if(q&&!document.title.startsWith('🤖'))document.title='🤖 '+q.innerText.slice(0,10);
    }, 100);

    // --- Keys ---
    window.addEventListener('keydown',e=>{
        if(e.altKey&&(e.key==='g'||e.key==='G')){const p=document.getElementById('gg-panel-v20');p.style.left='50%';p.style.top='50%';p.style.transform='translate(-50%,-50%)';p.style.display='flex';p.style.opacity='1';document.getElementById('gg-float-ball').style.display='none';isHidden=false;}
        if(!e.target.isContentEditable)return;
        if(e.key==='Enter'&&e.ctrlKey){
            e.preventDefault();e.stopPropagation();
            const btn=document.querySelector('button[aria-label*="Send"]')||document.querySelector('button[aria-label*="发送"]');
            if(btn)btn.click();else{const icon=document.querySelector('mat-icon[data-mat-icon-name="send"]');if(icon)icon.closest('button').click();}
        }else if(e.key==='Enter'&&!e.shiftKey){
            e.preventDefault();e.stopPropagation(); document.execCommand('insertText',false,'\n');
        }
    },true);
})();

觉得好用求个鸡腿!🍗 感谢!
xhj003 xhj003 **

12
  • @91 #1 嘿嘿,不知道应该咋说。。。 xhj006

  • 哥们,让Gemini更好用,不叫“制夷”

  • 待会试试,给鸡腿

  • 如果有好用的功能,各位可以随时评论回复。我有空看到我就加进去

  • 比较喜欢这个去除**##的功能

  • @a5293604 #5 我主要是用AI来写公众号啥的。 这样我拿着直接偷很舒服 xhj001

  • 真不错😦

  • 大佬nb

  • 历史对话分组功能感觉挺有用的,不知道能否实现。

  • 感谢分享

12

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有60098位seeker

🎉欢迎新用户🎉