在ChatGPT页面添加一个对话导航目录,并为每个项添加序号,加入可控制显示/隐藏的按钮,默认状态为显示
// ==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
})();