Use prettier config file.

This commit is contained in:
Dylan Vann 2018-05-06 19:04:28 -04:00
parent 3e692b901d
commit b2fb48bbe3
21 changed files with 627 additions and 609 deletions

View File

@ -5,28 +5,28 @@ import FastImageGrid from './FastImageGrid'
import DefaultImageGrid from './DefaultImageGrid'
const App = TabNavigator(
{
fastImageExample: {
screen: FastImageExamples,
{
fastImageExample: {
screen: FastImageExamples,
},
image: {
screen: DefaultImageGrid,
},
fastImage: {
screen: FastImageGrid,
},
},
image: {
screen: DefaultImageGrid,
{
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
swipeEnabled: false,
animationEnabled: false,
tabBarOptions: {
style: {
backgroundColor: 'white',
},
},
},
fastImage: {
screen: FastImageGrid,
},
},
{
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
swipeEnabled: false,
animationEnabled: false,
tabBarOptions: {
style: {
backgroundColor: 'white',
},
},
},
)
export default App

View File

@ -9,52 +9,52 @@ import FeatureText from './FeatureText'
const IMAGE_URL = 'https://media.giphy.com/media/GEsoqZDGVoisw/giphy.gif'
const BorderRadiusExample = ({ onPressReload, bust }) => (
<View>
<Section>
<FeatureText text="• Border radius." />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage
style={styles.imageSquare}
source={{
uri: IMAGE_URL + bust,
}}
/>
<FastImage
style={styles.imageRectangular}
source={{
uri: IMAGE_URL + bust,
}}
/>
</SectionFlex>
</View>
<View>
<Section>
<FeatureText text="• Border radius." />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage
style={styles.imageSquare}
source={{
uri: IMAGE_URL + bust,
}}
/>
<FastImage
style={styles.imageRectangular}
source={{
uri: IMAGE_URL + bust,
}}
/>
</SectionFlex>
</View>
)
const styles = StyleSheet.create({
imageSquare: {
borderRadius: 50,
height: 100,
backgroundColor: '#ddd',
margin: 20,
width: 100,
flex: 0,
},
imageRectangular: {
borderRadius: 50,
borderTopLeftRadius: 10,
borderBottomRightRadius: 10,
height: 100,
backgroundColor: '#ddd',
margin: 20,
flex: 1,
},
plus: {
width: 30,
height: 30,
position: 'absolute',
bottom: 0,
right: 0,
},
imageSquare: {
borderRadius: 50,
height: 100,
backgroundColor: '#ddd',
margin: 20,
width: 100,
flex: 0,
},
imageRectangular: {
borderRadius: 50,
borderTopLeftRadius: 10,
borderBottomRightRadius: 10,
height: 100,
backgroundColor: '#ddd',
margin: 20,
flex: 1,
},
plus: {
width: 30,
height: 30,
position: 'absolute',
bottom: 0,
right: 0,
},
})
export default withCacheBust(BorderRadiusExample)

View File

@ -2,27 +2,27 @@ import React from 'react'
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'
const Button = ({ text, onPress }) => (
<TouchableOpacity onPress={onPress}>
<View style={styles.button}>
<Text style={styles.text}>{text}</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={onPress}>
<View style={styles.button}>
<Text style={styles.text}>{text}</Text>
</View>
</TouchableOpacity>
)
const styles = StyleSheet.create({
button: {
backgroundColor: 'black',
margin: 5,
height: 44,
paddingLeft: 10,
paddingRight: 10,
borderRadius: 10,
alignItems: 'center',
justifyContent: 'center',
},
text: {
color: 'white',
},
button: {
backgroundColor: 'black',
margin: 5,
height: 44,
paddingLeft: 10,
paddingRight: 10,
borderRadius: 10,
alignItems: 'center',
justifyContent: 'center',
},
text: {
color: 'white',
},
})
export default Button

View File

@ -7,10 +7,10 @@ import ImageGrid from './ImageGrid'
const DefaultImageGrid = () => <ImageGrid ImageComponent={Image} />
DefaultImageGrid.navigationOptions = {
tabBarLabel: 'Image Grid',
tabBarIcon: props => (
<Icon name="ios-image-outline" focusedName="ios-image" {...props} />
),
tabBarLabel: 'Image Grid',
tabBarIcon: props => (
<Icon name="ios-image-outline" focusedName="ios-image" {...props} />
),
}
export default DefaultImageGrid

View File

@ -11,71 +11,71 @@ import PreloadExample from './PreloadExample'
import StatusBarUnderlay, { STATUS_BAR_HEIGHT } from './StatusBarUnderlay'
const FastImageExample = () => (
<View style={styles.container}>
<StatusBar
translucent
barStyle="dark-content"
backgroundColor="transparent"
/>
<ScrollView
style={styles.scrollContainer}
contentContainerStyle={styles.scrollContentContainer}
>
<View style={styles.contentContainer}>
<Section>
<Text style={styles.titleText}>🚩 FastImage</Text>
<FeatureText text="Tap images to reload examples." />
</Section>
<PriorityExample />
<GifExample />
<BorderRadiusExample />
<ProgressExample />
<PreloadExample />
</View>
</ScrollView>
<StatusBarUnderlay />
</View>
<View style={styles.container}>
<StatusBar
translucent
barStyle="dark-content"
backgroundColor="transparent"
/>
<ScrollView
style={styles.scrollContainer}
contentContainerStyle={styles.scrollContentContainer}
>
<View style={styles.contentContainer}>
<Section>
<Text style={styles.titleText}>🚩 FastImage</Text>
<FeatureText text="Tap images to reload examples." />
</Section>
<PriorityExample />
<GifExample />
<BorderRadiusExample />
<ProgressExample />
<PreloadExample />
</View>
</ScrollView>
<StatusBarUnderlay />
</View>
)
FastImageExample.navigationOptions = {
tabBarLabel: 'FastImage Example',
tabBarIcon: props => (
<Icon
name="ios-information-circle-outline"
focusedName="ios-information-circle"
{...props}
/>
),
tabBarLabel: 'FastImage Example',
tabBarIcon: props => (
<Icon
name="ios-information-circle-outline"
focusedName="ios-information-circle"
{...props}
/>
),
}
const styles = StyleSheet.create({
titleText: {
fontWeight: '900',
marginBottom: 20,
color: '#222',
},
contentContainer: {
marginTop: 20,
marginBottom: 20,
},
image: {
flex: 1,
height: 100,
backgroundColor: '#ddd',
margin: 10,
},
container: {
flex: 1,
alignItems: 'stretch',
backgroundColor: '#fff',
},
scrollContainer: {
marginTop: STATUS_BAR_HEIGHT,
},
scrollContentContainer: {
alignItems: 'stretch',
flex: 0,
},
titleText: {
fontWeight: '900',
marginBottom: 20,
color: '#222',
},
contentContainer: {
marginTop: 20,
marginBottom: 20,
},
image: {
flex: 1,
height: 100,
backgroundColor: '#ddd',
margin: 10,
},
container: {
flex: 1,
alignItems: 'stretch',
backgroundColor: '#fff',
},
scrollContainer: {
marginTop: STATUS_BAR_HEIGHT,
},
scrollContentContainer: {
alignItems: 'stretch',
flex: 0,
},
})
export default FastImageExample

View File

@ -6,10 +6,10 @@ import ImageGrid from './ImageGrid'
const FastImageGrid = () => <ImageGrid ImageComponent={FastImage} />
FastImageGrid.navigationOptions = {
tabBarLabel: 'FastImage Grid',
tabBarIcon: props => (
<Icon name="ios-photos-outline" focusedName="ios-photos" {...props} />
),
tabBarLabel: 'FastImage Grid',
tabBarIcon: props => (
<Icon name="ios-photos-outline" focusedName="ios-photos" {...props} />
),
}
export default FastImageGrid

View File

@ -4,7 +4,7 @@ import { StyleSheet, Text } from 'react-native'
export default ({ text }) => <Text style={styles.style}>{text}</Text>
const styles = StyleSheet.create({
style: {
color: '#222',
},
style: {
color: '#222',
},
})

View File

@ -7,27 +7,27 @@ import Section from './Section'
import FeatureText from './FeatureText'
const GIF_URL =
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif'
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif'
const GifExample = ({ onPressReload, bust }) => (
<View>
<Section>
<FeatureText text="• GIF support." />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage style={styles.image} source={{ uri: GIF_URL + bust }} />
</SectionFlex>
</View>
<View>
<Section>
<FeatureText text="• GIF support." />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage style={styles.image} source={{ uri: GIF_URL + bust }} />
</SectionFlex>
</View>
)
const styles = StyleSheet.create({
image: {
backgroundColor: '#ddd',
margin: 10,
height: 100,
width: 100,
flex: 0,
},
image: {
backgroundColor: '#ddd',
margin: 10,
height: 100,
width: 100,
flex: 0,
},
})
export default withCacheBust(GifExample)

View File

@ -3,123 +3,123 @@ import { FlatList, StyleSheet, Text, View } from 'react-native'
import StatusBarUnderlay, { STATUS_BAR_HEIGHT } from './StatusBarUnderlay'
const getImageUrl = (id, width, height) =>
`https://unsplash.it/${width}/${height}?image=${id}`
`https://unsplash.it/${width}/${height}?image=${id}`
class ImageGrid extends Component {
constructor(props: Object) {
super(props)
constructor(props: Object) {
super(props)
fetch('https://unsplash.it/list')
.then(res => res.json())
.then(this._onFetchImagesSuccess)
.catch(this._onFetchImagesError)
}
state = {
images: [],
itemHeight: 0,
}
_onLayout = e => {
const width = e.nativeEvent.layout.width
this.setState({
itemHeight: width / 4,
})
}
_onFetchImagesError = () => {
this.setState({
error: true,
})
}
_onFetchImagesSuccess = images => {
this.setState({
images,
})
}
_getItemLayout = (data, index) => {
const { itemHeight } = this.state
return { length: itemHeight, offset: itemHeight * index, index }
}
_renderItem = ({ item }) => {
const ImageComponent = this.props.ImageComponent
const uri = getImageUrl(item.id, 100, 100)
return (
<View style={styles.imageContainer}>
<ImageComponent source={{ uri }} style={styles.image} />
</View>
)
}
_extractKey = item => {
return item.id
}
render() {
if (this.state.error) {
return (
<View style={styles.container}>
<Text style={styles.text}>Error fetching images.</Text>
</View>
)
fetch('https://unsplash.it/list')
.then(res => res.json())
.then(this._onFetchImagesSuccess)
.catch(this._onFetchImagesError)
}
state = {
images: [],
itemHeight: 0,
}
_onLayout = e => {
const width = e.nativeEvent.layout.width
this.setState({
itemHeight: width / 4,
})
}
_onFetchImagesError = () => {
this.setState({
error: true,
})
}
_onFetchImagesSuccess = images => {
this.setState({
images,
})
}
_getItemLayout = (data, index) => {
const { itemHeight } = this.state
return { length: itemHeight, offset: itemHeight * index, index }
}
_renderItem = ({ item }) => {
const ImageComponent = this.props.ImageComponent
const uri = getImageUrl(item.id, 100, 100)
return (
<View style={styles.imageContainer}>
<ImageComponent source={{ uri }} style={styles.image} />
</View>
)
}
_extractKey = item => {
return item.id
}
render() {
if (this.state.error) {
return (
<View style={styles.container}>
<Text style={styles.text}>Error fetching images.</Text>
</View>
)
}
return (
<View style={styles.container}>
<FlatList
onLayout={this._onLayout}
style={styles.list}
columnWrapperStyle={[
styles.columnWrapper,
{ height: this.state.itemHeight },
]}
data={this.state.images}
renderItem={this._renderItem}
numColumns={4}
keyExtractor={this._extractKey}
getItemLayout={this._getItemLayout}
/>
<StatusBarUnderlay />
</View>
)
}
return (
<View style={styles.container}>
<FlatList
onLayout={this._onLayout}
style={styles.list}
columnWrapperStyle={[
styles.columnWrapper,
{ height: this.state.itemHeight },
]}
data={this.state.images}
renderItem={this._renderItem}
numColumns={4}
keyExtractor={this._extractKey}
getItemLayout={this._getItemLayout}
/>
<StatusBarUnderlay />
</View>
)
}
}
const MARGIN = 2
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'stretch',
justifyContent: 'center',
},
text: {
textAlign: 'center',
},
list: {
marginTop: STATUS_BAR_HEIGHT,
flex: 1,
},
columnWrapper: {
flex: 1,
flexDirection: 'row',
marginLeft: -MARGIN,
marginRight: -MARGIN,
},
image: {
flex: 1,
width: null,
height: null,
margin: MARGIN,
backgroundColor: '#eee',
},
imageContainer: {
flex: 1,
alignItems: 'stretch',
},
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'stretch',
justifyContent: 'center',
},
text: {
textAlign: 'center',
},
list: {
marginTop: STATUS_BAR_HEIGHT,
flex: 1,
},
columnWrapper: {
flex: 1,
flexDirection: 'row',
marginLeft: -MARGIN,
marginRight: -MARGIN,
},
image: {
flex: 1,
width: null,
height: null,
margin: MARGIN,
backgroundColor: '#eee',
},
imageContainer: {
flex: 1,
alignItems: 'stretch',
},
})
export default ImageGrid

