1import type { FilePreviewItem, FilePreviewSource } from "../components/ui/FilePreviewModal.types";
2
3export function filePreviewKey(source: FilePreviewItem): string {
4 if ("resource" in source)
5 return JSON.stringify([
6 source.environmentId,
7 Object.entries(source.resource)
8 .filter(([key]) => key !== "mimeType" && key !== "fileName")
9 .sort(([a], [b]) => a.localeCompare(b)),
10 ]);
11 if ("attachment" in source) return `attachment:${source.attachment.id}`;
12 return source.uri;
13}
14
15export function filePreviewGallery(source: FilePreviewSource, group: readonly FilePreviewItem[]) {
16 if (source.kind !== "image") return [source];
17 const selectedKey = filePreviewKey(source);
18 const seen = new Set<string>();
19 const items: FilePreviewItem[] = [];
20 for (const item of source.gallery ?? group) {
21 if (item.kind !== "image") continue;
22 const key = filePreviewKey(item);
23 if (seen.has(key)) continue;
24 seen.add(key);
25 items.push(key === selectedKey ? source : item);
26 }
27 if (!seen.has(selectedKey)) items.unshift(source);
28 return items;
29}
30
31export function filePreviewName(source: FilePreviewItem): string {
32 const uriName = "uri" in source ? source.uri.split(/[?#]/)[0]?.split("/").pop() : undefined;
33 const name =
34 source.name ?? ("attachment" in source ? source.attachment.name : uriName) ?? "Preview";
35 const extension = /\.(png|jpe?g|gif|webp|heic|heif|avif|svg|pdf|docx?|xlsx?|pptx?|txt|rtf)$/i;
36 const filename =
37 source.kind !== "image" || extension.test(name)
38 ? name
39 : uriName && extension.test(uriName)
40 ? uriName
41 : name.replace(/\./g, "_");
42 return Array.from(filename, (character) =>
43 character.charCodeAt(0) < 32 || "/:\\".includes(character) ? "_" : character,
44 ).join("");
45}