// SEV-329: shared waitForImage (was byte-identical in public-site + vendor-site). // // SEV-306: uploads quarantine into a private incoming/ prefix and the // image-processor re-encodes them out to the public URL asynchronously (and // DELETES anything it can't decode). So the public URL 404s briefly after upload // and never appears for a rejected file. waitForImage polls (via Image() to // dodge CORS) until the sanitized object loads ('ready') or times out // ('rejected'). Callers gate display on this so users never see a broken . export function waitForImage(url, { timeoutMs = 30000, intervalMs = 1500 } = {}) { return new Promise((resolve) => { const start = Date.now(); const attempt = () => { const img = new Image(); img.onload = () => resolve('ready'); img.onerror = () => { if (Date.now() - start >= timeoutMs) resolve('rejected'); else setTimeout(attempt, intervalMs); }; img.src = url + (url.includes('?') ? '&' : '?') + '_cb=' + Date.now(); }; attempt(); }); }