// ==UserScript==
// @name AI Conversation Navigator
// @namespace https://greasyforks.org
// @version 1.9
// @description Floating navigator for your prompts in ChatGPT, Gemini, Aistudio, Kimi, Grok conversations
// @author Bui Quoc Dung
// @match https://chatgpt.com/*
// @match https://gemini.google.com/*
// @match https://aistudio.google.com/*
// @match https://www.kimi.com/*
// @match https://grok.com/*
// @grant GM_addStyle
// @license MIT
// ==/UserScript==
(function () {
'use strict';
const COMMON_TITLE = 'Your Prompts';
const COMMON_CONTAINER_STYLE = `
right: 20px; width: 250px; max-height: 90vh; overflow-y: auto;
z-index: 9999; border-radius: 2px; box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.3);
transition: width 0.3s, padding 0.3s, opacity 0.3s, transform 0.3s;
font-family: Calibri, sans-serif; font-size: 15px;
`;
const SITE_CONFIG = {
chatgpt: {
match: /chatgpt\.com/,
msgSelector: 'div[data-message-author-role="user"]',
conversationSelector: 'a.group.__menu-item.hoverable',
mainElemSelector: 'main',
moveLeftStyle: `
body.navigator-expanded .mx-auto,
body.navigator-expanded .md\\:max-w-3xl,
body.navigator-expanded .xl\\:max-w-\\[48rem\\],
body.navigator-expanded .max-w-2xl,
body.navigator-expanded .lg\\:px-2 {
margin-left: 0 !important;
margin-right: 130px !important;
}
body.navigator-expanded main,
body.navigator-expanded main > div,
body.navigator-expanded main article > div,
body.navigator-expanded div.flex.flex-col.items-center.text-sm {
margin-left: 0 !important;
margin-right: auto !important;
max-width: 100% !important;
}
body.navigator-expanded div.ProseMirror {
margin-left: 0 !important;
margin-right: auto !important;
}
body.navigator-expanded .xl\\:max-w-\\[48rem\\] {
width: 800px !important;
max-width: 100% !important;
}
`,
containerStyle: `position: fixed; top: 35px; ${COMMON_CONTAINER_STYLE}`,
bgClass: "text-token-text-primary bg-token-main-surface-primary rounded-lg shadow-lg"
},
gemini: {
match: /gemini\.google\.com/,
msgSelector: '.user-query-bubble-with-background',
conversationSelector: 'div[role="button"][data-test-id="conversation"]',
mainElemSelector: '.chat-history.ng-star-inserted',
moveLeftStyle: `
body.navigator-expanded .chat-history-scroll-container {
margin-left: 0 !important;
margin-right: 300px !important;
max-width: calc(100% - 300px) !important;
transition: margin-right 0.3s ease;
}
`,
containerStyle: `position: fixed; top: 55px; ${COMMON_CONTAINER_STYLE}`,
bgClass: ""
},
aistudio: {
match: /aistudio\.google\.com/,
msgSelector: '.user-prompt-container',
conversationSelector: 'mat-mdc-row.mdc-data-table__row.cdk-row.ng-star-inserted',
mainElemSelector: 'ms-autoscroll-container',
moveLeftStyle: `
body.navigator-expanded ms-autoscroll-container {
margin-left: 0 !important;
margin-right: 200px !important;
max-width: calc(100% - 200px) !important;
transition: margin-right 0.3s ease;
}
`,
containerStyle: `position: fixed; top: 55px; ${COMMON_CONTAINER_STYLE}`,
bgClass: ""
},
kimi: {
match: /www\.kimi\.com/,
msgSelector: '.user-content',
conversationSelector: '.chat-name',
mainElemSelector: '.chat-content-container',
moveLeftStyle: `
body.navigator-expanded .chat-content-container {
margin-left: 0 !important;
margin-right: 100px !important;
max-width: calc(100% - 150px) !important;
transition: margin-right 0.3s ease;
}
`,
containerStyle: `position: fixed; top: 55px; ${COMMON_CONTAINER_STYLE}`,
bgClass: ""
},
grok: {
match: /grok\.com/,
msgSelector: '.relative.group.flex.flex-col.justify-center.items-end',
conversationSelector: '.flex-1.select-none.text-nowrap.overflow-hidden.inline-block',
mainElemSelector: '.w-full.h-full.overflow-y-auto.overflow-x-hidden.scrollbar-gutter-stable.flex.flex-col.items-center.px-gutter',
moveLeftStyle: `
body.antialiased.font-body.bg-surface-base.overflow-x-hidden {
margin-left: 0 !important;
margin-right: 280px !important;
max-width: calc(100% - 280px) !important;
transition: margin-right 0.3s ease;
}
`,
containerStyle: `position: fixed; top: 55px; ${COMMON_CONTAINER_STYLE}`,
bgClass: ""
}
};
const site = Object.values(SITE_CONFIG).find(s => s.match.test(location.hostname));
if (!site) return;
GM_addStyle(site.moveLeftStyle);
let userMsgCounter = 0;
let conversationObserver = null;
let isCollapsed = false;
function updateBodyClassForLayout() {
const container = document.getElementById('message-nav');
const content = document.getElementById('message-nav-content');
if (container && content && content.style.display !== 'none') {
document.body.classList.add('navigator-expanded');
} else {
document.body.classList.remove('navigator-expanded');
}
}
function createContainer() {
let container = document.getElementById('message-nav');
if (!container) {
container = document.createElement('div');
container.id = 'message-nav';
container.className = site.bgClass;
container.style.cssText = site.containerStyle;
const header = document.createElement('div');
header.style.display = 'flex';
header.style.alignItems = 'center';
header.style.justifyContent = 'space-between';
header.style.padding = '5px';
header.style.cursor = 'pointer';
header.style.fontWeight = 'bold';
header.textContent = COMMON_TITLE;
const toggleBtn = document.createElement('button');
toggleBtn.style.background = 'none';
toggleBtn.style.border = 'none';
toggleBtn.style.cursor = 'pointer';
toggleBtn.style.fontSize = '16px';
toggleBtn.textContent = '⯈';
header.appendChild(toggleBtn);
const content = document.createElement('div');
content.id = 'message-nav-content';
content.style.padding = '5px';
container.appendChild(header);
container.appendChild(content);
document.body.appendChild(container);
if (isCollapsed) {
content.style.display = 'none';
container.style.width = '130px';
toggleBtn.textContent = '⯆';
}
toggleBtn.addEventListener('click', (e) => {
e.stopPropagation();
isCollapsed = !isCollapsed;
if (!isCollapsed) {
content.style.display = 'block';
container.style.width = '250px';
toggleBtn.textContent = '⯈';
} else {
content.style.display = 'none';
container.style.width = '130px';
toggleBtn.textContent = '⯆';
}
updateBodyClassForLayout();
});
updateBodyClassForLayout();
}
return container;
}
function assignIdToMessage(msgElem) {
if (!msgElem.id) {
userMsgCounter++;
msgElem.id = 'user-msg-' + userMsgCounter;
msgElem.dataset.index = userMsgCounter;
}
}
function createListItem(msgElem) {
const index = msgElem.dataset.index || '?';
const text = msgElem.innerText.trim();
const preview = text.length > 80 ? text.slice(0, 80) + '...' : text;
const listItem = document.createElement('li');
listItem.textContent = `${index}. ${preview}`;
listItem.style.cursor = 'pointer';
listItem.style.padding = '5px 5px';
listItem.addEventListener('click', () => {
const allItems = listItem.parentElement.querySelectorAll('li');
allItems.forEach(li => li.style.fontWeight = 'normal');
listItem.style.fontWeight = 'bold';
msgElem.scrollIntoView({ behavior: 'smooth', block: 'start' });
});
return listItem;
}
function updateMessageList() {
const container = createContainer();
const content = document.getElementById('message-nav-content');
if (!content) return;
let list = content.querySelector('ul');
if (!list) {
list = document.createElement('ul');
list.style.padding = '0';
list.style.margin = '0';
list.style.listStyle = 'none';
content.appendChild(list);
}
const userMessages = document.querySelectorAll(site.msgSelector);
const existingListItems = list.querySelectorAll('li');
if (userMessages.length < existingListItems.length) {
list.innerHTML = '';
}
if (userMessages.length > existingListItems.length) {
for (let i = existingListItems.length; i < userMessages.length; i++) {
const msgElem = userMessages[i];
assignIdToMessage(msgElem);
const listItem = createListItem(msgElem);
list.appendChild(listItem);
}
}
}
function observeConversation() {
if (conversationObserver) conversationObserver.disconnect();
const mainElem = document.querySelector(site.mainElemSelector);
if (!mainElem) return;
conversationObserver = new MutationObserver(() => updateMessageList());
conversationObserver.observe(mainElem, { childList: true, subtree: true });
}
function waitForChatToLoad() {
const interval = setInterval(() => {
const mainElem = document.querySelector(site.mainElemSelector);
if (mainElem && document.querySelector(site.msgSelector)) {
clearInterval(interval);
userMsgCounter = 0;
const content = document.getElementById('message-nav-content');
if (content) {
const list = content.querySelector('ul');
if (list) list.innerHTML = '';
}
updateMessageList();
observeConversation();
}
}, 500);
}
function attachConversationClickListener() {
document.body.addEventListener('click', (e) => {
const a = e.target.closest(site.conversationSelector);
if (!a) return;
userMsgCounter = 0;
const content = document.getElementById('message-nav-content');
if (content) {
const list = content.querySelector('ul');
if (list) list.innerHTML = '';
}
setTimeout(updateMessageList, 300);
});
}
attachConversationClickListener();
waitForChatToLoad();
let lastUrl = location.href;
new MutationObserver(() => {
if (location.href !== lastUrl) {
lastUrl = location.href;
waitForChatToLoad();
}
}).observe(document.body, { childList: true, subtree: true });
})();