I've gone ahead and implemented paste functionality, allowing you to simply press paste while having an image copied to your clipboard. Note that it does not open any sort of UI, but the cursor will show a waiting spinner while the image is being uploaded. When the upload finishes, the URL is automatically inserted into the text box.
Here's the new userscript:
// ==UserScript==
// @name Chat Image Upload
// @description Drag and Drop upload images
// @author fredley
// @version 1.0.0
// @match *://chat.meta.stackoverflow.com/rooms/*
// @match *://chat.meta.stackexchange.com/rooms/*
// @match *://chat.stackexchange.com/rooms/*
// @match *://chat.stackoverflow.com/rooms/*
// @match *://chat.askubuntu.com/rooms/*
// @match *://chat.serverfault.com/rooms/*
// @run-at document-end
// ==/UserScript==
function inject() {
for (var i = 0; i < arguments.length; ++i) {
if (typeof arguments[i] == "function") {
var script = document.createElement("script");
script.type = "text/javascript";
script.textContent = "(" + arguments[i].toString() + ")(jQuery)";
document.body.appendChild(script);
}
}
}
inject(function ($) {
async function uploadFile(fkey, image) {
const formdata = new FormData();
formdata.append("filename", image), formdata.append("fkey", fkey);
try {
const response = await fetch("https://chat.stackexchange.com/upload/image", { method: "post", body: formdata }),
responseText = await response.text();
const responseParsed = responseText.match(/var result = '(.+)'/);
if (!responseParsed) {
console.error("Failed to upload image", responseText);
return "ERROR";
} else return responseParsed[1];
} catch (e) {
console.error(e);
}
}
$(document).ready(function () {
$("body").append('<div id="dropper"><h1>Upload image!</h1></div>');
$("body").append(
"<style>#dropper{display:none;position:fixed;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:9999;}#dropper h1{text-align:center;padding-top:200px;position:absolute;width:100%;color:#FFF;font-size:450%;font-weight:bold;font-family:Helvetica;}body.waiting *{cursor:progress;}</style>"
);
$("body").on({
dragenter: function (e) {
$("#dropper").show();
e.preventDefault();
e.stopPropagation();
},
dragover: function (e) {
$("#dropper").show();
e.preventDefault();
e.stopPropagation();
},
dragend: function (e) {
$("#dropper").hide();
e.preventDefault();
e.stopPropagation();
},
drop: function (e) {
$("#dropper").hide();
if (e.originalEvent.dataTransfer && e.originalEvent.dataTransfer.files.length) {
console.log("upload!");
e.preventDefault();
e.stopPropagation();
var files = e.originalEvent.dataTransfer.files;
initFileUpload().showDialog(function (a) {
$("#input").val($("#input").val() + a);
$("#input").focus();
});
setTimeout(function () {
$("#filename-input").prop("files", files);
setTimeout(function () {
$('input[value="upload"]').click();
}, 20);
}, 20);
}
},
paste: async function (e) {
// upload the image from clipboard
try {
const clipboardItems = await navigator.clipboard.read();
for (const clipboardItem of clipboardItems) {
const imageType = clipboardItem.types.find((type) => type.startsWith("image/"));
if (!imageType) {
return;
}
const blob = await clipboardItem.getType(imageType);
const fkey = $("#fkey").val();
document.body.classList.add("waiting");
const response = await uploadFile(fkey, blob);
document.body.classList.remove("waiting");
if (response !== "ERROR") {
$("#input").val($("#input").val() + response);
$("#input").focus();
}
}
} catch (err) {
console.error(err.name, err.message);
}
},
});
$("#dropper").on("click", function (e) {
$(this).hide();
});
});
});
And the download link: