tooot/src/components/GracefullyImage.tsx

103 lines
2.9 KiB
TypeScript
Raw Normal View History

2022-02-12 18:25:53 +01:00
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { connectMedia } from '@utils/api/helpers/connect'
2021-02-14 00:27:21 +01:00
import { useTheme } from '@utils/styles/ThemeManager'
2023-02-08 01:10:59 +01:00
import { Image, ImageSource, ImageStyle } from 'expo-image'
import React, { useState } from 'react'
import { AccessibilityProps, Pressable, StyleProp, View, ViewStyle } from 'react-native'
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
2023-02-08 01:10:59 +01:00
sources: {
preview?: ImageSource
default?: ImageSource
remote?: ImageSource
static?: ImageSource
blurhash?: string
}
2021-01-16 00:00:31 +01:00
dimension?: { width: number; height: number }
onPress?: () => void
style?: StyleProp<ViewStyle>
2023-02-08 01:10:59 +01:00
imageStyle?: 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
2023-02-08 01:10:59 +01:00
enableLiveTextInteraction?: boolean
2021-01-16 00:00:31 +01:00
}
2022-04-30 21:29:08 +02:00
const GracefullyImage = ({
accessibilityLabel,
accessibilityHint,
hidden = false,
2023-02-08 01:10:59 +01:00
sources,
2022-04-30 21:29:08 +02:00
dimension,
onPress,
style,
imageStyle,
2023-01-29 17:28:49 +01:00
setImageDimensions,
2023-02-08 01:10:59 +01:00
dim,
enableLiveTextInteraction = false
2022-04-30 21:29:08 +02:00
}: Props) => {
const { reduceMotionEnabled } = useAccessibility()
2023-02-08 01:10:59 +01:00
const { theme } = useTheme()
2021-01-16 00:00:31 +01:00
2023-02-08 01:10:59 +01:00
const [currentSource, setCurrentSource] = useState<ImageSource | undefined>(
sources.default || sources.remote
)
const source: ImageSource | undefined =
reduceMotionEnabled && sources.static ? sources.static : currentSource
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}
2023-02-01 00:06:33 +01:00
style={[style, dimension]}
2022-09-14 21:52:16 +02:00
{...(onPress ? (hidden ? { disabled: true } : { onPress }) : { disabled: true })}
2022-04-30 21:29:08 +02:00
>
2023-02-08 01:10:59 +01:00
<Image
2023-02-08 21:41:16 +01:00
placeholderContentFit='cover'
2023-02-08 01:10:59 +01:00
placeholder={sources.blurhash || connectMedia(sources.preview)}
source={hidden ? undefined : connectMedia(source)}
2023-02-08 21:41:16 +01:00
transition={{ duration: 80 }}
2023-02-08 01:10:59 +01:00
style={{ flex: 1, ...imageStyle }}
onLoad={event => {
if (setImageDimensions && event.source) {
setImageDimensions(event.source)
2023-01-09 22:28:53 +01:00
}
}}
onError={() => {
2023-02-08 01:10:59 +01:00
if (
sources.default?.uri &&
sources.default?.uri === currentSource?.uri &&
sources.remote
) {
setCurrentSource(sources.remote)
2023-01-09 22:28:53 +01:00
}
}}
2023-02-08 01:10:59 +01:00
enableLiveTextInteraction={enableLiveTextInteraction}
2022-12-15 22:14:59 +01:00
/>
2023-01-29 17:28:49 +01:00
{dim && theme !== 'light' ? (
<View
2023-02-08 01:10:59 +01:00
style={{
width: '100%',
height: '100%',
position: 'absolute',
backgroundColor: 'black',
opacity: theme === 'dark_lighter' ? 0.18 : 0.36
}}
2023-01-29 17:28:49 +01:00
/>
) : null}
2022-04-30 21:29:08 +02:00
</Pressable>
)
}
2021-01-16 00:00:31 +01:00
export default GracefullyImage