View File

@ -9,76 +9,84 @@ import Button from './Button'
import { createImageProgress } from 'react-native-image-progress'
const IMAGE_URL =
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif'
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif'
const Image = createImageProgress(FastImage)
class PreloadExample extends Component {
state = {
show: false,
url: IMAGE_URL,
}
state = {
show: false,
url: IMAGE_URL,
}
bustCache = () => {
const key = uuid()
const bust = `?bust=${key}`
// Preload images. This can be called anywhere.
const url = IMAGE_URL + bust
this.setState({
url,
show: false,
})
}
bustCache = () => {
const key = uuid()
const bust = `?bust=${key}`
// Preload images. This can be called anywhere.
const url = IMAGE_URL + bust
this.setState({
url,
show: false,
})
}
preload = () => {
FastImage.preload([{ uri: this.state.url }])
}
preload = () => {
FastImage.preload([{ uri: this.state.url }])
}
showImage = () => {
this.setState({ show: true })
}
showImage = () => {
this.setState({ show: true })
}
render() {
return (
<View>
<Section>
<FeatureText text="• Preloading." />
<FeatureText text="• Progress indication using react-native-image-progress." />
</Section>
<SectionFlex style={styles.section} onPress={this.props.onPressReload}>
{this.state.show ? (
<Image style={styles.image} source={{ uri: this.state.url }} />
) : (
<View style={styles.image} />
)}
<View style={{ flexDirection: 'row', marginHorizontal: 10 }}>
<View style={{ flex: 1 }}>
<Button text="Bust" onPress={this.bustCache} />
render() {
return (
<View>
<Section>
<FeatureText text="• Preloading." />
<FeatureText text="• Progress indication using react-native-image-progress." />
</Section>
<SectionFlex
style={styles.section}
onPress={this.props.onPressReload}
>
{this.state.show ? (
<Image
style={styles.image}
source={{ uri: this.state.url }}
/>
) : (
<View style={styles.image} />
)}
<View
style={{ flexDirection: 'row', marginHorizontal: 10 }}
>
<View style={{ flex: 1 }}>
<Button text="Bust" onPress={this.bustCache} />
</View>
<View style={{ flex: 1 }}>
<Button text="Preload" onPress={this.preload} />
</View>
<View style={{ flex: 1 }}>
<Button text="Render" onPress={this.showImage} />
</View>
</View>
</SectionFlex>
</View>
<View style={{ flex: 1 }}>
<Button text="Preload" onPress={this.preload} />
</View>
<View style={{ flex: 1 }}>
<Button text="Render" onPress={this.showImage} />
</View>
</View>
</SectionFlex>
</View>
)
}
)
}
}
const styles = StyleSheet.create({
section: {
flexDirection: 'column',
alignItems: 'center',
},
image: {
backgroundColor: '#ddd',
margin: 10,
height: 100,
width: 100,
},
section: {
flexDirection: 'column',
alignItems: 'center',
},
image: {
backgroundColor: '#ddd',
margin: 10,
height: 100,
width: 100,
},
})
export default PreloadExample

