Copy Code in Code Block Footer

Duplicate the header of code blocks as a footer to give a second copy code button

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Copy Code in Code Block Footer
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Duplicate the header of code blocks as a footer to give a second copy code button
// @author       Gavin Trutzenbach / @gaveroid
// @match        https://chat.openai.com/*
// ==/UserScript==

(function() {
    'use strict';

    // Helper function to copy text to clipboard
    function copyToClipboard(text) {
        var dummy = document.createElement("textarea");
        document.body.appendChild(dummy);
        dummy.value = text;
        dummy.select();
        document.execCommand("copy");
        document.body.removeChild(dummy);
    }

    // Function to process code blocks
    function processCodeBlocks() {
        var codeBlocks = document.querySelectorAll('div[class^="bg-black"]');
        codeBlocks.forEach(function(codeBlock) {
            var headerDiv = codeBlock.querySelector('div[class^="flex items-center"]');
            if (headerDiv && !codeBlock.querySelector('.duplicated-footer')) {
                var footerDiv = headerDiv.cloneNode(true);
                footerDiv.classList.add('duplicated-footer');
                codeBlock.appendChild(footerDiv);

                // Update copy button function
                var updateCopyButtonFunction = function(button) {
                    var originalInnerHTML = button.innerHTML;  // Store the original inner HTML
                    var copyFunction = function() {
                        var codeText = codeBlock.querySelector('code').innerText;
                        copyToClipboard(codeText);
                        this.innerHTML = '✔ Copied!';  // ASCII icon for checkmark
                        var btn = this;
                        setTimeout(function() {
                            btn.innerHTML = originalInnerHTML;  // Revert to original inner HTML
                        }, 3000);  // Revert back after 3 seconds
                    };
                    button.removeEventListener('click', copyFunction);  // Remove old event listener
                    button.addEventListener('click', copyFunction);  // Add new event listener
                };

                // Update copy buttons in header and footer
                var copyButtonHeader = headerDiv.querySelector('button');
                var copyButtonFooter = footerDiv.querySelector('button');
                updateCopyButtonFunction(copyButtonHeader);
                updateCopyButtonFunction(copyButtonFooter);
            }
        });
    }

    // Create a MutationObserver to monitor the DOM for changes
    var observer = new MutationObserver(function(mutationsList, observer) {
        processCodeBlocks();
    });

    // Start observing the document with the configured parameters
    observer.observe(document, { childList: true, subtree: true });
})();