Changeset View
Changeset View
Standalone View
Standalone View
native/media/loadable-image.react.js
// @flow | // @flow | ||||
import { Image } from 'expo-image'; | import { Image } from 'expo-image'; | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { View, StyleSheet, ActivityIndicator } from 'react-native'; | import { View, StyleSheet, ActivityIndicator } from 'react-native'; | ||||
import type { ImageSource } from 'react-native/Libraries/Image/ImageSource'; | import type { ImageSource } from 'react-native/Libraries/Image/ImageSource'; | ||||
import type { ImageStyle } from '../types/styles.js'; | import type { ImageStyle } from '../types/styles.js'; | ||||
type Props = { | type Props = { | ||||
+placeholder: ?ImageSource, | |||||
+source: ?ImageSource, | +source: ?ImageSource, | ||||
+onLoad: () => void, | +onLoad: () => void, | ||||
+spinnerColor: string, | +spinnerColor: string, | ||||
+style: ImageStyle, | +style: ImageStyle, | ||||
+invisibleLoad: boolean, | +invisibleLoad: boolean, | ||||
}; | }; | ||||
function LoadableImage(props: Props): React.Node { | function LoadableImage(props: Props): React.Node { | ||||
const { source, onLoad: onLoadProp } = props; | const { source, placeholder, onLoad: onLoadProp } = props; | ||||
const [loaded, setLoaded] = React.useState(false); | const [loaded, setLoaded] = React.useState(false); | ||||
const onLoad = React.useCallback(() => { | const onLoad = React.useCallback(() => { | ||||
setLoaded(true); | setLoaded(true); | ||||
onLoadProp && onLoadProp(); | onLoadProp && onLoadProp(); | ||||
}, [onLoadProp]); | }, [onLoadProp]); | ||||
const invisibleStyle = React.useMemo( | const invisibleStyle = React.useMemo( | ||||
() => [props.style, styles.invisible], | () => [props.style, styles.invisible], | ||||
[props.style], | [props.style], | ||||
); | ); | ||||
if (!loaded && props.invisibleLoad) { | if (!loaded && props.invisibleLoad) { | ||||
return <Image source={source} onLoad={onLoad} style={invisibleStyle} />; | return ( | ||||
<Image | |||||
source={source} | |||||
placeholder={placeholder} | |||||
onLoad={onLoad} | |||||
style={invisibleStyle} | |||||
/> | |||||
); | |||||
} | } | ||||
let spinner; | let spinner; | ||||
if (!loaded) { | if (!loaded) { | ||||
spinner = ( | spinner = ( | ||||
<View style={styles.spinnerContainer}> | <View style={styles.spinnerContainer}> | ||||
<ActivityIndicator color={props.spinnerColor} size="large" /> | <ActivityIndicator color={props.spinnerColor} size="large" /> | ||||
</View> | </View> | ||||
); | ); | ||||
} | } | ||||
return ( | return ( | ||||
<View style={styles.container}> | <View style={styles.container}> | ||||
<Image | |||||
source={source} | |||||
placeholder={placeholder} | |||||
onLoad={onLoad} | |||||
style={props.style} | |||||
/> | |||||
{spinner} | {spinner} | ||||
<Image source={source} onLoad={onLoad} style={props.style} /> | |||||
</View> | </View> | ||||
); | ); | ||||
} | } | ||||
const styles = StyleSheet.create({ | const styles = StyleSheet.create({ | ||||
container: { | container: { | ||||
flex: 1, | flex: 1, | ||||
}, | }, | ||||
Show All 15 Lines |