View File

@ -7,53 +7,53 @@ import SectionFlex from './SectionFlex'
import FeatureText from './FeatureText'
const getImageUrl = (id, width, height) =>
`https://source.unsplash.com/${id}/${width}x${height}`
`https://source.unsplash.com/${id}/${width}x${height}`
const IMAGE_SIZE = 1024
const IMAGE_SIZE_PX = PixelRatio.getPixelSizeForLayoutSize(IMAGE_SIZE)
const IMAGE_URLS = [
getImageUrl('x58soEovG_M', IMAGE_SIZE_PX, IMAGE_SIZE_PX),
getImageUrl('yPI7myL5eWY', IMAGE_SIZE_PX, IMAGE_SIZE_PX),
getImageUrl('S7VCcp6KCKE', IMAGE_SIZE, IMAGE_SIZE),
getImageUrl('x58soEovG_M', IMAGE_SIZE_PX, IMAGE_SIZE_PX),
getImageUrl('yPI7myL5eWY', IMAGE_SIZE_PX, IMAGE_SIZE_PX),
getImageUrl('S7VCcp6KCKE', IMAGE_SIZE, IMAGE_SIZE),
]
const PriorityExample = ({ onPressReload, bust }) => (
<View>
<Section>
<FeatureText text="• Prioritize images (low, normal, high)." />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage
style={styles.image}
source={{
uri: IMAGE_URLS[0] + bust,
priority: FastImage.priority.low,
}}
/>
<FastImage
style={styles.image}
source={{
uri: IMAGE_URLS[1] + bust,
priority: FastImage.priority.normal,
}}
/>
<FastImage
style={styles.image}
source={{
uri: IMAGE_URLS[2] + bust,
priority: FastImage.priority.high,
}}
/>
</SectionFlex>
</View>
<View>
<Section>
<FeatureText text="• Prioritize images (low, normal, high)." />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage
style={styles.image}
source={{
uri: IMAGE_URLS[0] + bust,
priority: FastImage.priority.low,
}}
/>
<FastImage
style={styles.image}
source={{
uri: IMAGE_URLS[1] + bust,
priority: FastImage.priority.normal,
}}
/>
<FastImage
style={styles.image}
source={{
uri: IMAGE_URLS[2] + bust,
priority: FastImage.priority.high,
}}
/>
</SectionFlex>
</View>
)
const styles = StyleSheet.create({
image: {
flex: 1,
height: 100,
backgroundColor: '#ddd',
margin: 10,
},
image: {
flex: 1,
height: 100,
backgroundColor: '#ddd',
margin: 10,
},
})
export default withCacheBust(PriorityExample)

