ProgramizX

Mejoras inteligentes para Programiz

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         ProgramizX
// @namespace    http://tampermonkey.net/
// @version      3.0
// @icon         https://i.ibb.co/B5Ks6Fvp/descarga-19.webp
// @description  Mejoras inteligentes para Programiz
// @author       7anvz
// @match        https://www.programiz.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
'use strict';

let fullscreenActivated = false;

// Función para verificar si estamos en una ruta de compilador
function isCompilerRoute() {
    const path = window.location.pathname;
    return path.includes('/online-compiler') ||
           path.includes('/csharp-programming') ||
           path.includes('/python-programming') ||
           path.includes('/java-programming') ||
           path.includes('/cpp-programming') ||
           path.includes('/c-programming');
}

// Función para obtener la extensión del archivo basado en la ruta
function getFileExtension() {
    const path = window.location.pathname;
    if (path.includes('csharp-programming')) return '.cs';
    if (path.includes('python-programming')) return '.py';
    if (path.includes('java-programming')) return '.java';
    if (path.includes('cpp-programming')) return '.cpp';
    if (path.includes('c-programming')) return '.c';
    return '.txt';
}

// Función para obtener el nombre del archivo
function getFileName() {
    const extension = getFileExtension();
    const langMap = {
        '.cs': 'program',
        '.py': 'script',
        '.java': 'Main',
        '.cpp': 'program',
        '.c': 'program'
    };
    return (langMap[extension] || 'code') + extension;
}

// SVG Icons
const downloadSVG = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
    <polyline points="7 10 12 15 17 10"></polyline>
    <line x1="12" y1="15" x2="12" y2="3"></line>
</svg>`;

const startSVG = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <polygon points="5 3 19 12 5 21 5 3"></polygon>
</svg>`;

