Several changes I should have committed sooner, they would be better
with seperate commits but I never got around to it
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
<!--
|
||||
Profile picture upload widget.
|
||||
Drop into a Content: block.
|
||||
|
||||
Client-side, this only checks that the file is *some* readable image -
|
||||
no type or dimension restriction, since the server now accepts any
|
||||
recognizable image format, center-crops it to square, downscales to
|
||||
32x32, and always transcodes to GIF. The username is derived from the
|
||||
session cookie server-side, never from the client.
|
||||
-->
|
||||
<div id="pfp-upload">
|
||||
<img id="pfp-preview" src="/Images/default_pfp.gif" alt="Profile picture preview"
|
||||
style="width:64px; height:64px; image-rendering:pixelated; display:block; margin-bottom:8px; border:1px solid #888;">
|
||||
|
||||
<input type="file" id="pfp-file" accept="image/*">
|
||||
|
||||
<p id="pfp-status" style="margin-top:8px;"></p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const fileInput = document.getElementById("pfp-file");
|
||||
const preview = document.getElementById("pfp-preview");
|
||||
const status = document.getElementById("pfp-status");
|
||||
|
||||
function setStatus(msg, isError) {
|
||||
status.textContent = msg;
|
||||
status.style.color = isError ? "#c0392b" : "#2c7a2c";
|
||||
}
|
||||
|
||||
fileInput.addEventListener("change", async () => {
|
||||
const file = fileInput.files[0];
|
||||
if (!file) return;
|
||||
|
||||
setStatus("Checking image...", false);
|
||||
|
||||
let objectUrl;
|
||||
try {
|
||||
// Just confirm the browser can decode it as an image at all - the
|
||||
// actual format whitelist, cropping, and resizing happens server-side.
|
||||
await new Promise((resolve, reject) => {
|
||||
objectUrl = URL.createObjectURL(file);
|
||||
const img = new Image();
|
||||
img.onload = () => resolve();
|
||||
img.onerror = () => reject(new Error("That doesn't look like a readable image."));
|
||||
img.src = objectUrl;
|
||||
});
|
||||
|
||||
// Looks good locally - show the preview immediately.
|
||||
preview.src = objectUrl;
|
||||
|
||||
setStatus("Uploading...", false);
|
||||
|
||||
const response = await fetch("/upload?name=profileimages", {
|
||||
method: "POST",
|
||||
credentials: "same-origin", // send the session cookie
|
||||
body: file,
|
||||
});
|
||||
|
||||
const text = await response.text();
|
||||
|
||||
if (!response.ok) {
|
||||
setStatus("Upload failed: " + text, true);
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus("Profile picture updated!", false);
|
||||
} catch (err) {
|
||||
setStatus(err.message || "Something went wrong.", true);
|
||||
} finally {
|
||||
fileInput.value = "";
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
Reference in New Issue
Block a user