View File

@ -9,71 +9,73 @@ import FeatureText from './FeatureText'
const IMAGE_URL = 'https://media.giphy.com/media/GEsoqZDGVoisw/giphy.gif'
class ProgressExample extends Component {
state = {
mount: new Date(),
start: undefined,
progress: undefined,
end: undefined,
}
state = {
mount: new Date(),
start: undefined,
progress: undefined,
end: undefined,
}
render() {
const { onPressReload, bust } = this.props
const { mount, start, progress, end } = this.state
return (
<View>
<Section>
<FeatureText text="• Progress callbacks." />
</Section>
<SectionFlex
onPress={onPressReload}
style={{
flexDirection: 'column',
alignItems: 'center',
paddingBottom: 20,
}}
>
<FastImage
style={styles.image}
source={{
uri: IMAGE_URL + bust,
}}
onLoadStart={() => this.setState({ start: Date.now() })}
onProgress={e =>
this.setState({
progress: Math.round(
100 * (e.nativeEvent.loaded / e.nativeEvent.total),
),
})
}
onLoad={() => this.setState({ end: Date.now() })}
onLoadEnd={() => {}}
/>
<Text>
onLoadStart
{start !== undefined && ` - ${start - mount} ms`}
</Text>
<Text>
onProgress
{progress !== undefined && ` - ${progress} %`}
</Text>
<Text>
onLoad
{end !== undefined && ` - ${end - mount} ms`}
</Text>
</SectionFlex>
</View>
)
}
render() {
const { onPressReload, bust } = this.props
const { mount, start, progress, end } = this.state
return (
<View>
<Section>
<FeatureText text="• Progress callbacks." />
</Section>
<SectionFlex
onPress={onPressReload}
style={{
flexDirection: 'column',
alignItems: 'center',
paddingBottom: 20,
}}
>
<FastImage
style={styles.image}
source={{
uri: IMAGE_URL + bust,
}}
onLoadStart={() => this.setState({ start: Date.now() })}
onProgress={e =>
this.setState({
progress: Math.round(
100 *
(e.nativeEvent.loaded /
e.nativeEvent.total),
),
})
}
onLoad={() => this.setState({ end: Date.now() })}
onLoadEnd={() => {}}
/>
<Text>
onLoadStart
{start !== undefined && ` - ${start - mount} ms`}
</Text>
<Text>
onProgress
{progress !== undefined && ` - ${progress} %`}
</Text>
<Text>
onLoad
{end !== undefined && ` - ${end - mount} ms`}
</Text>
</SectionFlex>
</View>
)
}
}
const styles = StyleSheet.create({
image: {
height: 100,
backgroundColor: '#ddd',
margin: 20,
width: 100,
flex: 0,
},
image: {
height: 100,
backgroundColor: '#ddd',
margin: 20,
width: 100,
flex: 0,
},
})
export default withCacheBust(ProgressExample)

