OpenAI Playground Config Panel Toggle

Toggle the configuration panel in OpenAI Playground with a sleek arrow button

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==UserScript==
// @name         OpenAI Playground Config Panel Toggle
// @namespace    https://github.com/NoahTheGinger/
// @version      3.2
// @description  Toggle the configuration panel in OpenAI Playground with a sleek arrow button
// @author       NoahTheGinger
// @match        https://platform.openai.com/chat
// @match        https://platform.openai.com/chat/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    let configPanel = null;
    let chatContainer = null;
    let toggleButton = null;
    let isPanelHidden = false;
    let parentContainer = null;

    // Function to find the configuration panel
    function findConfigPanel() {
        // Look for the panel containing Model, Variables, Tools sections
        const panels = document.querySelectorAll('div[class*="neIqM"], div[class*="_0-y9H"]');
        for (const panel of panels) {
            const text = panel.innerText || '';
            if (text.includes('Model') && text.includes('Variables') && text.includes('Tools')) {
                return panel.closest('div[class*="_0-y9H"]') || panel;
            }
        }
        return null;
    }

    // Function to find the chat container and parent
    function findContainers() {
        // Find the config panel first
        const config = findConfigPanel();
        if (!config) return { config: null, chat: null, parent: null };

        // Find the parent that contains both config and chat
        let parent = config.parentElement;
        while (parent) {
            // Look for a flex container that has both panels
            if (parent.style.display === 'flex' || 
                (parent.classList && Array.from(parent.classList).some(c => c.includes('flex')))) {
                
                const children = Array.from(parent.children);
                if (children.length >= 2) {
                    // Find the chat container (should be after config panel)
                    const chatIndex = children.indexOf(config) + 1;
                    if (chatIndex < children.length) {
                        return {
                            config: config,
                            chat: children[chatIndex],
                            parent: parent
                        };
                    }
                }
            }
            parent = parent.parentElement;
        }
        
        return { config: config, chat: null, parent: null };
    }

    // Function to create the toggle button
    function createToggleButton() {
        const button = document.createElement('button');
        button.innerHTML = `
            <svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor">
                <path d="M7.5 3L4.5 6L7.5 9" stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
        `;
        
        button.style.cssText = `
            position: absolute;
            right: -16px;
            top: 50%;
            transform: translateY(-50%);
            z-index: 1000;
            background: #ffffff;
            border: 1px solid #e5e5e5;
            border-radius: 6px;
            padding: 6px;
            cursor: pointer;
            transition: all 0.2s ease;
            display: flex;
            align-items: center;
            justify-content: center;
            width: 28px;
            height: 28px;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
            color: #666;
        `;

        button.addEventListener('mouseenter', () => {
            button.style.background = '#f7f7f7';
            button.style.borderColor = '#d5d5d5';
            button.style.color = '#333';
        });

        button.addEventListener('mouseleave', () => {
            button.style.background = '#ffffff';
            button.style.borderColor = '#e5e5e5';
            button.style.color = '#666';
        });

        button.addEventListener('click', togglePanel);
        
        return button;
    }

    // Function to update button position
    function updateButtonPosition() {
        if (!toggleButton || !configPanel) return;

        if (isPanelHidden) {
            // When hidden, attach to chat container's left edge but with proper offset
            if (chatContainer) {
                chatContainer.style.position = 'relative';
                toggleButton.style.position = 'absolute';
                toggleButton.style.right = 'auto';
                toggleButton.style.left = '8px'; // Changed from -16px to 8px to stay visible
                
                if (toggleButton.parentElement !== chatContainer) {
                    chatContainer.appendChild(toggleButton);
                }
            }
        } else {
            // When visible, attach to config panel's right edge
            configPanel.style.position = 'relative';
            toggleButton.style.position = 'absolute';
            toggleButton.style.left = 'auto';
            toggleButton.style.right = '-16px';
            
            if (toggleButton.parentElement !== configPanel) {
                configPanel.appendChild(toggleButton);
            }
        }
    }

    // Function to toggle the panel
    function togglePanel() {
        if (!configPanel || !chatContainer) {
            // Try to find containers again
            const containers = findContainers();
            configPanel = containers.config;
            chatContainer = containers.chat;
            parentContainer = containers.parent;
        }

        if (!configPanel || !chatContainer) return;

        isPanelHidden = !isPanelHidden;

        if (isPanelHidden) {
            // Store original values
            configPanel.dataset.originalWidth = configPanel.style.width || '';
            configPanel.dataset.originalFlex = configPanel.style.flex || '';
            chatContainer.dataset.originalFlex = chatContainer.style.flex || '';
            
            // Hide the config panel
            configPanel.style.transition = 'all 0.3s ease';
            configPanel.style.width = '0';
            configPanel.style.minWidth = '0';
            configPanel.style.overflow = 'hidden';
            configPanel.style.opacity = '0';
            configPanel.style.flex = '0 0 0';
            configPanel.style.padding = '0';
            configPanel.style.margin = '0';
            
            // Expand the chat container
            chatContainer.style.transition = 'all 0.3s ease';
            chatContainer.style.flex = '1 1 100%';
            chatContainer.style.width = '100%';
            chatContainer.style.maxWidth = '100%';
            
            // Update button icon (right arrow)
            toggleButton.innerHTML = `
                <svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor">
                    <path d="M4.5 3L7.5 6L4.5 9" stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
                </svg>
            `;
            
            // Move button after a delay
            setTimeout(() => {
                updateButtonPosition();
            }, 150);
        } else {
            // First move the button back
            updateButtonPosition();
            
            // Then restore the config panel
            setTimeout(() => {
                configPanel.style.transition = 'all 0.3s ease';
                configPanel.style.width = configPanel.dataset.originalWidth || '';
                configPanel.style.minWidth = '';
                configPanel.style.overflow = '';
                configPanel.style.opacity = '1';
                configPanel.style.flex = configPanel.dataset.originalFlex || '';
                configPanel.style.padding = '';
                configPanel.style.margin = '';
                
                // Restore chat container
                chatContainer.style.transition = 'all 0.3s ease';
                chatContainer.style.flex = chatContainer.dataset.originalFlex || '';
                chatContainer.style.width = '';
                chatContainer.style.maxWidth = '';
                
                // Update button icon (left arrow)
                toggleButton.innerHTML = `
                    <svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor">
                        <path d="M7.5 3L4.5 6L7.5 9" stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
                    </svg>
                `;
            }, 50);
        }
    }

    // Function to initialize the script
    function init() {
        // Find the containers
        const containers = findContainers();
        configPanel = containers.config;
        chatContainer = containers.chat;
        parentContainer = containers.parent;

        if (configPanel && chatContainer && !toggleButton) {
            // Create and add the toggle button
            toggleButton = createToggleButton();
            configPanel.style.position = 'relative';
            configPanel.appendChild(toggleButton);
            
            console.log('OpenAI Playground Toggle initialized');
        }
    }

    // Wait for the page to load and initialize
    function waitForLoad() {
        if (document.readyState === 'complete' || document.readyState === 'interactive') {
            setTimeout(init, 1000);
        } else {
            document.addEventListener('DOMContentLoaded', () => setTimeout(init, 1000));
        }
    }

    waitForLoad();

    // Re-initialize on navigation changes (SPA)
    let lastUrl = location.href;
    new MutationObserver(() => {
        const url = location.href;
        if (url !== lastUrl) {
            lastUrl = url;
            setTimeout(init, 1000);
        }
    }).observe(document, { subtree: true, childList: true });

    // Also watch for dynamic content changes
    const observer = new MutationObserver((mutations) => {
        if (!configPanel || !chatContainer) {
            init();
        }
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

})();