Greasy Fork

Greasy Fork is available in English.

ChatGPT 对话问题导航

在ChatGPT页面添加一个对话导航目录,并为每个项添加序号,加入可控制显示/隐藏的按钮,默认状态为显示

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         ChatGPT 对话问题导航
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  在ChatGPT页面添加一个对话导航目录,并为每个项添加序号,加入可控制显示/隐藏的按钮,默认状态为显示
// @author       Angury
// @match        https://chatgpt.com/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    const tocContainer = document.createElement('div');
    tocContainer.id = 'tocContainer';
    tocContainer.style.cssText = 'position: fixed; right: 0; top: 50px; width: 200px; height: 80vh; overflow-y: auto; background-color: #fff; border: 1px solid #ccc; padding: 10px; z-index: 1000; display: block;';

    const toggleButton = document.createElement('div');
    toggleButton.innerHTML = '▶'; // Unicode character for rightward triangle, indicating the menu is open
    toggleButton.style.cssText = 'position: fixed; right: 0; top: 30px; width: 30px; height: 20px; padding: 5px; text-align: center; cursor: pointer; z-index: 1001; background-color: transparent; border: none;';

    document.body.appendChild(toggleButton);
    document.body.appendChild(tocContainer);

    toggleButton.onclick = function() {
        tocContainer.style.display = tocContainer.style.display === 'block' ? 'none' : 'block';
        toggleButton.innerHTML = tocContainer.style.display === 'none' ? '◀' : '▶';
    };

    function updateTOC() {
        const messages = document.querySelectorAll('div[data-message-author-role="user"]');
        if (messages.length === tocContainer.childNodes.length) {
            return; // Skip update if the count of messages hasn't changed
        }

        tocContainer.innerHTML = ''; // Clear previous entries

        messages.forEach((message, index) => {
            const lastDiv = message.querySelector('div:last-child div:last-child');
            if (!lastDiv) return; // Skip if no div found

            const questionId = `question-${index}`;
            lastDiv.id = questionId;

            let questionText = lastDiv.textContent.trim() || `......`;
            questionText = questionText.length > 9 ? `${questionText.substring(0, 8)}...` : questionText;
            let formattedIndex = ("0" + (index + 1)).slice(-2);  // Two-digit numbering

            const tocItem = document.createElement('div');
            tocItem.textContent = `${formattedIndex} ${questionText}`;
            tocItem.style.cssText = 'cursor: pointer; margin-bottom: 5px;';
            tocItem.onclick = function() {
                document.getElementById(questionId).scrollIntoView({ behavior: 'smooth' });
            };

            tocContainer.appendChild(tocItem);
        });
    }

    // Use MutationObserver to listen for changes in the DOM
    const observer = new MutationObserver(mutations => {
        let shouldUpdate = false;
        mutations.forEach(mutation => {
            if (mutation.addedNodes.length) shouldUpdate = true;
        });
        if (shouldUpdate) updateTOC();
    });

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

    updateTOC();  // Initial update
})();