Gemini Model & Brain Switcher

Yeni arayüzdeki data-active (hover) tuzağı düzeltildi. 1. element dahil tüm modellere sorunsuz geçer.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Advertisement:

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

Advertisement:

// ==UserScript==
// @name         Gemini Model & Brain Switcher
// @namespace    https://github.com/FrknKoseoglu
// @version      4.3
// @description  Yeni arayüzdeki data-active (hover) tuzağı düzeltildi. 1. element dahil tüm modellere sorunsuz geçer.
// @author       frknkoseoglu
// @match        https://gemini.google.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    let isProcessing = false;

    // Ana tetikleyici
    const MAIN_MENU_SELECTORS = `
        .model-picker-container,
        [data-test-id*="mode-switch"],
        [data-test-id*="model-switch"],
        [data-test-id*="chat-model"],
        [data-test-id="bard-mode-menu-button"],
        .gds-mode-switch-button
    `;

    const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

    const hideUpgradeButton = () => {
        const style = document.createElement('style');
        style.type = 'text/css';
        style.textContent = `
            .upgrade-container, .g1-upsell-container, gem-menu-item[value="upgrade"] {
                display: none !important;
            }
        `;
        document.head.appendChild(style);
    };

    hideUpgradeButton();

    const waitForElements = async (selector, timeout = 1500) => {
        let elapsed = 0;
        const interval = 20;
        while (elapsed < timeout) {
            const elements = Array.from(document.querySelectorAll(selector)).filter(el => {
                return el.offsetParent !== null || el.getBoundingClientRect().width > 0;
            });
            if (elements.length > 0) return elements;
            await delay(interval);
            elapsed += interval;
        }
        throw new Error(`Element bulunamadı: ${selector}`);
    };

    const simulateClick = (element) => {
        if (!element) return;
        element.focus();
        element.click();
    };

    const closeMenu = () => {
        document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true, cancelable: true }));
        document.body.click();
    };

    // --------------------------------------------------------
    // 1. İŞLEM: TEKERLEK KAYDIRMA (Model Değişimi - Kesin Çözüm)
    // --------------------------------------------------------
    document.addEventListener('wheel', async function(e) {
        if (isProcessing) return;

        const modelContainer = e.target.closest(MAIN_MENU_SELECTORS);
        if (!modelContainer) return;

        e.preventDefault();
        e.stopPropagation();

        isProcessing = true;
        const direction = e.deltaY > 0 ? 1 : -1;

        try {
            const triggerButton = modelContainer.querySelector('button') || modelContainer;
            
            if (triggerButton.getAttribute('aria-expanded') !== 'true') {
                simulateClick(triggerButton);
                await delay(150); 
            }
            
            const buttons = await waitForElements('gem-menu-item[data-mode-id]');
            
            // KRİTİK DÜZELTME: data-active kontrolü kaldırıldı! 
            // Sadece gerçek seçili (selected) sınıflara ve check ikonuna bakılıyor.
            let currentIndex = buttons.findIndex(btn => 
                btn.classList.contains('selected') || 
                btn.querySelector('.selected') || 
                btn.querySelector('mat-icon[fonticon="check"]')
            );
            
            // Eğer hiçbir şey bulunamazsa varsayılan olarak 0 (ilk element) kabul et
            if (currentIndex === -1) currentIndex = 0;
            
            let nextIndex = currentIndex + direction;
            if (nextIndex >= buttons.length) nextIndex = 0;
            if (nextIndex < 0) nextIndex = buttons.length - 1;

            simulateClick(buttons[nextIndex]);

        } catch (err) {
            console.warn("Gemini Switcher Hatası (Model Scroll):", err);
            closeMenu();
        } finally {
            // Artçı scroll sinyallerini sönümlemek için 450ms soğuma
            await delay(450);
            isProcessing = false;
        }
    }, { passive: false, capture: true });

    // --------------------------------------------------------
    // 2. İŞLEM: BUTON RENGİNİ DÜZENLEME
    // --------------------------------------------------------
    const updateBrainButtonState = () => {
        const brainBtn = document.getElementById('gemini-brain-btn');
        const modelContainer = document.querySelector(MAIN_MENU_SELECTORS);
        
        if (brainBtn && modelContainer) {
            if (modelContainer.textContent.includes('Uzatılmış')) {
                brainBtn.style.filter = 'none';
                brainBtn.style.opacity = '1';
            } else {
                brainBtn.style.filter = 'grayscale(100%)';
                brainBtn.style.opacity = '0.7';
            }
        }
    };

    // --------------------------------------------------------
    // 3. İŞLEM: "🧠" BUTONU ENJEKSİYONU
    // --------------------------------------------------------
    const injectBrainButton = () => {
        let brainBtn = document.getElementById('gemini-brain-btn');
        const targetWrapper = document.querySelector('.trailing-actions-wrapper.with-model-picker');
        const modelContainer = document.querySelector('.model-picker-container'); 
        
        if (!brainBtn && targetWrapper && modelContainer) {
            brainBtn = document.createElement('button');
            brainBtn.id = 'gemini-brain-btn';
            brainBtn.textContent = '🧠';
            brainBtn.title = 'Düşünme Düzeyini Değiştir (Standart / Uzatılmış)';
            
            brainBtn.style.cssText = `
                background: transparent !important;
                border: none !important;
                font-size: 1.4rem !important;
                cursor: pointer !important;
                margin: 0 !important; 
                padding: 6px 10px !important;
                border-radius: 50% !important;
                display: flex !important;
                align-items: center !important;
                justify-content: center !important;
                transition: all 0.2s !important;
                user-select: none !important;
                flex-shrink: 0 !important;
                z-index: 9999 !important;
            `;

            brainBtn.onmouseenter = () => { brainBtn.style.backgroundColor = 'rgba(128, 128, 128, 0.1)'; };
            brainBtn.onmouseleave = () => { brainBtn.style.backgroundColor = 'transparent'; };
            brainBtn.onmousedown = () => { brainBtn.style.transform = 'scale(0.9)'; };
            brainBtn.onmouseup = () => { brainBtn.style.transform = 'scale(1)'; };

            brainBtn.onclick = async (e) => {
                e.preventDefault();
                e.stopPropagation();

                if (isProcessing) return;
                isProcessing = true;

                try {
                    const clickableMenu = document.querySelector(MAIN_MENU_SELECTORS);
                    const mainTriggerButton = clickableMenu.querySelector('button') || clickableMenu;

                    if (mainTriggerButton.getAttribute('aria-expanded') !== 'true') {
                        simulateClick(mainTriggerButton);
                        await delay(150); 
                    }

                    const thinkingHeaders = await waitForElements('gem-menu-item[value="thinking_level"]');
                    const headerButton = thinkingHeaders[0];
                    
                    if (headerButton.getAttribute('aria-expanded') !== 'true') {
                        simulateClick(headerButton);
                        await delay(150); 
                    }

                    const thinkingOptions = await waitForElements('gem-menu-item:not([data-mode-id]):not([value="thinking_level"])');
                    
                    // Aynı düzeltme kuralı buradaki seçici için de uygulandı
                    let currentIndex = thinkingOptions.findIndex(btn => 
                        btn.classList.contains('selected') || 
                        btn.querySelector('.selected') || 
                        btn.querySelector('mat-icon[fonticon="check"]')
                    );
                    if (currentIndex === -1) currentIndex = 0;
                    
                    let nextIndex = currentIndex + 1;
                    if (nextIndex >= thinkingOptions.length) nextIndex = 0;

                    simulateClick(thinkingOptions[nextIndex]);
                    await delay(150); 

                    closeMenu();

                } catch (err) {
                    console.warn("Gemini Switcher Hatası (Brain Butonu):", err);
                    closeMenu();
                } finally {
                    await delay(300);
                    isProcessing = false;
                }
            };

            modelContainer.after(brainBtn);
        }

        updateBrainButtonState();
    };

    const init = () => {
        injectBrainButton();
        setInterval(injectBrainButton, 1000);
    };

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

})();