Quickly edit previous prompt for Superpower ChatGPT

Press Ctrl + Alt + Left click on the previous prompt text to jump in at the current mouse position to quickly edit the prompt

目前為 2024-05-09 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Quickly edit previous prompt for Superpower ChatGPT
// @description  Press Ctrl + Alt + Left click on the previous prompt text to jump in at the current mouse position to quickly edit the prompt
// @author       NWP
// @namespace    https://greasyfork.org/users/877912
// @version      0.3
// @license      MIT
// @match        https://chat.openai.com/*
// @match        https://chatgpt.com/*
// @grant        none
// ==/UserScript==

// TODO:
// 1. Fix the screen flicker due to the fast jumping to the Save & Submit button and then
// jumping back to the current position of the caret in the textarea
// 2. Launch a version for pure OpenAI

(function() {
    'use strict';

    document.addEventListener('mousedown', function(event) {
        // Check if the Ctrl and Alt keys are pressed, and the primary mouse button (left click) is used
        if (event.ctrlKey && event.altKey && event.button === 0) {
            const targetDiv = event.target;
            // Ensure the event's target is a div
            if (targetDiv.tagName === 'DIV') {
                let textNode, offset;
                if (document.caretPositionFromPoint) {
                    const caretPos = document.caretPositionFromPoint(event.clientX, event.clientY);
                    if (caretPos) {
                        textNode = caretPos.offsetNode;
                        offset = caretPos.offset;
                    }
                } else if (document.caretRangeFromPoint) {
                    const range = document.caretRangeFromPoint(event.clientX, event.clientY);
                    if (range) {
                        textNode = range.startContainer;
                        offset = range.startOffset;
                    }
                }

                // Check if we successfully got a text node and offset
                if (textNode && (offset !== undefined)) {
                    // console.log('Text node:', textNode);
                    // console.log('Offset in node:', offset);

                    if (targetDiv) {
                        // Extract the unique ID from the DIV's ID
                        const uniqueID = targetDiv.id.replace('message-text-', '');
                        // Find the corresponding button using the unique ID
                        const button = document.getElementById(`message-edit-button-${uniqueID}`);
                        if (button) {
                            // Get the scrollable container - THIS WILL LIKELY BREAK IN THE FUTURE
                            const scrollableContainer = document.querySelector('div#conversation-inner-div.h-full.overflow-y-auto');
                            // Save current scroll position
                            const x = scrollableContainer.scrollLeft, // Horizontal scroll position
                                  y = scrollableContainer.scrollTop;  // Vertical scroll position
                            // console.log(x, y);

                            // If the button exists, simulate a click on it
                            button.click();

                            // Prevent the default action to avoid any unwanted side effects
                            event.preventDefault();

                            // Wait a bit for the textarea to become visible
                            setTimeout(function() {
                                // const x1 = scrollableContainer.scrollLeft, // Horizontal scroll position
                                // y1 = scrollableContainer.scrollTop;  // Vertical scroll position
                                // console.log(x1, y1);
                                const textarea = document.getElementById(`message-text-${uniqueID}`);
                                if (textarea) {
                                    // Manually set focus without scrolling
                                    textarea.focus({preventScroll: true});
                                    textarea.setSelectionRange(offset, offset);

                                    // Restore the scroll position
                                    scrollableContainer.scrollTo(x, y);
                                }
                            }, 0); // Adjust the timeout as necessary based on how the textarea is shown
                        }
                    }
                }
            }
        }
    });


})();

// When scrollableContainer breaks use this code to find the new scrollableContainer element:

// function isScrollable(element) {
//     const hasScrollableContent = element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
//     const overflowStyle = window.getComputedStyle(element).overflow;
//     return hasScrollableContent && (overflowStyle === 'scroll' || overflowStyle === 'auto');
//   }

//   // Find all elements in the body
//   const allElements = document.querySelectorAll('body, body *');

//   // Counter variable to track index
//   let index = 1;

//   // Filter out scrollable elements and apply a red border
//   Array.from(allElements).forEach(element => {
//     if (isScrollable(element)) {
//       element.style.border = '2px solid red';
//       console.log("Scrollable Element " + index + ":", element);
//       console.log("Scroll Position " + index + " (x, y):", element.scrollLeft, element.scrollTop);
//       index++; // Increment index for the next scrollable element
//     }
//   });