Skip to content

Instantly share code, notes, and snippets.

@0nelight
Last active March 20, 2025 10:09
Show Gist options
  • Save 0nelight/48731a24fe32c96566ee4289f7fb9ab3 to your computer and use it in GitHub Desktop.
Save 0nelight/48731a24fe32c96566ee4289f7fb9ab3 to your computer and use it in GitHub Desktop.
Adds a Conversation Overview Area to Grok-AI-WebUi for easy navigation (no doomscrooling anymore)
// ==UserScript==
// @name Grok Conversation Overview Overlay
// @namespace http://tampermonkey.net/
// @version 0.31
// @description Displays a hierarchical list of prompts, answers, and code blocks with scroll and copy functionality
// @author Grok
// @match https://grok.com/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
function buildOverview() {
// Alle .message-bubble Elemente auswählen
const bubbles = document.querySelectorAll('.message-bubble');
const items = [];
// Bubbles verarbeiten
bubbles.forEach(bubble => {
const parent = bubble.parentElement;
// Prompt oder Antwort basierend auf Elternklassen unterscheiden
if (parent.classList.contains('items-end')) {
items.push({type: 'prompt', element: parent});
} else if (parent.classList.contains('items-start')) {
items.push({type: 'answer', element: parent});
// Code-Blöcke innerhalb der Antwort finden
const notProseDivs = bubble.querySelectorAll('.not-prose');
notProseDivs.forEach(div => {
const codeElement = div.querySelector('code');
if (codeElement) {
items.push({type: 'code', element: div, codeElement: codeElement});
}
});
}
});
let overviewDiv = document.getElementById('conversation-overview');
if (!overviewDiv) {
overviewDiv = document.createElement('div');
overviewDiv.id = 'conversation-overview';
overviewDiv.style.position = 'fixed';
overviewDiv.style.top = '70px';
overviewDiv.style.right = '10px';
overviewDiv.style.bottom = '10px';
overviewDiv.style.background = '#fff';
overviewDiv.style.padding = '10px';
overviewDiv.style.border = '1px solid #ccc';
overviewDiv.style.zIndex = '1';
overviewDiv.style.overflowY = 'auto';
overviewDiv.style.fontSize = '12px';
document.body.appendChild(overviewDiv);
}
// HTML für die hierarchische Liste erstellen
let html = '<strong>Conversation Overview:</strong><ul style="list-style: none; padding: 0;">';
let promptCount = 0;
let answerCount = 0;
items.forEach((item, index) => {
if (item.type === 'prompt') {
promptCount++;
const preview = item.element.querySelector('.message-bubble')?.textContent.trim().substring(0, 30) || 'Prompt';
html += `<li><a href="#" data-index="${index}" style="text-decoration: none; color: blue; cursor: pointer;">Prompt ${promptCount}: ${preview}...</a></li>`;
} else if (item.type === 'answer') {
answerCount++;
const preview = item.element.querySelector('.message-bubble')?.textContent.trim().substring(0, 30) || 'Answer';
html += `<li><a href="#" data-index="${index}" style="text-decoration: none; color: blue; cursor: pointer;">Answer ${answerCount}: ${preview}...</a></li>`;
} else if (item.type === 'code') {
const codePreview = item.codeElement.textContent.trim().substring(0, 30) || 'Code block';
html += `<li style="padding-left:20px"><a href="#" data-index="${index}" style="text-decoration: none; color: blue; cursor: pointer;">Code block: ${codePreview}...</a> <button data-index="${index}" style="margin-left:5px; position:relative;">Copy</button></li>`;
}
});
html += '</ul>';
overviewDiv.innerHTML = html;
// Event-Listener für Scrollen hinzufügen
overviewDiv.querySelectorAll('a').forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const index = link.getAttribute('data-index');
const item = items[index];
item.element.scrollIntoView({behavior: 'smooth', block: 'start'});
});
});
// Event-Listener für Kopieren hinzufügen
overviewDiv.querySelectorAll('button').forEach(button => {
button.addEventListener('click', () => {
const index = button.getAttribute('data-index');
const item = items[index];
const codeText = item.codeElement.textContent;
navigator.clipboard.writeText(codeText).then(() => {
const confirmSpan = document.createElement('span');
confirmSpan.textContent = 'Copied!';
confirmSpan.style.position = 'absolute';
confirmSpan.style.left = '100%';
confirmSpan.style.marginLeft = '5px';
confirmSpan.style.color = '#28a745';
confirmSpan.style.fontSize = '12px';
button.appendChild(confirmSpan);
setTimeout(() => {
confirmSpan.remove();
}, 2000);
}).catch(err => {
console.error('Fehler beim Kopieren: ', err);
const errorSpan = document.createElement('span');
errorSpan.textContent = 'Error';
errorSpan.style.position = 'absolute';
errorSpan.style.left = '100%';
errorSpan.style.marginLeft = '5px';
errorSpan.style.color = '#dc3545';
errorSpan.style.fontSize = '12px';
button.appendChild(errorSpan);
setTimeout(() => {
errorSpan.remove();
}, 2000);
});
});
});
}
// Initialer Aufruf beim Laden der Seite
window.addEventListener('load', buildOverview);
// Aktualisierung alle 5 Sekunden
setInterval(buildOverview, 5000);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment