Last active
August 12, 2025 20:07
-
-
Save DiyarD/dc51b79c8cf446aa662e79638f9aeba3 to your computer and use it in GitHub Desktop.
A user script that fixes major performance and UX issues on Google's AI Studio. It eliminates scroll-fighting, stops content from flickering/disappearing, and removes rendering lag for a much smoother experience.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Google AI Studio Performance & UX Fixer | |
| // @namespace http://tampermonkey.net/ | |
| // @version 1 | |
| // @description A comprehensive script to fix all major UI/UX issues in AI Studio, including scroll-fighting, content flicker, rendering lag, and edit-scroll bugs. | |
| // @author Diyar Baban | |
| // @match https://aistudio.google.com/prompts/* | |
| // @grant none | |
| // @run-at document-start | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| const log = (message, ...args) => console.log('[AI Studio Fixer v1]', message, ...args); | |
| const addGlobalStyle = () => { | |
| const styleId = 'ai-studio-fixer-styles'; | |
| if (document.getElementById(styleId)) return; | |
| const style = document.createElement('style'); | |
| style.id = styleId; | |
| style.textContent = ` | |
| * { | |
| transition-property: none !important; | |
| animation: none !important; | |
| scroll-behavior: auto !important; | |
| } | |
| .turn, ms-chat-turn { | |
| contain: layout paint !important; | |
| padding-bottom: 24px !important; | |
| } | |
| .conversation-container, .turns-container { background: #1E1E1E !important; } | |
| .turn { | |
| background: transparent !important; | |
| border: none !important; | |
| box-shadow: none !important; | |
| padding-top: 8px !important; | |
| margin: 0 !important; | |
| } | |
| .prompt-textarea { box-shadow: none !important; border-top: 1px solid #3a3a3a !important; } | |
| .turn-footer .right-items, .turn-footer .model-info, .turn-footer .tools-info { display: none !important; } | |
| .turn-footer { min-height: auto !important; padding-top: 4px !important; } | |
| pre, code { background-color: #252526 !important; border: 1px solid #333 !important; } | |
| `; | |
| document.documentElement.appendChild(style); | |
| log('Performance & UI CSS injected.'); | |
| }; | |
| const fixDisappearingContent = () => { | |
| const originalIntersectionObserver = window.IntersectionObserver; | |
| window.IntersectionObserver = function(callback, options) { | |
| const newCallback = (entries, observer) => { | |
| const modifiedEntries = entries.map(entry => { | |
| if (entry.target.closest('.turn, ms-chat-turn') && !entry.isIntersecting) { | |
| return new Proxy(entry, { | |
| get: (target, prop) => (prop === 'isIntersecting' ? true : Reflect.get(target, prop)) | |
| }); | |
| } | |
| return entry; | |
| }); | |
| return callback(modifiedEntries, observer); | |
| }; | |
| return new originalIntersectionObserver(newCallback, options); | |
| }; | |
| log('Disappearing content/flicker fix is active.'); | |
| }; | |
| const fixScrollFighting = (chatContainer) => { | |
| const originalScrollIntoView = Element.prototype.scrollIntoView; | |
| let isUserScrolling = false; | |
| let scrollBlockTimer; | |
| const blockAppScrolls = () => { | |
| isUserScrolling = true; | |
| clearTimeout(scrollBlockTimer); | |
| scrollBlockTimer = setTimeout(() => isUserScrolling = false, 1000); | |
| }; | |
| chatContainer.addEventListener('wheel', blockAppScrolls, { passive: true, capture: true }); | |
| chatContainer.addEventListener('keydown', blockAppScrolls, { passive: true, capture: true }); | |
| document.body.addEventListener('click', (e) => { | |
| const button = e.target.closest('button'); | |
| if (button && button.getAttribute('aria-label')?.toLowerCase().includes('edit')) { | |
| const turnElement = e.target.closest('ms-chat-turn'); | |
| if (turnElement) { | |
| log('Edit click detected. Manually scrolling element into view.'); | |
| setTimeout(() => { | |
| turnElement.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); | |
| }, 50); | |
| } | |
| } | |
| }, true); | |
| Element.prototype.scrollIntoView = function(...args) { | |
| if (isUserScrolling && chatContainer.contains(this)) { | |
| log('Blocked app-forced scroll due to user wheel/key action.'); | |
| return; | |
| } | |
| return originalScrollIntoView.apply(this, args); | |
| }; | |
| log('Direct-control scroll fix is active.'); | |
| }; | |
| let fixesInitialized = false; | |
| const runAllFixes = () => { | |
| if (fixesInitialized || !document.body) return; | |
| addGlobalStyle(); | |
| fixDisappearingContent(); | |
| const observer = new MutationObserver(() => { | |
| const chatContainer = document.querySelector('main .conversation-container'); | |
| if (chatContainer) { | |
| log('Chat container found. Applying targeted fixes.'); | |
| fixScrollFighting(chatContainer); | |
| fixesInitialized = true; | |
| observer.disconnect(); | |
| } | |
| }); | |
| observer.observe(document.body, { childList: true, subtree: true }); | |
| }; | |
| if (document.readyState === 'loading') { | |
| document.addEventListener('DOMContentLoaded', runAllFixes); | |
| } else { | |
| runAllFixes(); | |
| } | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment