Gemini Model & Brain Switcher

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

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Advertisement:

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

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

})();