Files
2026-08-23 21:00:22 -07:00

76 lines
2.3 KiB
HTML

<!--
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>