Gemini Model Memory

Automatically select default model. Remembers user's choice across app, notebook, and gem pages.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         Gemini Model Memory
// @namespace    http://greatest.deepsurf.us/
// @version      2.1
// @description  Automatically select default model. Remembers user's choice across app, notebook, and gem pages.
// @author       Bui Quoc Dung
// @match        https://gemini.google.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    if (window.self !== window.top) return;


    const siteConfig = {
        targetPaths: ['app', 'notebook', 'gem'],
        selectors: {
            pickerBtn: 'button[data-test-id="bard-mode-menu-button"]',
            menuItems: '[role="menuitemradio"], [role="menuitem"]'
        }
    };

    const timings = {
        interval: 1000,
        renderDelay: 600,
        cooldown: 1500
    };

    const MODELS = {
        0: { keywords: ["Flash-lite"] },
        1: { keywords: ["Flash"] },
        2: { keywords: ["Pro"] }
    };

    let savedIndex = localStorage.getItem('gemini_saved_model_index');
    let targetModelId = (savedIndex !== null && MODELS[savedIndex]) ? parseInt(savedIndex) : 1;

    let isSwitching = false;
    let userManualSelection = false;


    function isValidTargetPage() {
        const path = window.location.pathname;
        return siteConfig.targetPaths.some(target => {
            const regex = new RegExp(`\\/(${target})(\\/|$)`, 'i');
            return regex.test(path);
        });
    }

    document.addEventListener('click', (e) => {
        if (isSwitching) return;

        const pickerBtn = document.querySelector(siteConfig.selectors.pickerBtn);
        const item = e.target.closest(siteConfig.selectors.menuItems);

        if (item) {
            const itemText = item.innerText || item.textContent || "";
            for (let key in MODELS) {
                if (MODELS[key].keywords.some(k => itemText.includes(k))) {
                    targetModelId = parseInt(key);
                    localStorage.setItem('gemini_saved_model_index', key);
                    break;
                }
            }
            userManualSelection = false;
        } else if (pickerBtn && pickerBtn.contains(e.target)) {
            userManualSelection = true;
        } else {
            userManualSelection = false;
        }
    }, true);

    setInterval(() => {
        if (!isValidTargetPage() || isSwitching || userManualSelection) return;

        const pickerBtn = document.querySelector(siteConfig.selectors.pickerBtn);
        if (!pickerBtn) return;

        const currentText = pickerBtn.innerText || pickerBtn.textContent || "";
        const targetModel = MODELS[targetModelId];

        if (!targetModel) return;
        if (targetModel.keywords.some(k => currentText.includes(k))) return;

        isSwitching = true;
        pickerBtn.click();

        setTimeout(() => {
            const menuItems = document.querySelectorAll(siteConfig.selectors.menuItems);
            let clicked = false;

            for (let item of menuItems) {
                if (item.getBoundingClientRect().width > 0) {
                    const itemText = item.innerText || item.textContent || "";
                    if (targetModel.keywords.some(k => itemText.includes(k))) {
                        item.click();
                        clicked = true;
                        break;
                    }
                }
            }

            if (!clicked) document.body.click();

            setTimeout(() => {
                isSwitching = false;
            }, timings.cooldown);

        }, timings.renderDelay);
    }, timings.interval);

})();