View File

@ -4,10 +4,10 @@ import { StyleSheet, View } from 'react-native'
export default ({ children }) => <View style={styles.section}>{children}</View>
const styles = StyleSheet.create({
section: {
marginTop: 10,
marginBottom: 10,
marginLeft: 40,
marginRight: 40,
},
section: {
marginTop: 10,
marginBottom: 10,
marginLeft: 40,
marginRight: 40,
},
})

View File

@ -2,19 +2,19 @@ import React from 'react'
import { StyleSheet, TouchableOpacity } from 'react-native'
export default ({ children, onPress, style }) => (
<TouchableOpacity style={[styles.sectionFlex, style]} onPress={onPress}>
{children}
</TouchableOpacity>
<TouchableOpacity style={[styles.sectionFlex, style]} onPress={onPress}>
{children}
</TouchableOpacity>
)
const styles = StyleSheet.create({
sectionFlex: {
backgroundColor: '#eee',
flexDirection: 'row',
justifyContent: 'center',
marginTop: 10,
marginBottom: 10,
marginLeft: -10,
marginRight: -10,
},
sectionFlex: {
backgroundColor: '#eee',
flexDirection: 'row',
justifyContent: 'center',
marginTop: 10,
marginBottom: 10,
marginLeft: -10,
marginRight: -10,
},
})