// Función para aplicar todos los estilos CSS (CORREGIDO)
function applyCustomStyles() {
    const style = document.createElement('style');
    style.textContent = `
        .bn-sale-banner { display: none !important; }
        body.bn-sale-active .container .wrapper { height: calc(128vh - 96px) !important; }
        body.bn-sale-active .sidebar-wrapper { height: calc(128vh - 198px) !important; }

        /* BOTÓN DESCARGAR - ESTILOS BASE */
        .download-code-btn {
            justify-content: center !important;
            gap: 6px !important;
            font-weight: 500 !important;
            font-size: 13px !important;
            line-height: 20px !important;
            align-items: center !important;
            margin-left: 12px !important;
            width: auto !important;
            height: 32px !important;
            border-radius: 4px !important;
            cursor: pointer !important;
            padding: 6px 12px !important;
            display: flex !important;
            white-space: nowrap !important;
            transition: all 0.2s ease !important;
            min-width: 100px !important;
        }

        /* MODO OSCURO */
        .dark-mode .download-code-btn {
            border: 1px solid rgba(255, 255, 255, 0.4) !important;
            background: rgba(255, 255, 255, 0.1) !important;
            color: #ffffff !important;
        }

        .dark-mode .download-code-btn:hover {
            background: rgba(255, 255, 255, 0.2) !important;
            border-color: rgba(255, 255, 255, 0.6) !important;
        }

        /* MODO CLARO */
        .container:not(.dark-mode) .download-code-btn {
            border: 1px solid rgba(0, 0, 0, 0.2) !important;
            background: rgba(0, 0, 0, 0.05) !important;
            color: #333333 !important;
        }

        .container:not(.dark-mode) .download-code-btn:hover {
            background: rgba(0, 0, 0, 0.1) !important;
            border-color: rgba(0, 0, 0, 0.3) !important;
        }

        /* BOTÓN START - ESTILOS BASE */
        .desktop-run-button.run {
            justify-content: center !important;
            gap: 6px !important;
            font-weight: 500 !important;
            font-size: 13px !important;
            line-height: 20px !important;
            align-items: center !important;
            margin-left: 8px !important;
            width: auto !important;
            height: 32px !important;
            border-radius: 4px !important;
            cursor: pointer !important;
            padding: 6px 12px !important;
            display: flex !important;
            white-space: nowrap !important;
            transition: all 0.2s ease !important;
            min-width: 80px !important;
        }

        /* MODO OSCURO */
        .dark-mode .desktop-run-button.run {
            border: 1px solid rgba(255, 255, 255, 0.4) !important;
            background: rgba(255, 255, 255, 0.1) !important;
            color: #ffffff !important;
        }

        .dark-mode .desktop-run-button.run:hover {
            background: rgba(255, 255, 255, 0.2) !important;
            border-color: rgba(255, 255, 255, 0.6) !important;
        }

        /* MODO CLARO */
        .container:not(.dark-mode) .desktop-run-button.run {
            border: 1px solid rgba(0, 0, 0, 0.2) !important;
            background: rgba(0, 0, 0, 0.05) !important;
            color: #333333 !important;
        }

        .container:not(.dark-mode) .desktop-run-button.run:hover {
            background: rgba(0, 0, 0, 0.1) !important;
            border-color: rgba(0, 0, 0, 0.3) !important;
        }

        /* BOTÓN RUN MÓVIL - TAMAÑO CORREGIDO */
        .mobile-top-bar-run-button.run {
            justify-content: center !important;
            align-items: center !important;
            width: 32px !important;
            height: 28px !important;
            border-radius: 4px !important;
            cursor: pointer !important;
            padding: 6px !important;
            display: flex !important;
            transition: all 0.2s ease !important;
            margin-left: 6px !important;
        }

        /* MODO OSCURO */
        .dark-mode .mobile-top-bar-run-button.run {
            border: 1px solid rgba(255, 255, 255, 0.4) !important;
            background: rgba(255, 255, 255, 0.1) !important;
        }

        .dark-mode .mobile-top-bar-run-button.run:hover {
            background: rgba(255, 255, 255, 0.2) !important;
            border-color: rgba(255, 255, 255, 0.6) !important;
        }

        /* MODO CLARO */
        .container:not(.dark-mode) .mobile-top-bar-run-button.run {
            border: 1px solid rgba(0, 0, 0, 0.2) !important;
            background: rgba(0, 0, 0, 0.05) !important;
        }

        .container:not(.dark-mode) .mobile-top-bar-run-button.run:hover {
            background: rgba(0, 0, 0, 0.1) !important;
            border-color: rgba(0, 0, 0, 0.3) !important;
        }

        .mobile-top-bar-run-button.run img {
            width: 14px !important;
            height: 14px !important;
        }

        .dark-mode .mobile-top-bar-run-button.run img {
            filter: invert(1) !important;
        }

        .container:not(.dark-mode) .mobile-top-bar-run-button.run img {
            filter: invert(1) !important;
        }

        /* BOTÓN DESCARGAR MÓVIL - TAMAÑO CORREGIDO */
        .mobile-download-btn {
            justify-content: center !important;
            align-items: center !important;
            margin-left: 6px !important;
            width: 32px !important;
            height: 28px !important;
            border-radius: 4px !important;
            cursor: pointer !important;
            padding: 6px !important;
            display: flex !important;
            transition: all 0.2s ease !important;
        }

        /* MODO OSCURO */
        .dark-mode .mobile-download-btn {
            border: 1px solid rgba(255, 255, 255, 0.4) !important;
            background: rgba(255, 255, 255, 0.1) !important;
        }

        .dark-mode .mobile-download-btn:hover {
            background: rgba(255, 255, 255, 0.2) !important;
            border-color: rgba(255, 255, 255, 0.6) !important;
        }

        /* MODO CLARO */
        .container:not(.dark-mode) .mobile-download-btn {
            border: 1px solid rgba(0, 0, 0, 0.2) !important;
            background: rgba(0, 0, 0, 0.05) !important;
        }

        .container:not(.dark-mode) .mobile-download-btn:hover {
            background: rgba(0, 0, 0, 0.1) !important;
            border-color: rgba(0, 0, 0, 0.3) !important;
        }

        /* ICONOS SVG */
        .download-icon, .start-icon, .mobile-download-icon {
            display: flex !important;
            align-items: center !important;
            justify-content: center !important;
        }

        .download-icon svg, .start-icon svg, .mobile-download-icon svg {
            width: 14px !important;
            height: 14px !important;
        }

        div .header {
            display: none;
        }

        /* ELIMINAR BOTÓN RUN MÓVIL ANTIGUO */
        .mobile-run-button.run {
            display: none !important;
        }

        /* RESPONSIVE MEJORADO - PANTALLA DIVIDIDA */
        @media (max-width: 1200px) {
            .download-text, .start-text, .mobile-download-text {
                display: none !important;
            }

            .download-code-btn, .desktop-run-button.run {
                width: 32px !important;
                min-width: 32px !important;
                height: 28px !important;
                padding: 6px !important;
                margin-left: 6px !important;
            }

            .download-icon svg, .start-icon svg, .mobile-download-icon svg {
                width: 14px !important;
                height: 14px !important;
            }

            /* Asegurar que los botones se alineen correctamente */
            .options-wrapper {
                display: flex !important;
                gap: 6px !important;
                align-items: center !important;
            }

            .mobile-download-btn, .mobile-top-bar-run-button.run {
                margin-left: 10px !important;
                width: 28px !important;
                height: 26px !important;
                padding: 4px !important;
            }

            .mobile-download-icon svg {
                width: 12px !important;
                height: 12px !important;
            }

            .mobile-top-bar-run-button.run img {
                width: 12px !important;
                height: 12px !important;
            }
        }

        /* RESPONSIVE - MÓVIL */
        @media (max-width: 1024px) {
            .desktop-top-bar__btn-wrapper .download-code-btn {
                display: none !important;
            }
            .mobile-top-bar .mobile-download-btn {
                display: flex !important;
            }
        }

        /* RESPONSIVE EXTREMO - PANTALLAS MUY PEQUEÑAS */
        @media (max-width: 768px) {
            .mobile-download-btn, .mobile-top-bar-run-button.run {
                width: 24px !important;
                height: 24px !important;
                padding: 1px !important;
                margin: 6px;
            }

            .mobile-download-icon svg {
                width: 11px !important;
                height: 11px !important;
            }

            .mobile-top-bar-run-button.run img {
                width: 11px !important;
                height: 11px !important;
            }

            .options-wrapper {
                gap: 4px !important;
            }
        }

        /* ESTADOS OCULTOS */
        .download-code-btn.hidden, .mobile-download-btn.hidden {
            display: none !important;
        }
    `;
    document.head.appendChild(style);
}

