formats.exposed/public/index/index.js

82 lines
1.9 KiB
JavaScript

// @ts-check
import { SUPPORTED_FILE_TYPES } from "./constants.js";
import crel from "../common/crel.js";
import * as base64url from "../common/base64url.js";
import { routeFile } from "./fileRouter.js";
const accept = SUPPORTED_FILE_TYPES
.flatMap((t) => [t.mimeType, ...t.extensions])
.join(",");
const inputEl = /** @type {HTMLInputElement} */ (
crel("input", {
type: "file",
id: "file-input",
accept,
})
);
const supportedFileTypeNameString = SUPPORTED_FILE_TYPES
.map((t, index, array) => (
(array.length > 1 && (index === array.length - 1))
? `and ${t.name}`
: t.name
))
.join(", ");
const labelParagraphEl = crel(
"p",
{},
crel(
"label",
{ "for": "file-input" },
`Upload something! Supports ${supportedFileTypeNameString} files, with more on the way.`,
),
);
const disclaimerParagraphEl = crel(
"p",
{},
crel("small", {}, "Your files do not leave your computer."),
);
/**
* @param {Blob} blob
* @returns {Promise<string>}
*/
const formatBytes = async (blob) => {
const arrayBuffer = await blob.arrayBuffer();
const bytes = new Uint8Array(arrayBuffer);
return base64url.stringify(bytes);
};
const main = () => {
const appEl = document.getElementById("app");
if (!appEl) throw new Error("HTML is not set up correctly");
inputEl.addEventListener("change", async () => {
const file = inputEl.files?.[0];
if (!file) return;
// TODO: Prevent large files.
const route = await routeFile(file);
if (!route) {
console.warn(
"Uploaded a file that was accepted but not routed. This may indicate a bug.",
);
// TODO: Show something better than this.
alert("Unsupported file type.");
return;
}
location.href = route + "#" + JSON.stringify({
name: file.name,
bytes: await formatBytes(file),
});
});
appEl.append(labelParagraphEl, inputEl, disclaimerParagraphEl);
};
main();