Strawpage Image Uploader

Upload and manipulate images on Strawpage

// ==UserScript==
// @name         Strawpage Image Uploader
// @namespace    http://tampermonkey.net/
// @version      2024-07-27
// @description  Upload and manipulate images on Strawpage
// @author       You
// @match        https://*.straw.page/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=straw.page
// @grant        none
// @license      The Unlicense
// ==/UserScript==

(function() {
    'use strict';

    $(".picasso canvas").each(function() {
        let canvasContainer = $(this).closest(".element");
        let canvas = this;
        let ctx = canvas.getContext('2d');
        let pixelRatio = window.devicePixelRatio || 1;
        let strokeColor = $(canvasContainer).css("--co").trim();
        let strokeWidth = 4;

        function isContextLost(context) {
            try {
                return false;
            } catch (e) {
                return true;
            }
        }

        if ($(window).width() < 450) {
            strokeWidth = 2;
        }

        ctx.canvas.width = $(canvas).outerWidth() * pixelRatio;
        ctx.canvas.height = $(canvas).outerHeight() * pixelRatio;
        ctx.scale(pixelRatio, pixelRatio);
        ctx.fillStyle = 'white';
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        let isDrawing = false;
        let lastX = 0;
        let lastY = 0;
        let undoStack = [];
        let undoIndex = -1;

        function startDrawing(event) {
            event.preventDefault();
            if (event.type == "touchstart") {
                let rect = canvas.getBoundingClientRect();
                lastX = event.touches[0].clientX - rect.left;
                lastY = event.touches[0].clientY - rect.top;
            } else {
                lastX = event.offsetX;
                lastY = event.offsetY;
            }
            isDrawing = true;
        }

        function draw(event) {
            event.preventDefault();
            if (isDrawing === true) {
                let currentX, currentY;
                if (event.type == "touchmove") {
                    let rect = canvas.getBoundingClientRect();
                    currentX = event.touches[0].clientX - rect.left;
                    currentY = event.touches[0].clientY - rect.top;
                } else {
                    currentX = event.offsetX;
                    currentY = event.offsetY;
                }
                drawLine(ctx, lastX, lastY, currentX, currentY);
                lastX = currentX;
                lastY = currentY;
            }
        }

        function stopDrawing(event) {
            if (isDrawing === true) {
                let endX, endY;
                if (event.type == 'touchend') {
                    let rect = canvas.getBoundingClientRect();
                    endX = event.changedTouches[0].clientX - rect.left;
                    endY = event.changedTouches[0].clientY - rect.top;
                } else {
                    endX = event.offsetX;
                    endY = event.offsetY;
                }
                drawLine(ctx, lastX, lastY, endX, endY);
                lastX = 0;
                lastY = 0;
                isDrawing = false;
                undoStack = undoStack.slice(0, undoIndex + 1);
                undoStack.push(ctx.getImageData(0, 0, canvas.width, canvas.height));
                undoIndex++;
                if (undoStack.length > 50) {
                    undoStack.shift();
                    undoIndex--;
                }
            }
        }

        canvas.addEventListener('mousedown', startDrawing);
        canvas.addEventListener("touchstart", startDrawing);
        canvas.addEventListener("mousemove", draw);
        canvas.addEventListener('touchmove', draw);
        window.addEventListener("mouseup", stopDrawing);
        window.addEventListener("touchend", stopDrawing);
        canvas.addEventListener("mouseleave", stopDrawing);
        canvas.addEventListener("touchleave", stopDrawing);

        function drawLine(context, x1, y1, x2, y2) {
            context.beginPath();
            context.strokeStyle = strokeColor;
            context.lineWidth = strokeWidth;
            context.moveTo(x1, y1);
            context.lineTo(x2, y2);
            context.lineCap = context.lineJoin = "round";
            context.stroke();
            context.closePath();
        }

        function undo() {
            if (undoIndex <= 0) {
                clearCanvas();
            } else {
                undoIndex -= 1;
                ctx.putImageData(undoStack[undoIndex], 0, 0);
            }
        }

        function clearCanvas() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = 'white';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            undoStack = [];
            undoIndex = -1;
        }

        $(canvasContainer).find('.canvCol').click(function() {
            $(canvasContainer).find('input[type=color]').click();
        });

        var isMobileDevice = navigator.maxTouchPoints > 1 && screen.height >= 768 && screen.width >= 768;
        if (navigator.userAgent.match(/(iPod|iPhone|iPad)/) || isMobileDevice) {
            $(canvasContainer).find(".canvCol,label").remove();
            $(canvasContainer).find("input[type=color]").css({
                'visibility': 'visible',
                'position': "static",
                'height': "1.1em",
                'width': "1.1em",
                'border-radius': "50%",
                'margin': "0 0.4em"
            });
        }

        $(canvasContainer).find("input[type=color]").on("input change", function() {
            strokeColor = $(this).val();
        });

        $(canvasContainer).find("input[type=range]").on("input change", function() {
            strokeWidth = $(this).val();
        });

        $(canvasContainer).find(".fa-undo").click(function() {
            undo();
        });

        function sendArtwork() {
            if (isContextLost(ctx)) {
                window.location.reload();
                return;
            }
            if (undoStack.length < 1) {
                return;
            }
            if ($(".sendPicasso button").text() == "Sending your art...") {
                return;
            }
            $(canvasContainer).find(".sendPicasso button").text("Sending your art...");
            var userId = $("meta[name='straw:user']").attr("content");
            let imageData = canvas.toDataURL("image/png") + '-' + userId + "xNNkISDNFkoovdmRKUyeQcOHyvnfgQVfbLkjXbiuLGYpMHIxOyjRDjBxnzqcSlXRPHzcljrZxdtWMTnnBrLBHhNqoJLVfxPLlBfdBOxPCZkBZUwQmqexdZjHTekoWomkXUONQJjGWqLEfiYAINdRFgMZyjVNQDfEGufrpPkwedDnELuzrMWqoD";
            $.ajax({
                'type': "POST",
                'url': "/gimmicks/canvas",
                'data': {
                    'image': imageData
                },
                'success': function(response) {
                    ok.track("sent drawing!");
                    $(canvasContainer).find(".sendPicasso button").text("Sent! 👨‍🎨");
                    $(canvasContainer).addClass('doneArt');
                }
            });
        }

        $(canvasContainer).find(".sendPicasso button").click(function() {
            sendArtwork();
        });

        $(document).ready(function() {
            const uploadIcon = '<i class="fas fa-upload" title="Upload Image"></i>';

            $('.toolbox').append(uploadIcon);

            $(document).on('click', '.fa-upload', function() {
                const input = $('<input type="file" accept="image/*">');
                input.on('change', function(event) {
                    const file = event.target.files[0];
                    if (file) {
                        const reader = new FileReader();
                        reader.onload = function(e) {
                            const img = new Image();
                            img.onload = function() {
                                ctx.clearRect(0, 0, canvas.width, canvas.height);
                                ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
                                undoStack.push(ctx.getImageData(0, 0, canvas.width, canvas.height));
                            };
                            img.src = e.target.result;
                        };
                        reader.readAsDataURL(file);
                    }
                });
                input.click();
            });
        });
    });

    $(document).on("click", ".doneArt .completionCasso button", function() {
        try {
            window.fathom.trackGoal("N11W936N", 0);
        } catch (error) {}
        window.location.href = 'https://straw.page/start';
    });
})();