// Función para extraer el código del editor ACE
function getCodeFromEditor() {
    const aceContent = document.querySelector('.ace_content');
    if (!aceContent) return null;

    const textLines = aceContent.querySelectorAll('.ace_line');
    let code = '';
    textLines.forEach(line => {
        code += (line.textContent || line.innerText) + '\n';
    });
    return code.trim();
}

// Función para descargar el código
function downloadCode() {
    if (!isCompilerRoute()) return;

    const code = getCodeFromEditor();
    if (!code) {
        alert('No se pudo encontrar el código en el editor');
        return;
    }

    const blob = new Blob([code], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = getFileName();
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
}

// Función para modificar el botón Run a Start
function modifyRunButton() {
    const runButton = document.querySelector('.desktop-run-button.run');
    if (runButton && !runButton.querySelector('.start-icon')) {
        runButton.innerHTML = `<span class="start-icon">${startSVG}</span><span class="start-text">Start</span>`;

        const originalOnClick = runButton.onclick;
        if (originalOnClick) {
            runButton.onclick = originalOnClick;
        }
    }
}

// Función para crear botones de descarga
function createDownloadButtons() {
    // Botón desktop
    const desktopWrapper = document.querySelector('.desktop-top-bar__btn-wrapper');
    if (desktopWrapper && !desktopWrapper.querySelector('.download-code-btn')) {
        const downloadBtn = document.createElement('button');
        downloadBtn.className = 'download-code-btn' + (isCompilerRoute() ? '' : ' hidden');
        downloadBtn.innerHTML = `<span class="download-icon">${downloadSVG}</span><span class="download-text">Download</span>`;
        downloadBtn.onclick = downloadCode;

        const shareButton = desktopWrapper.querySelector('.share-button');
        if (shareButton) {
            shareButton.parentNode.insertBefore(downloadBtn, shareButton.nextSibling);
        } else {
            desktopWrapper.appendChild(downloadBtn);
        }
    }

    // Botón móvil - MEJORADO
    const mobileTopBar = document.querySelector('.mobile-top-bar');
    if (mobileTopBar && !mobileTopBar.querySelector('.mobile-download-btn')) {
        const optionsWrapper = mobileTopBar.querySelector('.options-wrapper');
        if (optionsWrapper) {
            const mobileBtn = document.createElement('button');
            mobileBtn.className = 'mobile-download-btn' + (isCompilerRoute() ? '' : ' hidden');
            mobileBtn.innerHTML = `<span class="mobile-download-icon">${downloadSVG}</span><span class="mobile-download-text">Save</span>`;
            mobileBtn.onclick = downloadCode;

            // Insertar al inicio del options-wrapper
            const firstChild = optionsWrapper.firstChild;
            if (firstChild) {
                optionsWrapper.insertBefore(mobileBtn, firstChild);
            } else {
                optionsWrapper.appendChild(mobileBtn);
            }
        }
    }

    // Eliminar botón run móvil antiguo
    const oldMobileRunBtn = document.querySelector('.mobile-run-button.run');
    if (oldMobileRunBtn) {
        oldMobileRunBtn.remove();
    }

    // Modificar botón Run a Start
    modifyRunButton();
}

// Observar cambios de modo oscuro/claro
function observeThemeChanges() {
    const themeObserver = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.attributeName === 'class') {
                // Forzar actualización de estilos cuando cambia la clase
                const container = document.querySelector('.container');
                if (container) {
                    // Los estilos CSS se aplican automáticamente
                    console.log('Modo cambiado:', container.classList.contains('dark-mode') ? 'oscuro' : 'claro');
                }
            }
        });
    });

    const container = document.querySelector('.container');
    if (container) {
        themeObserver.observe(container, { attributes: true, attributeFilter: ['class'] });
    }
}

