Search with Gemini

Lets you use Gemini as a custom search engine. Reads 'prompt' parameter from URL and automatically submits it to Gemini chat.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         Search with Gemini
// @namespace    https://github.com/alexey-kudryavtsev/
// @version      2025.07.27.1
// @description  Lets you use Gemini as a custom search engine. Reads 'prompt' parameter from URL and automatically submits it to Gemini chat.
// @author       Alexey Kudryavtsev
// @match        https://gemini.google.com/*
// @grant        none
// @run-at       document-start
// @license      Apache-2.0
// @homepageURL  https://github.com/alexey-kudryavtsev/search-with-gemini
// @supportURL   https://github.com/alexey-kudryavtsev/search-with-gemini/issues
// ==/UserScript==


(function() {
    'use strict';

    // --- Configuration ---
    const log = (message) => console.log(`[Gemini Userscript] ${message}`);
    const PROMPT_SELECTOR = '.ql-editor[contenteditable="true"] > p';
    const SUBMIT_BUTTON_SELECTOR = 'button[aria-label="Send message"]';

    log('Script initialized (document-start).');

    // Ensure window.geminiScript object exists
    if (typeof window.geminiScript === 'undefined') {
        window.geminiScript = {};
    }

    // --- Early Execution: Extract prompt and clean URL ---
    const currentUrl = new URL(window.location.href);
    const promptValue = currentUrl.searchParams.get('prompt');

    if (promptValue) {
        log(`Found 'prompt' URL parameter during early execution: "${promptValue}"`);
        window.geminiScript.currentPrompt = promptValue; // Store the prompt
        currentUrl.searchParams.delete('prompt'); // Remove the 'prompt' parameter

        // Replace the URL in the browser's history without reloading
        const cleanUrl = currentUrl.pathname + currentUrl.search + currentUrl.hash;
        history.replaceState(null, '', cleanUrl);
        log(`🧹 URL cleaned. New URL: ${cleanUrl}`);
    } else {
        log("No 'prompt' URL parameter found during early execution. Script is idle for prefill.");
        window.geminiScript.currentPrompt = null; // Ensure it's explicitly null if not found
    }

    /**
     * Finds the prompt input, fills it, finds the submit button, and clicks it.
     * This function will be called AFTER the document is ready.
     * @param {string} textToFill - The prompt text to inject.
     */
    function prefillThenSubmit(textToFill) {
        log('🕵️‍♂️ Starting observer for the input field...');
        const inputObserver = new MutationObserver((mutations, inputObs) => {
            const promptInput = document.querySelector(PROMPT_SELECTOR);
            if (promptInput) {
                log('✅ Step 1: Input field found.');
                inputObs.disconnect();

                // Inject prompt text
                promptInput.textContent = textToFill;
                log(`📝 Text set to: "${textToFill}"`);

                // Now, wait for the submit button to become available
                const submitObserver = new MutationObserver((mutations, submitObs) => {
                    const submitButton = document.querySelector(SUBMIT_BUTTON_SELECTOR);
                    // Also check that it's not disabled
                    if (submitButton && !submitButton.disabled) {
                        log('✅ Step 2: Submit button found and enabled.');
                        submitObs.disconnect();

                        submitButton.click();
                        log('🚀 Prompt submitted!');
                    }
                });

                submitObserver.observe(document.body, {
                    childList: true,
                    subtree: true,
                    attributes: true // Also watch for attribute changes like 'disabled'
                });
            }
        });

        inputObserver.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

    // --- Main Execution (after document is ready) ---
    // Wait for the DOM to be fully loaded before trying to interact with elements
    document.addEventListener('DOMContentLoaded', () => {
        log('DOMContentLoaded fired. Executing main logic.');
        if (window.geminiScript.currentPrompt) {
            prefillThenSubmit(window.geminiScript.currentPrompt);
        } else {
            log("No prompt stored from early execution. No prefill action needed.");
        }
    });

})();