Gemini - Last Prompt Replacer

Streamlines replacing the last prompt in a Gemini conversation with robust short and long press support.

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

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

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Gemini - Last Prompt Replacer
// @namespace    http://tampermonkey.net/
// @version      0.8
// @description  Streamlines replacing the last prompt in a Gemini conversation with robust short and long press support.
// @author       vfxturjo
// @license      MIT
// @match        https://gemini.google.com/app/*
// @grant        GM_registerMenuCommand
// @grant        GM_setClipboard
// ==/UserScript==

(function() {
    'use strict';

    let keydownTimer = null;
    let isActionInProgress = false; // State flag to prevent key-repeat issues
    const longPressDuration = 400; // Time in ms to distinguish a long press

    /**
     * The core function to replace the last prompt.
     * @param {boolean} submit - If true, the script will simulate an "Enter" key press.
     */
    async function replacePrompt(submit = true) {
        console.log(`Gemini Replacer: Action triggered (Submit: ${submit}).`);

        try {
            const allEditButtons = document.querySelectorAll('[data-test-id="prompt-edit-button"]');
            if (allEditButtons.length === 0) {
                // Check if we are already in edit mode
                if (!document.querySelector('textarea[aria-label="Edit prompt"]')) {
                    alert("Gemini Replacer Error: Could not find any prompt edit buttons.");
                }
                // If we are already in edit mode, we can still proceed to paste.
            } else {
                const lastEditButton = allEditButtons[allEditButtons.length - 1];
                lastEditButton.click();
                console.log("Gemini Replacer: Edit button clicked.");
            }

            const clipboardText = await navigator.clipboard.readText();
            if (typeof clipboardText !== 'string' || clipboardText.length === 0) {
                alert("Gemini Replacer: Clipboard is empty or contains no text.");
                return;
            }
            console.log("Gemini Replacer: Successfully read from clipboard.");

            // A brief moment for the text area to become visible.
            setTimeout(() => {
                const promptTextArea = document.querySelector('textarea[aria-label="Edit prompt"]');

                if (promptTextArea) {
                    console.log("Gemini Replacer: Found the prompt text area.");
                    promptTextArea.value = clipboardText;
                    promptTextArea.dispatchEvent(new Event('input', { bubbles: true }));

                    if (submit) {
                        const enterEvent = new KeyboardEvent('keydown', {
                            bubbles: true, cancelable: true, key: 'Enter', code: 'Enter', keyCode: 13, which: 13
                        });
                        promptTextArea.dispatchEvent(enterEvent);
                        console.log("Gemini Replacer: Pasted content and simulated Enter press.");
                    } else {
                        console.log("Gemini Replacer: Pasted content without submitting. Ready for editing.");
                    }
                } else {
                    alert("Gemini Replacer Error: Could not find the prompt text area after clicking edit.");
                }
            }, 100);

        } catch (error) {
            if (error.name === 'NotAllowedError') {
                alert('Gemini Replacer: Please grant clipboard access permission to the site.');
            } else {
                console.error("Gemini Replacer: An unexpected error occurred:", error);
                alert("Gemini Replacer: An unexpected error occurred. See the console for details.");
            }
        }
    }

    // --- Triggers ---

    GM_registerMenuCommand('Replace Last Prompt', () => replacePrompt(true));

    document.addEventListener('keydown', function(event) {
        // Only run if CTRL+Q is pressed AND we are not already processing an action
        if (event.ctrlKey && event.key.toLowerCase() === 'q' && !isActionInProgress) {
            event.preventDefault();
            isActionInProgress = true; // Set the flag to block repeated events

            // Start a timer for the long press action.
            keydownTimer = setTimeout(() => {
                replacePrompt(false); // Execute the action without submitting.
                keydownTimer = null; // Clear the timer ID after it has run.
            }, longPressDuration);
        }
    });

    document.addEventListener('keyup', function(event) {
        // We only care about the keyup event if we started an action
        if (event.key.toLowerCase() === 'q' && isActionInProgress) {
            // If the timer is still running, it's a short press.
            if (keydownTimer) {
                clearTimeout(keydownTimer);
                replacePrompt(true); // Execute the action with submission.
            }
            // If keydownTimer is null, the long press already fired. Do nothing.

            // Reset state for the next key press
            keydownTimer = null;
            isActionInProgress = false;
        }
    });

})();