// FUNCIÓN ULTRA-RÁPIDA PARA FULLSCREEN
function activateFullscreenFast() {
    if (fullscreenActivated) return;

    const fullscreenButton = document.querySelector('#toggle-expanded-mode-desktop');
    if (fullscreenButton) {
        fullscreenButton.click();
        fullscreenActivated = true;

        setTimeout(() => {
            window.dispatchEvent(new Event('resize'));
            document.body.clientHeight;
        }, 50);
    }
}

// Función para manejar cambios de tamaño de ventana
function handleResize() {
    const mobileBtn = document.querySelector('.mobile-download-btn');
    const desktopBtn = document.querySelector('.download-code-btn');

    if (window.innerWidth <= 1024) {
        if (mobileBtn) mobileBtn.classList.toggle('hidden', !isCompilerRoute());
        if (desktopBtn) desktopBtn.classList.add('hidden');
    } else {
        if (desktopBtn) desktopBtn.classList.toggle('hidden', !isCompilerRoute());
        if (mobileBtn) mobileBtn.classList.add('hidden');
    }
}

// Función para ocultar banners
function hideSaleBanner() {
    const banners = document.querySelectorAll('.bn-sale-banner');
    banners.forEach(banner => banner.style.display = 'none');
}

// Observador mejorado para detectar cambios
const observer = new MutationObserver(function(mutations) {
    for (let mutation of mutations) {
        if (mutation.addedNodes.length > 0) {
            for (let node of mutation.addedNodes) {
                if (node.nodeType === 1) {
                    if (node.matches && node.matches('#toggle-expanded-mode-desktop') && !fullscreenActivated) {
                        setTimeout(activateFullscreenFast, 10);
                    }
                    if (node.matches && (node.matches('.desktop-top-bar__btn-wrapper') || node.matches('.mobile-top-bar') || node.matches('.desktop-run-button.run') || node.matches('.options-wrapper'))) {
                        setTimeout(() => {
                            createDownloadButtons();
                            modifyRunButton();
                        }, 10);
                    }
                    if (node.matches && node.matches('.bn-sale-banner')) {
                        hideSaleBanner();
                    }
                }
            }
        }
    }
});

// INICIALIZACIÓN RÁPIDA
function initializeFast() {
    applyCustomStyles();
    hideSaleBanner();
    createDownloadButtons();
    observeThemeChanges();

    window.addEventListener('resize', handleResize);
    document.addEventListener('fullscreenchange', () => {
        fullscreenActivated = !!document.fullscreenElement;
    });

    setTimeout(activateFullscreenFast, 300);
    observer.observe(document.body, { childList: true, subtree: true });
    handleResize();
}

// Detector de cambios de ruta
let currentUrl = location.href;
setInterval(() => {
    if (location.href !== currentUrl) {
        currentUrl = location.href;
        setTimeout(() => {
            createDownloadButtons();
            handleResize();
            if (!fullscreenActivated) {
                setTimeout(activateFullscreenFast, 200);
            }
        }, 100);
    }
}, 500);

// INICIAR
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initializeFast);
} else {
    initializeFast();
}

})();