{"slug": "a-user-script-that-fixes-major-performance-and-ux-issues-on-google-s-ai-studio-a", "title": "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…", "summary": "Based on the article, a user script called \"Google AI Studio Performance & UX Fixer\" has been created to resolve major performance and user experience issues on Google's AI Studio platform. The script eliminates scroll-fighting, prevents content from flickering or disappearing, and removes rendering lag to provide a smoother user experience. It achieves this by injecting custom CSS to disable animations and transitions, overriding the IntersectionObserver to prevent content from being unloaded, and intercepting scroll events to stop automatic scrolling from interfering with user input.", "body_md": "Google AI Studio Performance & UX Fixer-1.user.js\n\n      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.\n      \nLearn more about bidirectional Unicode characters\n\n \n    Show hidden characters\n\n// ==UserScript==\n\n// @name         Google AI Studio Performance & UX Fixer\n\n// @namespace    http://tampermonkey.net/\n\n// @version      1\n\n// @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.\n\n// @author       Diyar Baban\n\n// @match        https://aistudio.google.com/prompts/*\n\n// @grant        none\n\n// @run-at       document-start\n\n// ==/UserScript==\n\n(function() {\n\n    'use strict';\n\n    const log = (message, ...args) => console.log('[AI Studio Fixer v1]', message, ...args);\n\n    const addGlobalStyle = () => {\n\n        const styleId = 'ai-studio-fixer-styles';\n\n        if (document.getElementById(styleId)) return;\n\n        const style = document.createElement('style');\n\n        style.id = styleId;\n\n        style.textContent = `\n\n            * {\n\n                transition-property: none !important;\n\n                animation: none !important;\n\n                scroll-behavior: auto !important;\n\n            }\n\n            .turn, ms-chat-turn {\n\n                contain: layout paint !important;\n\n                padding-bottom: 24px !important;\n\n            }\n\n            .conversation-container, .turns-container { background: #1E1E1E !important; }\n\n            .turn {\n\n                background: transparent !important;\n\n                border: none !important;\n\n                box-shadow: none !important;\n\n                padding-top: 8px !important;\n\n                margin: 0 !important;\n\n            }\n\n            .prompt-textarea { box-shadow: none !important; border-top: 1px solid #3a3a3a !important; }\n\n            .turn-footer .right-items, .turn-footer .model-info, .turn-footer .tools-info { display: none !important; }\n\n            .turn-footer { min-height: auto !important; padding-top: 4px !important; }\n\n            pre, code { background-color: #252526 !important; border: 1px solid #333 !important; }\n\n        `;\n\n        document.documentElement.appendChild(style);\n\n        log('Performance & UI CSS injected.');\n\n    };\n\n    const fixDisappearingContent = () => {\n\n        const originalIntersectionObserver = window.IntersectionObserver;\n\n        window.IntersectionObserver = function(callback, options) {\n\n            const newCallback = (entries, observer) => {\n\n                const modifiedEntries = entries.map(entry => {\n\n                    if (entry.target.closest('.turn, ms-chat-turn') && !entry.isIntersecting) {\n\n                        return new Proxy(entry, {\n\n                            get: (target, prop) => (prop === 'isIntersecting' ? true : Reflect.get(target, prop))\n\n                        });\n\n                    }\n\n                    return entry;\n\n                });\n\n                return callback(modifiedEntries, observer);\n\n            };\n\n            return new originalIntersectionObserver(newCallback, options);\n\n        };\n\n        log('Disappearing content/flicker fix is active.');\n\n    };\n\n    const fixScrollFighting = (chatContainer) => {\n\n        const originalScrollIntoView = Element.prototype.scrollIntoView;\n\n        let isUserScrolling = false;\n\n        let scrollBlockTimer;\n\n        const blockAppScrolls = () => {\n\n            isUserScrolling = true;\n\n            clearTimeout(scrollBlockTimer);\n\n            scrollBlockTimer = setTimeout(() => isUserScrolling = false, 1000);\n\n        };\n\n        chatContainer.addEventListener('wheel', blockAppScrolls, { passive: true, capture: true });\n\n        chatContainer.addEventListener('keydown', blockAppScrolls, { passive: true, capture: true });\n\n        document.body.addEventListener('click', (e) => {\n\n            const button = e.target.closest('button');\n\n            if (button && button.getAttribute('aria-label')?.toLowerCase().includes('edit')) {\n\n                const turnElement = e.target.closest('ms-chat-turn');\n\n                if (turnElement) {\n\n                    log('Edit click detected. Manually scrolling element into view.');\n\n                    setTimeout(() => {\n\n                        turnElement.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n\n                    }, 50);\n\n                }\n\n            }\n\n        }, true);\n\n        Element.prototype.scrollIntoView = function(...args) {\n\n            if (isUserScrolling && chatContainer.contains(this)) {\n\n                log('Blocked app-forced scroll due to user wheel/key action.');\n\n                return;\n\n            }\n\n            return originalScrollIntoView.apply(this, args);\n\n        };\n\n        log('Direct-control scroll fix is active.');\n\n    };\n\n    let fixesInitialized = false;\n\n    const runAllFixes = () => {\n\n        if (fixesInitialized || !document.body) return;\n\n        addGlobalStyle();\n\n        fixDisappearingContent();\n\n        const observer = new MutationObserver(() => {\n\n            const chatContainer = document.querySelector('main .conversation-container');\n\n            if (chatContainer) {\n\n                log('Chat container found. Applying targeted fixes.');\n\n                fixScrollFighting(chatContainer);\n\n                fixesInitialized = true;\n\n                observer.disconnect();\n\n            }\n\n        });\n\n        observer.observe(document.body, { childList: true, subtree: true });\n\n    };\n\n    if (document.readyState === 'loading') {\n\n        document.addEventListener('DOMContentLoaded', runAllFixes);\n\n    } else {\n\n        runAllFixes();\n\n    }\n\n})();", "url": "https://wpnews.pro/news/a-user-script-that-fixes-major-performance-and-ux-issues-on-google-s-ai-studio-a", "canonical_source": "https://gist.github.com/DiyarD/dc51b79c8cf446aa662e79638f9aeba3", "published_at": "2025-07-02 15:56:40+00:00", "updated_at": "2026-05-22 13:49:03.025178+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "large-language-models"], "entities": ["Google AI Studio", "Diyar Baban", "Tampermonkey"], "alternates": {"html": "https://wpnews.pro/news/a-user-script-that-fixes-major-performance-and-ux-issues-on-google-s-ai-studio-a", "markdown": "https://wpnews.pro/news/a-user-script-that-fixes-major-performance-and-ux-issues-on-google-s-ai-studio-a.md", "text": "https://wpnews.pro/news/a-user-script-that-fixes-major-performance-and-ux-issues-on-google-s-ai-studio-a.txt", "jsonld": "https://wpnews.pro/news/a-user-script-that-fixes-major-performance-and-ux-issues-on-google-s-ai-studio-a.jsonld"}}