class PictureUpload extends HTMLElement { constructor() { super(); } connectedCallback() { this.tabIndex = 0; this.gotoInit(); this.preview = this.querySelector("img[name='preview']"); this.addEventListener("click", (event) => { if (event.target == this || event.target.parentElement == this) { event.preventDefault(); this.focus(); } }); this.addEventListener("paste", async (event) => { if (event.clipboardData.items.length != 1) { console.error("only one item is supported"); return; } let item = event.clipboardData.items[0]; await this.paste(item); }); } gotoInit() { this.setState("init"); this.innerHTML = `
paste or drop an image here to make a picture out of it
`; } async gotoHavePicture(imageType, imageFile) { this.setState("have-picture"); this.innerHTML = `
preview

× px ()

`; let preview = this.querySelector("img[name='preview']"); let previewWidth = this.querySelector("[name='preview-width']"); let previewHeight = this.querySelector("[name='preview-height']"); let fileSize = this.querySelector("[name='file-size']"); let label = this.querySelector("[name='label']"); let compression = this.querySelector("[name='compression']"); let upload = this.querySelector("button[name='upload']"); fileSize.textContent = formatSizeSI(imageFile.size); let url = URL.createObjectURL(imageFile); preview.src = url; createImageBitmap(imageFile).then((bitmap) => { console.log(bitmap); previewWidth.textContent = bitmap.width.toString(); previewHeight.textContent = bitmap.height.toString(); }); upload.addEventListener("click", async () => { let params = new URLSearchParams({ label: label.value, format: imageType, compression: compression.value, }); let response = await fetch(`/dev/picture-upload?${params}`, { method: "POST", body: imageFile, }); let json = await response.json(); if (json.error != null) { console.error(json.error); } else { await navigator.clipboard.writeText(json.ulid); await this.gotoCopiedToClipboard(); } }); } async gotoCopiedToClipboard() { this.setState("copied-to-clipboard"); this.innerHTML = `
ulid copied to clipboard; the window will now refresh
`; } setState(name) { this.setAttribute("data-state", name); } async paste(item) { console.log(item); if (!isSupportedImageType(item.type)) { console.error("unsupported mime type", item.type); return; } let file = item.getAsFile(); if (file == null) { console.error("data transfer does not contain a file"); return; } await this.gotoHavePicture(item.type, file); } } customElements.define("th-picture-upload", PictureUpload); function isSupportedImageType(mime) { return ( mime == "image/png" || mime == "image/jpeg" || mime == "image/svg+xml" || mime == "image/webp" ); } function formatSizeSI(bytes) { return new Intl.NumberFormat(undefined, { style: "unit", unit: "byte", notation: "compact", unitDisplay: "narrow", }).format(bytes); }