import { useEffect, useRef, useState } from "react"; import type { Task } from "../types"; export function ReplyCover({ task, image = task.replyImage!, loadImage, onOpen }: { task: Task; image?: { url: string; alt: string }; loadImage?: (task: Task, url?: string) => Promise; onOpen: () => void }) { const root = useRef(null); const [src, setSrc] = useState(null); const [failed, setFailed] = useState(false); useEffect(() => { let cancelled = false; let started = false; setSrc(null); setFailed(false); // Remote images remain click-only Markdown links, never automatic requests. if (/^https:\/\//i.test(image.url)) { setFailed(true); return; } const load = async () => { if (started) return; started = true; try { const url = await loadImage?.(task, image.url); if (!cancelled) { setSrc(url || null); setFailed(!url); } } catch { if (!cancelled) setFailed(true); } }; const observer = typeof IntersectionObserver === "undefined" ? null : new IntersectionObserver((entries) => { if (entries.some((entry) => entry.isIntersecting)) { observer?.disconnect(); void load(); } }, { rootMargin: "200px" }); if (observer && root.current) observer.observe(root.current); else void load(); return () => { cancelled = true; observer?.disconnect(); }; }, [image.url, task.turnId, loadImage]); if (failed) return null; return ; }