Skip to content

Commit

Permalink
feat: handle image loading failure
Browse files Browse the repository at this point in the history
Display a fallback image icon in case we fail to load
the image for some reason (should be bad news for the upload)
  • Loading branch information
acezard committed Nov 23, 2023
1 parent 433bbfb commit 5b9a34e
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 19 deletions.
9 changes: 9 additions & 0 deletions src/ui/Icons/Illus/FileTypeImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react'
import { CommonPathProps, SvgXml } from 'react-native-svg'

export const FileTypeImage = (props?: CommonPathProps): JSX.Element => (
<SvgXml
{...props}
xml='&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"&gt;&lt;g fill="none" fill-rule="evenodd" transform="translate(0 3)"&gt;&lt;rect width="32" height="26" fill="#8EE39B" rx="2"/&gt;&lt;path fill="#1EC737" d="M0 20l6.29-6.29a.999.999 0 0 1 1.416-.004L11 17l8.294-8.294a1.003 1.003 0 0 1 1.412 0L32 20v4.002C32 25.106 31.11 26 29.998 26H2.002A2.002 2.002 0 0 1 0 24.002V20z"/&gt;&lt;circle cx="8" cy="7" r="3" fill="#FFF"/&gt;&lt;path stroke="#8EE39B" d="M11 16l-5.5 5.5L11 16z" stroke-linecap="round" stroke-linejoin="round"/&gt;&lt;/g&gt;&lt;/svg&gt;'
/>
)
48 changes: 29 additions & 19 deletions src/ui/ImageThumbnail/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, { useState } from 'react'
import { Image, ImageStyle, View } from 'react-native'

import {
Expand All @@ -9,6 +9,7 @@ import {
import { Icon } from '/ui/Icon'
import { createImageStyles, createViewStyles } from '/ui/ImageThumbnail/styles'
import { ImageThumbnailProps } from '/ui/ImageThumbnail/types'
import { FileTypeImage } from '/ui/Icons/Illus/FileTypeImage'

/**
* Displays a thumbnail for a file.
Expand All @@ -20,21 +21,30 @@ export const FileThumbnail = ({
filePath = '',
mimeType = '',
size = 128,
style
}: ImageThumbnailProps): JSX.Element => (
<View style={[createViewStyles(size).view, style]}>
{isImageType(mimeType) ? (
<Image
source={{ uri: getImageUri(filePath) }}
// Casting to ImageStyle is necessary here to resolve a TypeScript type mismatch.
// The style object returned by StyleSheet.create includes a union of ViewStyle, TextStyle, and ImageStyle.
// However, the Image component's style prop specifically expects an ImageStyle.
// This cast ensures that TypeScript recognizes the style as ImageStyle, aligning with the expected type for the Image component.
style={createImageStyles(size).image as ImageStyle}
resizeMode="cover" // Will fill the frame and crop excess parts
/>
) : (
<Icon icon={getIconForMimeType(mimeType)} size={size} />
)}
</View>
)
style = {}
}: ImageThumbnailProps): JSX.Element => {
const [loadError, setLoadError] = useState(false)

return (
<View style={[createViewStyles(size).view, style]}>
{isImageType(mimeType) ? (
loadError ? (
<Icon icon={FileTypeImage} size={size} />
) : (
<Image
source={{ uri: getImageUri(filePath) }}
// Casting to ImageStyle is necessary here to resolve a TypeScript type mismatch.
// The style object returned by StyleSheet.create includes a union of ViewStyle, TextStyle, and ImageStyle.
// However, the Image component's style prop specifically expects an ImageStyle.
// This cast ensures that TypeScript recognizes the style as ImageStyle, aligning with the expected type for the Image component.
style={createImageStyles(size).image as ImageStyle}
resizeMode="cover" // Will fill the frame and crop excess parts
onError={(): void => setLoadError(true)}
/>
)
) : (
<Icon icon={getIconForMimeType(mimeType)} size={size} />
)}
</View>
)
}

0 comments on commit 5b9a34e

Please sign in to comment.