Gemini Model & Brain Switcher

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

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Advertisement:

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

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();
    }

})();