Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 8x 8x 8x 8x 8x 8x 8x 8x 30x 3x 2x 1x 16x 16x 16x 21x 21x 5x 5x 16x 2x 2x 14x 16x | export const MAX_UPLOAD_BYTES = 4_500_000;
const MAX_UPLOAD_LABEL = "4.5 MB";
export const MAX_UPLOAD_ERROR = `Image must be ${MAX_UPLOAD_LABEL} or smaller`;
/** Pool bulk-upload limits — the durable client-upload path (separate from the
* 4.5MB serverless single-photo cap above). Mirrors the token endpoint. */
export const POOL_ALLOWED_CONTENT_TYPES = [
"image/jpeg",
"image/png",
"image/gif",
"image/webp",
] as const;
export const POOL_MAX_BYTES = 50_000_000;
const POOL_MAX_LABEL = "50 MB";
const HEIF_EXTENSIONS = /\.(heic|heif)$/i;
const HEIF_MIME_TYPES = new Set(["image/heic", "image/heif"]);
export function isHeifFile(file: Pick<File, "name" | "type">): boolean {
return HEIF_MIME_TYPES.has(file.type.toLowerCase()) || HEIF_EXTENSIONS.test(file.name);
}
export function buildJpegFileName(name: string): string {
if (name.includes(".")) {
return name.replace(/\.[^.]+$/, ".jpg");
}
return `${name}.jpg`;
}
export interface SkippedFile {
name: string;
reason: string;
}
export interface PoolFilePartition {
accepted: File[];
skipped: SkippedFile[];
}
/** Pre-flight: split selected files into those the pool endpoint will accept
* vs. those to skip up front (with a gentle reason), so we never upload bytes
* that the token endpoint would reject. HEIC/HEIF is accepted — it is converted
* to JPEG before upload. */
export function partitionPoolFiles(files: File[]): PoolFilePartition {
const accepted: File[] = [];
const skipped: SkippedFile[] = [];
for (const file of files) {
const typeOk =
isHeifFile(file) ||
(POOL_ALLOWED_CONTENT_TYPES as readonly string[]).includes(file.type);
if (!typeOk) {
skipped.push({ name: file.name, reason: "This kind of photo isn't supported yet" });
continue;
}
if (file.size > POOL_MAX_BYTES) {
skipped.push({ name: file.name, reason: `This photo is over ${POOL_MAX_LABEL}` });
continue;
}
accepted.push(file);
}
return { accepted, skipped };
}
|