@@ -8,6 +8,7 @@ import { tracker } from "@follow/tracker"
8
8
import { cn , formatEstimatedMins , formatTimeToSeconds } from "@follow/utils"
9
9
import { useVideoPlayer , VideoView } from "expo-video"
10
10
import { memo , useCallback , useMemo , useRef , useState } from "react"
11
+ import type { ImageErrorEventData } from "react-native"
11
12
import { StyleSheet , Text , View } from "react-native"
12
13
13
14
import { useActionLanguage } from "@/src/atoms/settings/general"
@@ -223,19 +224,25 @@ const ThumbnailImage = ({
223
224
} )
224
225
} , [ audio , entry ?. title , feed ?. title , image , isLoading , isPlaying , video , videoPlayer ] )
225
226
227
+ const [ imageError , setImageError ] = useState ( audio && ! image )
228
+ const handleImageError = useCallback ( ( ) => {
229
+ setImageError ( true )
230
+ } , [ ] )
231
+
226
232
if ( ! image && ! audio && ! video ) return null
227
233
const isSquare = thumbnailRatio === "square"
228
234
return (
229
235
< View className = { cn ( "relative ml-4 h-24 overflow-hidden rounded-lg" , isSquare ? "h-24" : "" ) } >
230
236
{ image &&
231
237
( thumbnailRatio === "square" ? (
232
- < SquareImage image = { image } blurhash = { blurhash } />
238
+ < SquareImage image = { image } blurhash = { blurhash } onError = { handleImageError } />
233
239
) : (
234
240
< AspectRatioImage
235
241
blurhash = { blurhash }
236
242
image = { image }
237
243
height = { mediaModel ?. height }
238
244
width = { mediaModel ?. width }
245
+ onError = { handleImageError }
239
246
/>
240
247
) ) }
241
248
@@ -260,7 +267,7 @@ const ThumbnailImage = ({
260
267
) }
261
268
262
269
{ /* Show feed icon if no image but audio is present */ }
263
- { audio && ! image && < FeedIcon feed = { feed } size = { 96 } /> }
270
+ { imageError && < FeedIcon feed = { feed } size = { 96 } /> }
264
271
265
272
{ ( video || audio ) && (
266
273
< NativePressable
@@ -292,16 +299,16 @@ const AspectRatioImage = ({
292
299
blurhash,
293
300
height = 96 ,
294
301
width = 96 ,
302
+ onError,
295
303
} : {
296
304
image : string
297
305
blurhash ?: string
298
306
height ?: number
299
307
width ?: number
308
+ onError ?: ( event : ImageErrorEventData ) => void
300
309
} ) => {
301
- const [ isLoading , setIsLoading ] = useState ( true )
302
-
303
310
if ( height === width || ! height || ! width ) {
304
- return < SquareImage image = { image } blurhash = { blurhash } />
311
+ return < SquareImage image = { image } blurhash = { blurhash } onError = { onError } />
305
312
}
306
313
// Calculate aspect ratio and determine dimensions
307
314
// Ensure the larger dimension is capped at 96px while maintaining aspect ratio
@@ -320,22 +327,7 @@ const AspectRatioImage = ({
320
327
}
321
328
322
329
return (
323
- < View
324
- style = { {
325
- width : scaledWidth ,
326
- height : scaledHeight ,
327
- } }
328
- className = "ml-auto overflow-hidden rounded-lg"
329
- >
330
- { isLoading && (
331
- < View
332
- style = { {
333
- width : scaledWidth ,
334
- height : scaledHeight ,
335
- } }
336
- className = "bg-system-fill absolute animate-pulse rounded-lg"
337
- />
338
- ) }
330
+ < View className = "ml-auto flex h-full justify-center overflow-hidden rounded-lg" >
339
331
< Image
340
332
proxy = { {
341
333
width : 96 ,
@@ -351,31 +343,38 @@ const AspectRatioImage = ({
351
343
blurhash = { blurhash }
352
344
contentFit = "cover"
353
345
hideOnError
354
- onLoad = { ( ) => setIsLoading ( false ) }
346
+ onError = { onError }
355
347
/>
356
348
</ View >
357
349
)
358
350
}
359
351
360
- const SquareImage = ( { image, blurhash } : { image : string ; blurhash ?: string } ) => {
361
- const [ isLoading , setIsLoading ] = useState ( true )
352
+ const SquareImage = ( {
353
+ image,
354
+ blurhash,
355
+ onError,
356
+ } : {
357
+ image : string
358
+ blurhash ?: string
359
+ onError ?: ( event : ImageErrorEventData ) => void
360
+ } ) => {
362
361
return (
363
362
< View className = "size-24 overflow-hidden rounded-lg" >
364
- { isLoading && < View className = "bg-system-fill absolute inset-0 animate-pulse rounded-lg" /> }
365
363
< Image
366
364
proxy = { {
367
365
width : 96 ,
368
366
height : 96 ,
369
367
} }
368
+ style = { {
369
+ width : 96 ,
370
+ height : 96 ,
371
+ } }
370
372
transition = { 100 }
371
373
source = { {
372
374
uri : image ,
373
375
} }
374
376
blurhash = { blurhash }
375
- className = "size-24 overflow-hidden rounded-lg"
376
- contentFit = "cover"
377
- hideOnError
378
- onLoad = { ( ) => setIsLoading ( false ) }
377
+ onError = { onError }
379
378
/>
380
379
</ View >
381
380
)
0 commit comments