Files
zap.stream/src/element/file-uploader.tsx
Alejandro Gomez 4e4ea9efa6 feat: stream cards improvements
- edit toggle
- reorder with drag and drop
- delete button inside edit modal
- add ability to clear image from card
- make card textarea taller and avoid horizontal resize
2023-07-28 12:00:03 +02:00

88 lines
2.1 KiB
TypeScript

import "./file-uploader.css";
import { VoidApi } from "@void-cat/api";
import { useState } from "react";
const voidCatHost = "https://void.cat";
const fileExtensionRegex = /\.([\w]{1,7})$/i;
const voidCatApi = new VoidApi(voidCatHost);
type UploadResult = {
url?: string;
error?: string;
};
async function voidCatUpload(file: File | Blob): Promise<UploadResult> {
const uploader = voidCatApi.getUploader(file);
const rsp = await uploader.upload({
"V-Strip-Metadata": "true",
});
if (rsp.ok) {
let ext = file.name.match(fileExtensionRegex);
if (rsp.file?.metadata?.mimeType === "image/webp") {
ext = ["", "webp"];
}
const resultUrl =
rsp.file?.metadata?.url ??
`${voidCatHost}/d/${rsp.file?.id}${ext ? `.${ext[1]}` : ""}`;
const ret = {
url: resultUrl,
} as UploadResult;
return ret;
} else {
return {
error: rsp.errorMessage,
};
}
}
export function FileUploader({ defaultImage, onClear, onFileUpload }) {
const [img, setImg] = useState(defaultImage);
const [isUploading, setIsUploading] = useState(false);
async function onFileChange(ev) {
const file = ev.target.files[0];
if (file) {
try {
setIsUploading(true);
const upload = await voidCatUpload(file);
if (upload.url) {
setImg(upload.url);
onFileUpload(upload.url);
}
if (upload.error) {
console.error(upload.error);
}
} catch (error) {
console.error(error);
} finally {
setIsUploading(false);
}
}
}
function clearImage() {
setImg("");
onClear();
}
return (
<div className="file-uploader-container">
<label className="file-uploader">
<input type="file" onChange={onFileChange} />
{isUploading ? "Uploading..." : "Add File"}
</label>
<div className="file-uploader-preview">
{img?.length > 0 && (
<button className="btn btn-primary clear-button" onClick={clearImage}>
Clear
</button>
)}
{img && <img className="image-preview" src={img} />}
</div>
</div>
);
}