View File

@ -7,12 +7,12 @@ export const STATUS_BAR_HEIGHT = getStatusBarHeight()
export default () => <View style={styles.statusBarUnderlay} />
const styles = StyleSheet.create({
statusBarUnderlay: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: STATUS_BAR_HEIGHT,
backgroundColor: 'white',
},
statusBarUnderlay: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: STATUS_BAR_HEIGHT,
backgroundColor: 'white',
},
})

View File

@ -2,27 +2,27 @@ import React, { Component } from 'react'
import uuid from 'uuid/v4'
export default BaseComponent => {
class WithCacheBust extends Component {
state = { bust: '?bust' }
class WithCacheBust extends Component {
state = { bust: '?bust' }
onPressReload = () => {
// Force complete re-render and bust image cache.
const key = uuid()
const bust = `?bust=${key}`
this.setState({ bust })
onPressReload = () => {
// Force complete re-render and bust image cache.
const key = uuid()
const bust = `?bust=${key}`
this.setState({ bust })
}
render() {
return (
<BaseComponent
bust={this.state.bust}
onPressReload={this.onPressReload}
/>
)
}
}
render() {
return (
<BaseComponent
bust={this.state.bust}
onPressReload={this.onPressReload}
/>
)
}
}
WithCacheBust.displayName = `withCacheBust${BaseComponent.displayName}`
WithCacheBust.displayName = `withCacheBust${BaseComponent.displayName}`
return WithCacheBust
return WithCacheBust
}

204
index.js
View File

@ -1,13 +1,13 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {
Platform,
View,
Image,
NativeModules,
requireNativeComponent,
ViewPropTypes,
StyleSheet,
Platform,
View,
Image,
NativeModules,
requireNativeComponent,
ViewPropTypes,
StyleSheet,
} from 'react-native'
const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSource')
@ -15,130 +15,132 @@ const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSou
const FastImageViewNativeModule = NativeModules.FastImageView
const useLocalImage = source => {
// No source.
if (!source) return true
// No uri.
if (!source.uri) return true
// Is a local Android image.
if (source.uri.startsWith('file://')) return true
// Content URI.
if (source.uri.startsWith('content://')) return true
// Smart album.
if (source.uri.startsWith('photos://')) return true
// From asset library / camera roll.
if (source.uri.startsWith('assets-library://')) return true
// We have a remote source.
return false
// No source.
if (!source) return true
// No uri.
if (!source.uri) return true
// Is a local Android image.
if (source.uri.startsWith('file://')) return true
// Content URI.
if (source.uri.startsWith('content://')) return true
// Smart album.
if (source.uri.startsWith('photos://')) return true
// From asset library / camera roll.
if (source.uri.startsWith('assets-library://')) return true
// We have a remote source.
return false
}
class FastImage extends Component {
setNativeProps(nativeProps) {
this._root.setNativeProps(nativeProps)
}
captureRef = e => (this._root = e)
render() {
const {
source,
onLoadStart,
onProgress,
onLoad,
onError,
onLoadEnd,
style,
children,
...props
} = this.props
// If there's no source or source uri just fallback to Image.
if (useLocalImage(source)) {
return (
<Image
ref={this.captureRef}
{...props}
style={style}
source={source}
onLoadStart={onLoadStart}
onProgress={onProgress}
onLoad={onLoad}
onError={onError}
onLoadEnd={onLoadEnd}
/>
)
setNativeProps(nativeProps) {
this._root.setNativeProps(nativeProps)
}
const resolvedSource = resolveAssetSource(source)
captureRef = e => (this._root = e)
return (
<View style={[style, styles.imageContainer]} ref={this.captureRef}>
<FastImageView
{...props}
style={StyleSheet.absoluteFill}
source={resolvedSource}
onFastImageLoadStart={onLoadStart}
onFastImageProgress={onProgress}
onFastImageLoad={onLoad}
onFastImageError={onError}
onFastImageLoadEnd={onLoadEnd}
/>
{children && <View style={StyleSheet.absoluteFill}>{children}</View>}
</View>
)
}
render() {
const {
source,
onLoadStart,
onProgress,
onLoad,
onError,
onLoadEnd,
style,
children,
...props
} = this.props
// If there's no source or source uri just fallback to Image.
if (useLocalImage(source)) {
return (
<Image
ref={this.captureRef}
{...props}
style={style}
source={source}
onLoadStart={onLoadStart}
onProgress={onProgress}
onLoad={onLoad}
onError={onError}
onLoadEnd={onLoadEnd}
/>
)
}
const resolvedSource = resolveAssetSource(source)
return (
<View style={[style, styles.imageContainer]} ref={this.captureRef}>
<FastImageView
{...props}
style={StyleSheet.absoluteFill}
source={resolvedSource}
onFastImageLoadStart={onLoadStart}
onFastImageProgress={onProgress}
onFastImageLoad={onLoad}
onFastImageError={onError}
onFastImageLoadEnd={onLoadEnd}
/>
{children && (
<View style={StyleSheet.absoluteFill}>{children}</View>
)}
</View>
)
}
}
const styles = StyleSheet.create({
imageContainer: {
overflow: 'hidden',
},
imageContainer: {
overflow: 'hidden',
},
})
FastImage.resizeMode = {
contain: 'contain',
cover: 'cover',
stretch: 'stretch',
center: 'center',
contain: 'contain',
cover: 'cover',
stretch: 'stretch',
center: 'center',
}
FastImage.priority = {
low: 'low',
normal: 'normal',
high: 'high',
low: 'low',
normal: 'normal',
high: 'high',
}
FastImage.preload = sources => {
FastImageViewNativeModule.preload(sources)
FastImageViewNativeModule.preload(sources)
}
FastImage.defaultProps = {
resizeMode: FastImage.resizeMode.cover,
resizeMode: FastImage.resizeMode.cover,
}
const FastImageSourcePropType = PropTypes.shape({
uri: PropTypes.string,
headers: PropTypes.objectOf(PropTypes.string),
priority: PropTypes.oneOf(Object.keys(FastImage.priority)),
uri: PropTypes.string,
headers: PropTypes.objectOf(PropTypes.string),
priority: PropTypes.oneOf(Object.keys(FastImage.priority)),
})
FastImage.propTypes = {
...ViewPropTypes,
source: PropTypes.oneOfType([FastImageSourcePropType, PropTypes.number]),
onLoadStart: PropTypes.func,
onProgress: PropTypes.func,
onLoad: PropTypes.func,
onError: PropTypes.func,
onLoadEnd: PropTypes.func,
...ViewPropTypes,
source: PropTypes.oneOfType([FastImageSourcePropType, PropTypes.number]),
onLoadStart: PropTypes.func,
onProgress: PropTypes.func,
onLoad: PropTypes.func,
onError: PropTypes.func,
onLoadEnd: PropTypes.func,
}
const FastImageView = requireNativeComponent('FastImageView', FastImage, {
nativeOnly: {
onFastImageLoadStart: true,
onFastImageProgress: true,
onFastImageLoad: true,
onFastImageError: true,
onFastImageLoadEnd: true,
},
nativeOnly: {
onFastImageLoadStart: true,
onFastImageProgress: true,
onFastImageLoad: true,
onFastImageError: true,
onFastImageLoadEnd: true,
},
})
export default FastImage

View File

@ -6,33 +6,33 @@ import FastImage from './index.js'
const style = StyleSheet.create({ image: { width: 44, height: 44 } })
test('FastImage renders correctly.', () => {
const tree = renderer
.create(
<FastImage
source={{
uri: 'https://facebook.github.io/react/img/logo_og.png',
headers: {
token: 'someToken',
},
priority: FastImage.priority.high,
}}
style={style.image}
/>,
)
.toJSON()
const tree = renderer
.create(
<FastImage
source={{
uri: 'https://facebook.github.io/react/img/logo_og.png',
headers: {
token: 'someToken',
},
priority: FastImage.priority.high,
}}
style={style.image}
/>,
)
.toJSON()
expect(tree).toMatchSnapshot()
expect(tree).toMatchSnapshot()
})
test('Renders a normal Image when not passed a uri.', () => {
const tree = renderer
.create(
<FastImage
source={require('./react-native-fast-image-example-server/pictures/jellyfish.gif')}
style={style.image}
/>,
)
.toJSON()
const tree = renderer
.create(
<FastImage
source={require('./react-native-fast-image-example-server/pictures/jellyfish.gif')}
style={style.image}
/>,
)
.toJSON()
expect(tree).toMatchSnapshot()
expect(tree).toMatchSnapshot()
})

View File

@ -33,11 +33,11 @@
"url": "git+https://github.com/DylanVann/react-native-fast-image.git"
},
"scripts": {
"format": "prettier --write --no-semi --single-quote --trailing-comma all ./index.js ./ReactNativeFastImageExample/FastImage/*.js ./react-native-fast-image-server/*.js",
"format": "prettier --write ./*.js ./ReactNativeFastImageExample/FastImage/*.js ./react-native-fast-image-server/*.js",
"prepare": "git submodule update --init --recursive",
"test": "yarn run test:pretty && yarn run test:jest",
"test": "yarn run test:format && yarn run test:jest",
"test:jest": "jest *.js",
"test:pretty": "prettier-check --write --no-semi --single-quote --trailing-comma all ./index.js ./ReactNativeFastImageExample/FastImage/*.js ./react-native-fast-image-server/*.js"
"test:format": "prettier-check ./*.js ./ReactNativeFastImageExample/FastImage/*.js ./react-native-fast-image-server/*.js"
},
"dependencies": {
"prop-types": "^15.5.10"
@ -46,7 +46,7 @@
"babel-jest": "^21.2.0",
"babel-preset-react-native": "^4.0.0",
"jest": "^21.2.1",
"prettier": "^1.5.2",
"prettier": "^1.12.1",
"prettier-check": "^2.0.0",
"react": "^16.3.0-alpha.1",
"react-native": "^0.54.1",

6
prettier.config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
semi: false,
singleQuote: true,
trailingComma: 'all',
tabWidth: 4,
}

View File

@ -3642,9 +3642,9 @@ prettier-check@^2.0.0:
dependencies:
execa "^0.6.0"
prettier@^1.5.2:
version "1.8.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.8.2.tgz#bff83e7fd573933c607875e5ba3abbdffb96aeb8"
prettier@^1.12.1:
version "1.12.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325"
pretty-format@^21.2.1:
version "21.2.1"