@@ -148,7 +148,7 @@ export const PreviewMediaContent: FC<{
148148 ) : (
149149 < FallbackableImage
150150 fallbackUrl = { media [ 0 ] . fallbackUrl }
151- className = "size-full object-contain"
151+ className = "h-auto w-fit object-contain"
152152 alt = "cover"
153153 src = { src }
154154 onContextMenu = { ( e ) => handleContextMenu ( src , e ) }
@@ -270,44 +270,55 @@ const FallbackableImage: FC<
270270 const [ currentSrc , setCurrentSrc ] = useState ( ( ) => replaceImgUrlIfNeed ( src ) )
271271 const [ isAllError , setIsAllError ] = useState ( false )
272272
273+ const [ isLoading , setIsLoading ] = useState ( true )
274+
273275 const [ currentState , setCurrentState ] = useState <
274276 "proxy" | "origin" | "fallback"
275277 > ( ( ) => ( currentSrc === src ? "origin" : "proxy" ) )
276278
277- const handleError = useCallback (
278- ( ) => {
279- switch ( currentState ) {
280- case "proxy" : {
281- if ( currentSrc !== src ) {
282- setCurrentSrc ( src )
283- setCurrentState ( "origin" )
284- } else {
285- if ( fallbackUrl ) {
286- setCurrentSrc ( fallbackUrl )
287- setCurrentState ( "fallback" )
288- }
289- }
290-
291- break
292- }
293- case "origin" : {
279+ const handleError = useCallback ( ( ) => {
280+ switch ( currentState ) {
281+ case "proxy" : {
282+ if ( currentSrc !== src ) {
283+ setCurrentSrc ( src )
284+ setCurrentState ( "origin" )
285+ } else {
294286 if ( fallbackUrl ) {
295287 setCurrentSrc ( fallbackUrl )
296288 setCurrentState ( "fallback" )
297289 }
298- break
299290 }
300- case "fallback" : {
301- setIsAllError ( true )
291+
292+ break
293+ }
294+ case "origin" : {
295+ if ( fallbackUrl ) {
296+ setCurrentSrc ( fallbackUrl )
297+ setCurrentState ( "fallback" )
302298 }
299+ break
303300 }
304- } ,
305- [ currentSrc , currentState , fallbackUrl , src ] ,
306- )
301+ case "fallback" : {
302+ setIsAllError ( true )
303+ }
304+ }
305+ } , [ currentSrc , currentState , fallbackUrl , src ] )
307306
308307 return (
309- < Fragment >
310- { ! isAllError && < img src = { currentSrc } onError = { handleError } { ...props } /> }
308+ < div className = "flex flex-col" >
309+ { isLoading && ! isAllError && (
310+ < div className = "center absolute size-full" >
311+ < i className = "i-mgc-loading-3-cute-re size-8 animate-spin text-white/80" />
312+ </ div >
313+ ) }
314+ { ! isAllError && (
315+ < img
316+ src = { currentSrc }
317+ onLoad = { ( ) => setIsLoading ( false ) }
318+ onError = { handleError }
319+ { ...props }
320+ />
321+ ) }
311322 { isAllError && (
312323 < div
313324 className = "center flex-col gap-6 text-white/80"
@@ -327,7 +338,7 @@ const FallbackableImage: FC<
327338 >
328339 Retry
329340 </ MotionButtonBase >
330- Or
341+ or
331342 < a
332343 className = "underline underline-offset-4"
333344 href = { src }
@@ -339,6 +350,25 @@ const FallbackableImage: FC<
339350 </ div >
340351 </ div >
341352 ) }
342- </ Fragment >
353+
354+ { currentState === "fallback" && (
355+ < div className = "mt-4 text-xs" >
356+ < span >
357+ This image is preview in low quality, because the original image is
358+ not available.
359+ </ span >
360+ < br />
361+ < span >
362+ You can
363+ { " " }
364+ < a href = { src } target = "_blank" rel = "noreferrer" className = "underline duration-200 hover:text-accent" >
365+ visit the original image
366+ </ a >
367+ { " " }
368+ if you want to see the full quality.
369+ </ span >
370+ </ div >
371+ ) }
372+ </ div >
343373 )
344374}
0 commit comments