2022-02-12 18:25:53 +01:00
|
|
|
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
|
2023-01-29 15:32:40 +01:00
|
|
|
import { connectImage } from '@utils/api/helpers/connect'
|
2021-02-14 00:27:21 +01:00
|
|
|
import { useTheme } from '@utils/styles/ThemeManager'
|
2023-01-10 14:56:13 +01:00
|
|
|
import React, { useEffect, useState } from 'react'
|
2021-03-18 23:54:40 +01:00
|
|
|
import {
|
2021-04-09 21:43:12 +02:00
|
|
|
AccessibilityProps,
|
2021-03-18 23:54:40 +01:00
|
|
|
Image,
|
|
|
|
Pressable,
|
|
|
|
StyleProp,
|
|
|
|
StyleSheet,
|
2021-04-01 18:39:53 +02:00
|
|
|
View,
|
2021-03-18 23:54:40 +01:00
|
|
|
ViewStyle
|
|
|
|
} from 'react-native'
|
2021-01-28 01:31:19 +01:00
|
|
|
import { Blurhash } from 'react-native-blurhash'
|
2022-12-28 23:41:36 +01:00
|
|
|
import FastImage, { ImageStyle } from 'react-native-fast-image'
|
2021-02-14 00:27:21 +01:00
|
|
|
|
|
|
|
// blurhas -> if blurhash, show before any loading succeed
|
|
|
|
// original -> load original
|
|
|
|
// original, remote -> if original failed, then remote
|
|
|
|
// preview, original -> first show preview, then original
|
|
|
|
// preview, original, remote -> first show preview, then original, if original failed, then remote
|
2021-01-16 00:00:31 +01:00
|
|
|
|
|
|
|
export interface Props {
|
2021-04-09 21:43:12 +02:00
|
|
|
accessibilityLabel?: AccessibilityProps['accessibilityLabel']
|
|
|
|
accessibilityHint?: AccessibilityProps['accessibilityHint']
|
|
|
|
|
2021-01-16 00:00:31 +01:00
|
|
|
hidden?: boolean
|
2022-02-12 18:25:53 +01:00
|
|
|
uri: { preview?: string; original?: string; remote?: string; static?: string }
|
2021-01-16 00:00:31 +01:00
|
|
|
blurhash?: string
|
|
|
|
dimension?: { width: number; height: number }
|
|
|
|
onPress?: () => void
|
|
|
|
style?: StyleProp<ViewStyle>
|
2021-01-23 02:41:50 +01:00
|
|
|
imageStyle?: StyleProp<ImageStyle>
|
2021-02-14 00:27:21 +01:00
|
|
|
// For image viewer when there is no image size available
|
|
|
|
setImageDimensions?: React.Dispatch<
|
|
|
|
React.SetStateAction<{
|
|
|
|
width: number
|
|
|
|
height: number
|
|
|
|
}>
|
|
|
|
>
|
2023-01-29 17:28:49 +01:00
|
|
|
dim?: boolean
|
2021-01-16 00:00:31 +01:00
|
|
|
}
|
|
|
|
|
2022-04-30 21:29:08 +02:00
|
|
|
const GracefullyImage = ({
|
|
|
|
accessibilityLabel,
|
|
|
|
accessibilityHint,
|
|
|
|
hidden = false,
|
|
|
|
uri,
|
|
|
|
blurhash,
|
|
|
|
dimension,
|
|
|
|
onPress,
|
|
|
|
style,
|
|
|
|
imageStyle,
|
2023-01-29 17:28:49 +01:00
|
|
|
setImageDimensions,
|
|
|
|
dim
|
2022-04-30 21:29:08 +02:00
|
|
|
}: Props) => {
|
|
|
|
const { reduceMotionEnabled } = useAccessibility()
|
2023-01-29 17:28:49 +01:00
|
|
|
const { colors, theme } = useTheme()
|
2022-04-30 21:29:08 +02:00
|
|
|
const [imageLoaded, setImageLoaded] = useState(false)
|
2021-01-16 00:00:31 +01:00
|
|
|
|
2023-01-09 22:28:53 +01:00
|
|
|
const [currentUri, setCurrentUri] = useState<string | undefined>(uri.original || uri.remote)
|
2023-01-29 15:32:40 +01:00
|
|
|
const source: { uri?: string } = {
|
2023-01-09 22:28:53 +01:00
|
|
|
uri: reduceMotionEnabled && uri.static ? uri.static : currentUri
|
2022-04-30 21:29:08 +02:00
|
|
|
}
|
2023-01-10 14:56:13 +01:00
|
|
|
useEffect(() => {
|
2023-01-10 19:36:42 +01:00
|
|
|
if (
|
|
|
|
(uri.original ? currentUri !== uri.original : true) &&
|
|
|
|
(uri.remote ? currentUri !== uri.remote : true)
|
|
|
|
) {
|
2023-01-10 14:56:13 +01:00
|
|
|
setCurrentUri(uri.original || uri.remote)
|
|
|
|
}
|
|
|
|
}, [currentUri, uri.original, uri.remote])
|
2021-02-02 22:50:38 +01:00
|
|
|
|
2022-12-29 00:36:35 +01:00
|
|
|
const blurhashView = () => {
|
2022-04-30 21:29:08 +02:00
|
|
|
if (hidden || !imageLoaded) {
|
|
|
|
if (blurhash) {
|
2022-09-14 21:52:16 +02:00
|
|
|
return <Blurhash decodeAsync blurhash={blurhash} style={styles.placeholder} />
|
2022-04-30 21:29:08 +02:00
|
|
|
} else {
|
2022-09-14 21:52:16 +02:00
|
|
|
return <View style={[styles.placeholder, { backgroundColor: colors.shimmerDefault }]} />
|
2022-04-30 21:29:08 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return null
|
|
|
|
}
|
2022-12-29 00:36:35 +01:00
|
|
|
}
|
2022-04-30 21:29:08 +02:00
|
|
|
|
|
|
|
return (
|
|
|
|
<Pressable
|
2022-09-14 21:52:16 +02:00
|
|
|
{...(onPress ? { accessibilityRole: 'imagebutton' } : { accessibilityRole: 'image' })}
|
2022-04-30 21:29:08 +02:00
|
|
|
accessibilityLabel={accessibilityLabel}
|
|
|
|
accessibilityHint={accessibilityHint}
|
|
|
|
style={[style, dimension, { backgroundColor: colors.shimmerDefault }]}
|
2022-09-14 21:52:16 +02:00
|
|
|
{...(onPress ? (hidden ? { disabled: true } : { onPress }) : { disabled: true })}
|
2022-04-30 21:29:08 +02:00
|
|
|
>
|
|
|
|
{uri.preview && !imageLoaded ? (
|
2022-12-15 22:14:59 +01:00
|
|
|
<FastImage
|
2023-01-29 15:32:40 +01:00
|
|
|
source={connectImage({ uri: uri.preview })}
|
2022-09-14 21:52:16 +02:00
|
|
|
style={[styles.placeholder, { backgroundColor: colors.shimmerDefault }]}
|
2021-02-14 00:27:21 +01:00
|
|
|
/>
|
2022-04-30 21:29:08 +02:00
|
|
|
) : null}
|
2022-12-15 22:14:59 +01:00
|
|
|
<FastImage
|
2023-01-29 15:32:40 +01:00
|
|
|
source={connectImage(source)}
|
2022-12-15 22:14:59 +01:00
|
|
|
style={[{ flex: 1 }, imageStyle]}
|
2023-01-09 22:28:53 +01:00
|
|
|
onLoad={() => {
|
|
|
|
setImageLoaded(true)
|
|
|
|
if (setImageDimensions && source.uri) {
|
|
|
|
Image.getSize(source.uri, (width, height) => setImageDimensions({ width, height }))
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
onError={() => {
|
|
|
|
if (uri.original && uri.original === currentUri && uri.remote) {
|
|
|
|
setCurrentUri(uri.remote)
|
|
|
|
}
|
|
|
|
}}
|
2022-12-15 22:14:59 +01:00
|
|
|
/>
|
2022-12-29 00:36:35 +01:00
|
|
|
{blurhashView()}
|
2023-01-29 17:28:49 +01:00
|
|
|
{dim && theme !== 'light' ? (
|
|
|
|
<View
|
|
|
|
style={[
|
|
|
|
styles.placeholder,
|
|
|
|
{ backgroundColor: 'black', opacity: theme === 'dark_lighter' ? 0.18 : 0.36 }
|
|
|
|
]}
|
|
|
|
/>
|
|
|
|
) : null}
|
2022-04-30 21:29:08 +02:00
|
|
|
</Pressable>
|
|
|
|
)
|
|
|
|
}
|
2021-01-16 00:00:31 +01:00
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
2021-04-19 17:15:52 +02:00
|
|
|
placeholder: {
|
2021-02-14 00:27:21 +01:00
|
|
|
width: '100%',
|
|
|
|
height: '100%',
|
2021-03-27 00:17:34 +01:00
|
|
|
position: 'absolute'
|
2021-01-16 00:00:31 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
export default GracefullyImage
|