Refine image fallback behavior

This commit is contained in:
Sam Becker 2025-04-05 00:31:19 -05:00
parent a07978309b
commit 11b9716482

View File

@ -5,7 +5,7 @@ import { BLUR_ENABLED } from '@/app/config';
import { useAppState } from '@/state/AppState';
import { clsx} from 'clsx/lite';
import Image, { ImageProps } from 'next/image';
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
export default function ImageWithFallback(props: ImageProps & {
blurCompatibilityLevel?: 'none' | 'low' | 'high'
@ -22,7 +22,7 @@ export default function ImageWithFallback(props: ImageProps & {
const { shouldDebugImageFallbacks } = useAppState();
const [wasCached, setWasCached] = useState(false);
const [wasCached, setWasCached] = useState(true);
const [isLoading, setIsLoading] = useState(true);
const [didError, setDidError] = useState(false);
@ -31,6 +31,16 @@ export default function ImageWithFallback(props: ImageProps & {
const [hideFallback, setHideFallback] = useState(false);
const imgRef = useRef<HTMLImageElement>(null);
useEffect(() => {
const timeout = setTimeout(
() => setWasCached(imgRef.current?.complete ?? false),
100,
);
return () => clearTimeout(timeout);
}, []);
useEffect(() => {
if (!isLoading && !didError) {
const timeout = setTimeout(() => {
@ -61,11 +71,11 @@ export default function ImageWithFallback(props: ImageProps & {
className,
)}
>
{(showFallback || shouldDebugImageFallbacks) &&
<div className={clsx(
'@container',
'absolute inset-0',
'overflow-hidden',
(showFallback || shouldDebugImageFallbacks) &&
'transition-opacity duration-300 ease-in',
!(BLUR_ENABLED && blurDataURL) && 'bg-main',
(isLoading || shouldDebugImageFallbacks)
@ -85,10 +95,10 @@ export default function ImageWithFallback(props: ImageProps & {
'w-full h-full',
'bg-gray-100/50 dark:bg-gray-900/50',
)} />}
</div>}
</div>
<Image {...{
...rest,
ref: (element) => setWasCached(element?.complete ?? false),
ref: imgRef,
priority,
className: classNameImage,
onLoad,