Greasy Fork is available in English.

Copy Code in Code Block Footer

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

// ==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 });
})();