"use client" import { useEffect, useState } from "react" import { useAuthStore } from "@/lib/api/auth-store" function attachmentInlineUrl(attachmentId: string): string { const base = process.env.NEXT_PUBLIC_API_URL ?? "/api/v1" const normalizedBase = base.endsWith("/") ? base.slice(0, -1) : base return `${normalizedBase}/mail/attachments/${encodeURIComponent(attachmentId)}/inline` } function normalizeCidKey(raw: string): string { const trimmed = raw.trim() if (trimmed.toLowerCase().startsWith("cid:")) { return trimmed.slice(4).trim() } return trimmed } /** Fetches inline attachment blobs and exposes blob: URLs keyed by cid (with or without cid: prefix). */ export function useInlineCidUrls(cidMap: Record | undefined) { const accessToken = useAuthStore((s) => s.accessToken) const [urls, setUrls] = useState>({}) useEffect(() => { if (!accessToken || !cidMap || Object.keys(cidMap).length === 0) { setUrls({}) return } let cancelled = false const objectUrls: string[] = [] void (async () => { const next: Record = {} for (const [contentId, attachmentId] of Object.entries(cidMap)) { if (!attachmentId) continue try { const res = await fetch(attachmentInlineUrl(attachmentId), { headers: { Authorization: `Bearer ${accessToken}` }, }) if (!res.ok) continue const blob = await res.blob() const blobUrl = URL.createObjectURL(blob) objectUrls.push(blobUrl) const key = normalizeCidKey(contentId) next[key] = blobUrl next[`cid:${key}`] = blobUrl } catch { // skip broken inline parts } } if (!cancelled) { setUrls(next) } else { for (const u of objectUrls) URL.revokeObjectURL(u) } })() return () => { cancelled = true for (const u of objectUrls) URL.revokeObjectURL(u) } }, [accessToken, cidMap]) return urls }