"use client"; import { useEffect, useState, type CSSProperties, type MouseEventHandler } from "react"; import { buildImageProxyUrl, getFullscreenPreviewSize } from "@/lib/image-delivery"; export type LoadedImagePreview = { src: string; width: number; height: number }; /** Keep the already displayed image visible while its larger preview loads. */ export function ProgressiveImagePreview({ src, preview, alt, className, style, onClick, }: { src: string; preview: LoadedImagePreview; alt: string; className?: string; style?: CSSProperties; onClick?: MouseEventHandler; }) { const size = getFullscreenPreviewSize({ imageWidth: preview.width, imageHeight: preview.height, viewportWidth: typeof window === "undefined" ? 1280 : window.innerWidth, viewportHeight: typeof window === "undefined" ? 900 : window.innerHeight, pixelRatio: typeof window === "undefined" ? 1 : window.devicePixelRatio, }); const fullSrc = buildImageProxyUrl(src, { delivery: "proxy", width: size.requestWidth, quality: 86, format: "webp", }); const [loadedSrc, setLoadedSrc] = useState(""); const [failedSrc, setFailedSrc] = useState(""); const ready = fullSrc === preview.src || loadedSrc === fullSrc; const failed = failedSrc === fullSrc; useEffect(() => { if (fullSrc === preview.src) return; const image = new Image(); image.decoding = "async"; image.onload = () => setLoadedSrc(fullSrc); image.onerror = () => setFailedSrc(fullSrc); image.src = fullSrc; return () => { image.onload = null; image.onerror = null; image.removeAttribute("src"); }; }, [fullSrc, preview.src]); return (
event.stopPropagation()}> {alt} {!ready && (
{failed ? "高清预览加载失败,已保留当前预览;可关闭后重试或下载原图" : "正在加载高清预览…"}
)}
); }