CR: check for supported image types, duplicate filenames
This commit is contained in:
@@ -215,29 +215,43 @@ export function Thread() {
|
|||||||
setPdfUrlList([]);
|
setPdfUrlList([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SUPPORTED_IMAGE_TYPES = ["image/jpeg", "image/png", "image/gif", "image/webp"];
|
||||||
|
const SUPPORTED_FILE_TYPES = [...SUPPORTED_IMAGE_TYPES, "application/pdf"];
|
||||||
|
|
||||||
|
const isDuplicate = (file: File, images: Base64ContentBlock[], pdfs: Base64ContentBlock[]) => {
|
||||||
|
if (SUPPORTED_IMAGE_TYPES.includes(file.type)) {
|
||||||
|
return images.some(img => img.metadata?.name === file.name && img.mime_type === file.type);
|
||||||
|
}
|
||||||
|
if (file.type === "application/pdf") {
|
||||||
|
return pdfs.some(pdf => pdf.metadata?.filename === file.name);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
const handleFileUpload = async (e: ChangeEvent<HTMLInputElement>) => {
|
const handleFileUpload = async (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
const files = e.target.files;
|
const files = e.target.files;
|
||||||
if (!files) return;
|
if (!files) return;
|
||||||
const fileArray = Array.from(files);
|
const fileArray = Array.from(files);
|
||||||
const imageFiles = fileArray.filter((file) =>
|
const validFiles = fileArray.filter((file) => SUPPORTED_FILE_TYPES.includes(file.type));
|
||||||
file.type.startsWith("image"),
|
const invalidFiles = fileArray.filter((file) => !SUPPORTED_FILE_TYPES.includes(file.type));
|
||||||
);
|
const duplicateFiles = validFiles.filter((file) => isDuplicate(file, imageUrlList, pdfUrlList));
|
||||||
const pdfFiles = fileArray.filter(
|
const uniqueFiles = validFiles.filter((file) => !isDuplicate(file, imageUrlList, pdfUrlList));
|
||||||
(file) => file.type === "application/pdf",
|
|
||||||
);
|
|
||||||
const invalidFiles = fileArray.filter(
|
|
||||||
(file) =>
|
|
||||||
!file.type.startsWith("image/") && file.type !== "application/pdf",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (invalidFiles.length > 0) {
|
if (invalidFiles.length > 0) {
|
||||||
toast.error(
|
toast.error(
|
||||||
"You have uploaded invalid file type. Please upload an image or a PDF.",
|
"You have uploaded invalid file type. Please upload a JPEG, PNG, GIF, WEBP image or a PDF.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (duplicateFiles.length > 0) {
|
||||||
|
toast.error(
|
||||||
|
`Duplicate file(s) detected: ${duplicateFiles.map(f => f.name).join(", ")}. Each file can only be uploaded once per message.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imageFiles.length) {
|
const imageFiles = uniqueFiles.filter((file) => SUPPORTED_IMAGE_TYPES.includes(file.type));
|
||||||
|
const pdfFiles = uniqueFiles.filter((file) => file.type === "application/pdf");
|
||||||
|
|
||||||
|
if (imageFiles.length) {
|
||||||
const imageBlocks = await Promise.all(imageFiles.map(fileToImageBlock));
|
const imageBlocks = await Promise.all(imageFiles.map(fileToImageBlock));
|
||||||
setImageUrlList((prev) => [...prev, ...imageBlocks]);
|
setImageUrlList((prev) => [...prev, ...imageBlocks]);
|
||||||
}
|
}
|
||||||
@@ -281,18 +295,24 @@ export function Thread() {
|
|||||||
if (!e.dataTransfer) return;
|
if (!e.dataTransfer) return;
|
||||||
|
|
||||||
const files = Array.from(e.dataTransfer.files);
|
const files = Array.from(e.dataTransfer.files);
|
||||||
const imageFiles = files.filter((file) => file.type.startsWith("image/"));
|
const validFiles = files.filter((file) => SUPPORTED_FILE_TYPES.includes(file.type));
|
||||||
const pdfFiles = files.filter((file) => file.type === "application/pdf");
|
const invalidFiles = files.filter((file) => !SUPPORTED_FILE_TYPES.includes(file.type));
|
||||||
const invalidFiles = files.filter(
|
const duplicateFiles = validFiles.filter((file) => isDuplicate(file, imageUrlList, pdfUrlList));
|
||||||
(file) =>
|
const uniqueFiles = validFiles.filter((file) => !isDuplicate(file, imageUrlList, pdfUrlList));
|
||||||
!file.type.startsWith("image/") && file.type !== "application/pdf",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (invalidFiles.length > 0) {
|
if (invalidFiles.length > 0) {
|
||||||
toast.error(
|
toast.error(
|
||||||
"You have uploaded invalid file type. Please upload an image or a PDF.",
|
"You have uploaded invalid file type. Please upload a JPEG, PNG, GIF, WEBP image or a PDF.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (duplicateFiles.length > 0) {
|
||||||
|
toast.error(
|
||||||
|
`Duplicate file(s) detected: ${duplicateFiles.map(f => f.name).join(", ")}. Each file can only be uploaded once per message.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageFiles = uniqueFiles.filter((file) => SUPPORTED_IMAGE_TYPES.includes(file.type));
|
||||||
|
const pdfFiles = uniqueFiles.filter((file) => file.type === "application/pdf");
|
||||||
|
|
||||||
if (imageFiles.length) {
|
if (imageFiles.length) {
|
||||||
const imageBlocks: Base64ContentBlock[] = await Promise.all(
|
const imageBlocks: Base64ContentBlock[] = await Promise.all(
|
||||||
@@ -586,7 +606,7 @@ export function Thread() {
|
|||||||
type="file"
|
type="file"
|
||||||
onChange={handleFileUpload}
|
onChange={handleFileUpload}
|
||||||
multiple
|
multiple
|
||||||
accept="image/*,application/pdf"
|
accept="image/jpeg,image/png,image/gif,image/webp,application/pdf"
|
||||||
className="hidden"
|
className="hidden"
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
|
|||||||
Reference in New Issue
Block a user