copy images in one click freepik

provides two buttons on each image: to copy image URL and to copy image itself in the clipboard

// ==UserScript==
// @name         copy images in one click freepik
// @namespace    http://tampermonkey.net/
// @version      1.0.2
// @description  provides two buttons on each image: to copy image URL and to copy image itself in the clipboard
// @author       GreatFireDragon
// @match        https://*.freepik.com/search*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=freepik.com
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==



(function() {
    'use strict';

    GM_addStyle(`
body #__next:nth-child(4) {
   background-color: red;
    visibility: hidden;
   height: 0;
   width: 0;
}

div[data-ssm],
figure[data-cy] > aside,
figure[data-cy] figcaption {
    display: none;
}

.smiley-wrapper,
.heart-wrapper{
    position: absolute;
    top: 0; right: 0;
    padding: 5px;
    background-color: grey;
    opacity: 0.3;
    transition: 1s;
    cursor: copy;
}

.heart-wrapper {right: 31px;}

.smiley-wrapper:hover,
.heart-wrapper:hover{
    opacity: 1;
}

@keyframes backgroundColorChange {
    0% {background-color: initial;}
    50% {
        background-color: #01cd5d;
        scale: 2;
    }
    100% {background-color: initial;}
}
.copied {
    animation: backgroundColorChange 0.5s ease-in-out infinite;
}
figure.clicked {
   filter: grayscale(100%);
   transition: filter 0.5s;
}
figure.clicked:hover {
    filter: grayscale(0%);
}
button#clearTakenImages {
    color: #cacaca;
    font-weight: bold;
    transitioN: 0.5s;
}
button#clearTakenImages:hover {
    scale: 1.2;
}
`)

    // Constants
    const CLICKED_CLASS = "clicked";
    const SMILEY_WRAPPER_CLASS = "smiley-wrapper";
    const HEART_WRAPPER_CLASS = "heart-wrapper";
    const COPIED_CLASS = "copied";
    const SMILEY_EMOJI = "😀";
    const HEART_EMOJI = "😍";
    const CLEAR_BUTTON_ID = "clearTakenImages";

    var urlsToCopy = [];

    function loadClickedImages() {
        var clickedImages = localStorage.getItem("clickedImages");
        return clickedImages ? JSON.parse(clickedImages) : [];
    }

    function saveClickedImage(url) {
        var clickedImages = loadClickedImages();
        if (!clickedImages.includes(url)) {
            clickedImages.push(url);
            localStorage.setItem("clickedImages", JSON.stringify(clickedImages));
        }
    }

    function applyClickedClass() {
        var clickedImages = loadClickedImages();
        var allFigures = document.querySelectorAll("figure[data-cy]");
        allFigures.forEach((figure) => {
            var imgElement = figure.querySelector("img");
            if (imgElement && clickedImages.includes(imgElement.src)) {
                figure.classList.add(CLICKED_CLASS);
            }
        });
    }

    function handleSmileyClick(event, figure, imgElement) {
        var url = imgElement.src;
        saveClickedImage(url);
        figure.classList.add(CLICKED_CLASS);

        if (event.shiftKey || event.ctrlKey) {
            urlsToCopy.push(url);
            setCopiedState(event.target);
        } else {
            navigator.clipboard.writeText(url).then(() => {
                setCopiedState(event.target);
            });
        }
    }

    function handleHeartClick(figure, imgElement) {
        var url = imgElement.src;
        saveClickedImage(url);
        figure.classList.add(CLICKED_CLASS);

        var xhr = new XMLHttpRequest();
        xhr.open("GET", url, true);
        xhr.responseType = "blob";
        xhr.onload = function () {
            if (xhr.status === 200) {
                var blob = xhr.response;
                var reader = new FileReader();
                reader.onloadend = function () {
                    var img = new Image();
                    img.src = reader.result;
                    img.onload = function () {
                        var canvas = document.createElement("canvas");
                        canvas.width = img.width;
                        canvas.height = img.height;
                        var ctx = canvas.getContext("2d");
                        ctx.drawImage(img, 0, 0);
                        canvas.toBlob(function (blob) {
                            var item = new ClipboardItem({ "image/png": blob });
                            navigator.clipboard.write([item]).then(() => {
                                setCopiedState(figure.querySelector(`.${HEART_WRAPPER_CLASS}`));
                            }).catch((err) => {
                                console.error("Failed to copy image: ", err);
                            });
                        }, "image/png");
                    };
                };
                reader.readAsDataURL(blob);
            }
        };
        xhr.send();
    }

    function setCopiedState(element) {
        element.classList.add(COPIED_CLASS);
        setTimeout(() => element.classList.remove(COPIED_CLASS), 500);
    }

    function addSmileyDivs() {
        var allFigures = document.querySelectorAll("figure[data-cy]");
        allFigures.forEach((figure) => {
            var imgElement = figure.querySelector("img");
            if (!imgElement) return;

            if (!figure.querySelector(`.${SMILEY_WRAPPER_CLASS}`)) {
                var smileyDiv = document.createElement("div");
                smileyDiv.textContent = SMILEY_EMOJI;
                smileyDiv.classList.add(SMILEY_WRAPPER_CLASS);
                smileyDiv.addEventListener("click", function (event) {
                    handleSmileyClick(event, figure, imgElement);
                });
                figure.appendChild(smileyDiv);
            }

            if (!figure.querySelector(`.${HEART_WRAPPER_CLASS}`)) {
                var heartDiv = document.createElement("div");
                heartDiv.textContent = HEART_EMOJI;
                heartDiv.classList.add(HEART_WRAPPER_CLASS);
                heartDiv.addEventListener("click", function () {
                    handleHeartClick(figure, imgElement);
                });
                figure.appendChild(heartDiv);
            }
        });

        applyClickedClass();
    }

    function clearClickedImages() {
        localStorage.removeItem("clickedImages");
        var allFigures = document.querySelectorAll(`figure.${CLICKED_CLASS}`);
        allFigures.forEach(figure => {
            figure.classList.remove(CLICKED_CLASS);
        });
    }

    function addClearButton() {
        if (!document.getElementById(CLEAR_BUTTON_ID)) {
            const clearButton = document.createElement("button");
            clearButton.id = CLEAR_BUTTON_ID;
            clearButton.textContent = "Clear Taken Images";
            clearButton.addEventListener("click", clearClickedImages);

            document.body.appendChild(clearButton);
        }
    }


    document.addEventListener("keyup", function (event) {
        if (event.key === "Shift" || event.key === "Control") {
            if (urlsToCopy.length > 0) {
                var urlsString = urlsToCopy.join(" ");
                navigator.clipboard.writeText(urlsString).then(() => {
                    urlsToCopy = [];
                });
            }
        }
    });

    var observer = new MutationObserver(function (mutationsList) {
        for (var mutation of mutationsList) {
            if (mutation.type === "childList" || mutation.type === "attributes") {
                addSmileyDivs();
                addClearButton();
                break;
            }
        }
    });

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

    addSmileyDivs();
    addClearButton();

})();