Merge branch 'master' into glide-v4

This commit is contained in:
Kingsley Ochu 2018-02-08 11:56:30 +01:00 committed by GitHub
commit 9c631af041
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 698 additions and 213 deletions

View File

@ -1,10 +1,12 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {
View,
Image,
NativeModules,
requireNativeComponent,
ViewPropTypes,
StyleSheet,
} from 'react-native'
const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSource')
@ -24,6 +26,9 @@ class FastImage extends Component {
onLoad,
onError,
onLoadEnd,
style,
children,
borderRadius,
...props
} = this.props
@ -33,6 +38,7 @@ class FastImage extends Component {
<Image
ref={e => (this._root = e)}
{...props}
style={style}
source={source}
onLoadStart={onLoadStart}
onProgress={onProgress}
@ -44,21 +50,53 @@ class FastImage extends Component {
}
const resolvedSource = resolveAssetSource(source)
if (children) {
throw new Error(
'The <FastImage> component cannot contain children. If you want to render content on top of the image consider using absolute positioning.',
)
}
if (!borderRadius) {
return (
<FastImageView
ref={e => (this._root = e)}
{...props}
style={style}
source={resolvedSource}
onFastImageLoadStart={onLoadStart}
onFastImageProgress={onProgress}
onFastImageLoad={onLoad}
onFastImageError={onError}
onFastImageLoadEnd={onLoadEnd}
/>
)
}
return (
<FastImageView
ref={e => (this._root = e)}
{...props}
source={resolvedSource}
onFastImageLoadStart={onLoadStart}
onFastImageProgress={onProgress}
onFastImageLoad={onLoad}
onFastImageError={onError}
onFastImageLoadEnd={onLoadEnd}
/>
<View style={[style, styles.imageContainer]} borderRadius={borderRadius}>
<FastImageView
ref={e => (this._root = e)}
{...props}
style={StyleSheet.absoluteFill}
source={resolvedSource}
onFastImageLoadStart={onLoadStart}
onFastImageProgress={onProgress}
onFastImageLoad={onLoad}
onFastImageError={onError}
onFastImageLoadEnd={onLoadEnd}
/>
</View>
)
}
}
const styles = StyleSheet.create({
imageContainer: {
overflow: 'hidden',
},
})
FastImage.resizeMode = {
contain: 'contain',
cover: 'cover',

View File

@ -1,8 +1,10 @@
import 'react-native'
import { StyleSheet } from 'react-native'
import React from 'react'
import renderer from 'react-test-renderer'
import FastImage from './FastImage.js'
const style = StyleSheet.create({ image: { width: 44, height: 44 } })
test('FastImage renders correctly.', () => {
const tree = renderer
.create(
@ -14,6 +16,20 @@ test('FastImage renders correctly.', () => {
},
priority: FastImage.priority.high,
}}
style={style.image}
/>,
)
.toJSON()
expect(tree).toMatchSnapshot()
})
test('Renders a normal Image when not passed a uri.', () => {
const tree = renderer
.create(
<FastImage
source={require('./server/pictures/jellyfish.gif')}
style={style.image}
/>,
)
.toJSON()

View File

@ -38,6 +38,7 @@ and
- [x] Prioritize images.
- [x] Preload images.
- [x] GIF support.
- [x] Border radius property.
## Usage
@ -92,8 +93,8 @@ Headers to load the image with. e.g. `{ Authorization: 'someAuthToken' }`.
### `resizeMode?: enum`
- `FastImage.resizeMode.contain` **(Default)** - Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or less than the corresponding dimension of the view (minus padding).
- `FastImage.resizeMode.cover` - Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding).
- `FastImage.resizeMode.contain` - Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or less than the corresponding dimension of the view (minus padding).
- `FastImage.resizeMode.cover` **(Default)** - Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding).
- `FastImage.resizeMode.stretch` - Scale width and height independently, This may change the aspect ratio of the src.
- `FastImage.resizeMode.center` - Do not scale the image, keep centered.
@ -131,12 +132,10 @@ Called when the image finishes loading, whether it was successful or an error.
---
### `children`
### `borderRadius: number`
`FastImage` does not currently support children.
Absolute positioning can be used as an alternative.
This is because `FastImage` supplies a `android.widget.imageview` and not a `android.view.viewgroup`.
A border radius for the image.
Can be used to make a circular cropped version of the image.
## Static Methods

View File

@ -17,5 +17,33 @@ exports[`FastImage renders correctly. 1`] = `
"uri": "https://facebook.github.io/react/img/logo_og.png",
}
}
style={
Object {
"height": 44,
"width": 44,
}
}
/>
`;
exports[`Renders a normal Image when not passed a uri. 1`] = `
<Image
onError={undefined}
onLoad={undefined}
onLoadEnd={undefined}
onLoadStart={undefined}
onProgress={undefined}
resizeMode="cover"
source={
Object {
"testUri": "../../../server/pictures/jellyfish.gif",
}
}
style={
Object {
"height": 44,
"width": 44,
}
}
/>
`;

View File

@ -64,7 +64,7 @@ class FastImageViewConverter {
}};
public static ScaleType scaleType(String resizeMode) {
if (resizeMode == null) resizeMode = "contain";
if (resizeMode == null) resizeMode = "cover";
final ImageView.ScaleType scaleType = REACT_RESIZE_MODE_MAP.get(resizeMode);
return scaleType;
}

View File

@ -9,6 +9,7 @@ import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Priority;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.request.RequestOptions;
import com.facebook.react.bridge.ReadableMap;
@ -100,10 +101,12 @@ class FastImageViewManager extends SimpleViewManager<ImageViewWithUrl> implement
RequestOptions options = new RequestOptions()
.priority(priority)
.dontTransform()
.placeholder(TRANSPARENT_DRAWABLE);
requestManager
.load(glideUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.apply(options)
.listener(new FastImageRequestListener(key))
.into(view);

View File

@ -0,0 +1,28 @@
# How is caching handled?
In the readme it says "Aggressively cache images.". What does this mean?
This library treats image urls as immutable.
That means it assumes the data located at a given url will not change.
This is ideal for performance.
The way this would work in practice for something like a user profile picture is:
- Request user from API.
- Receive JSON representing the user containing a `profilePicture` property that is the url of the profile picture.
- Display the profile picture.
So what happens if the user wants to change their profile picture?
- User uploads a new profile picture, it gets a new url on the backend.
- Update a field in a database.
Next time the app is opened:
- Display the cached profile picture immediately.
- Request the user json again (this time it will have the new profile picture url).
- Display the new profile picture.
## How is the cache cleared?
As the app is used the cache fills up. When the cache reaches its maximum size the least frequently used images will be purged from the cache. You generally do not need to manually manage the cache.

View File

@ -1,13 +1,13 @@
import React from 'react'
import { TabNavigator, TabBarBottom } from 'react-navigation'
import FastImageExample from './fastImage/FastImageExample'
import FastImageExamples from './fastImage/FastImageExamples'
import FastImageGrid from './fastImage/FastImageGrid'
import DefaultImageGrid from './fastImage/DefaultImageGrid'
const App = TabNavigator(
{
fastImageExample: {
screen: FastImageExample,
screen: FastImageExamples,
},
image: {
screen: DefaultImageGrid,

View File

@ -0,0 +1,58 @@
import React from 'react'
import { StyleSheet, View } from 'react-native'
import withCacheBust from './withCacheBust'
import SectionFlex from './SectionFlex'
import FastImage from 'react-native-fast-image'
import Section from './Section'
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}
borderRadius={50}
source={{
uri: IMAGE_URL + bust,
}}
/>
<FastImage
style={styles.imageRectangular}
borderRadius={50}
source={{
uri: IMAGE_URL + bust,
}}
/>
</SectionFlex>
</View>
)
const styles = StyleSheet.create({
imageSquare: {
height: 100,
backgroundColor: '#ddd',
margin: 20,
width: 100,
flex: 0,
},
imageRectangular: {
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

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

View File

@ -1,168 +0,0 @@
import React, { Component } from 'react'
import {
Button,
PixelRatio,
ScrollView,
StatusBar,
StyleSheet,
Text,
View,
} from 'react-native'
import Icon from 'react-native-vector-icons/Ionicons'
import FastImage from 'react-native-fast-image'
import uuid from 'uuid/v4'
const getImageUrl = (id, width, height) =>
`https://source.unsplash.com/${id}/${width}x${height}`
const IMAGE_SIZE = 150
const IMAGE_SIZE_PX = PixelRatio.getPixelSizeForLayoutSize(IMAGE_SIZE)
// The server is used to test that sending headers is working correctly.
const USE_SERVER = false
const TOKEN = 'someToken'
const getImages = () => {
if (USE_SERVER) {
const baseUrl = '192.168.2.11'
return [
`http://${baseUrl}:8080/pictures/ahmed-saffu-235616.jpg`,
`http://${baseUrl}:8080/pictures/alex-bertha-236361.jpg`,
`http://${baseUrl}:8080/pictures/jaromir-kavan-233699.jpg`,
]
}
return [
getImageUrl('x58soEovG_M', IMAGE_SIZE_PX, IMAGE_SIZE_PX),
getImageUrl('yPI7myL5eWY', IMAGE_SIZE_PX, IMAGE_SIZE_PX),
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif',
]
}
const getTestProgressCallbacks = label => ({
onLoadStart: () => console.log(`${label} - onLoadStart`),
onProgress: e =>
console.log(
`${label} - onProgress - ${e.nativeEvent.loaded / e.nativeEvent.total}`,
),
onLoad: () => console.log(`${label} - onLoad`),
onError: () => console.log(`${label} - onError`),
onLoadEnd: () => console.log(`${label} - onLoadEnd`),
})
const images = getImages()
// Preload images. This can be called anywhere.
FastImage.preload([
{
uri: 'https://facebook.github.io/react/img/logo_og.png',
headers: { Authorization: 'someAuthToken' },
},
{
uri: 'https://facebook.github.io/react/img/logo_og.png',
headers: { Authorization: 'someAuthToken' },
},
])
class FastImageExample extends Component {
state = { bust: '?bust' }
onPressedReload = () => {
// Force complete re-render and bust image cache.
const key = uuid()
const bust = `?bust=${key}`
this.setState({ bust })
}
render() {
return (
<View style={styles.container} key={this.state.bust}>
<StatusBar
translucent
barStyle="dark-content"
backgroundColor="transparent"
/>
<ScrollView
style={styles.scrollContainer}
contentContainerStyle={styles.scrollContentContainer}
>
<View style={styles.textContainer}>
<Text style={styles.bold}>FastImage</Text>
<Text> priority (low, normal, high)</Text>
<Text> authentication (token)</Text>
<Button title="Reload" onPress={this.onPressedReload} />
</View>
<FastImage
style={styles.image}
source={{
uri: images[0] + this.state.bust,
headers: {
token: TOKEN,
},
priority: FastImage.priority.low,
}}
{...getTestProgressCallbacks('1')}
/>
<FastImage
style={styles.image}
source={{
uri: images[1] + this.state.bust,
headers: {
token: TOKEN,
},
priority: FastImage.priority.normal,
}}
{...getTestProgressCallbacks('2')}
/>
<FastImage
style={styles.image}
source={{
uri: images[2] + this.state.bust,
headers: {
token: TOKEN,
},
priority: FastImage.priority.high,
}}
{...getTestProgressCallbacks('3')}
/>
</ScrollView>
</View>
)
}
}
FastImageExample.navigationOptions = {
tabBarLabel: 'FastImage Example',
tabBarIcon: ({ focused, tintColor }) => {
if (focused)
return <Icon name="ios-information-circle" size={26} color={tintColor} />
return (
<Icon name="ios-information-circle-outline" size={26} color={tintColor} />
)
},
}
const styles = StyleSheet.create({
bold: {
fontWeight: '900',
},
textContainer: {
marginTop: 40,
marginBottom: 20,
},
image: {
height: IMAGE_SIZE,
width: IMAGE_SIZE,
backgroundColor: '#eee',
margin: 2,
},
container: {
flex: 1,
},
scrollContainer: {},
scrollContentContainer: {
alignItems: 'center',
flex: 0,
},
})
export default FastImageExample

View File

@ -0,0 +1,80 @@
import React from 'react'
import { ScrollView, StatusBar, StyleSheet, Text, View } from 'react-native'
import Icon from 'react-native-vector-icons/Ionicons'
import Section from './Section'
import PriorityExample from './PriorityExample'
import GifExample from './GifExample'
import BorderRadiusExample from './BorderRadiusExample'
import FeatureText from './FeatureText'
import ProgressExample from './ProgressExample'
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>
)
FastImageExample.navigationOptions = {
tabBarLabel: 'FastImage Example',
tabBarIcon: ({ focused, tintColor }) => {
const name = focused
? 'ios-information-circle'
: 'ios-information-circle-outline'
return <Icon name={name} size={26} color={tintColor} />
},
}
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,
},
})
export default FastImageExample

View File

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

View File

@ -0,0 +1,33 @@
import React from 'react'
import { StyleSheet, View } from 'react-native'
import withCacheBust from './withCacheBust'
import SectionFlex from './SectionFlex'
import FastImage from 'react-native-fast-image'
import Section from './Section'
import FeatureText from './FeatureText'
const GIF_URL =
'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>
)
const styles = StyleSheet.create({
image: {
backgroundColor: '#ddd',
margin: 10,
height: 100,
width: 100,
flex: 0,
},
})
export default withCacheBust(GifExample)

View File

@ -1,12 +1,6 @@
import React, { Component } from 'react'
import {
StyleSheet,
View,
FlatList,
Platform,
StatusBar,
Text,
} from 'react-native'
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}`
@ -87,24 +81,15 @@ class ImageGrid extends Component {
keyExtractor={this._extractKey}
getItemLayout={this._getItemLayout}
/>
<View style={styles.statusBarUnderlay} />
<StatusBarUnderlay />
</View>
)
}
}
const MARGIN = 2
const STATUS_BAR_HEIGHT = Platform.OS === 'ios' ? 20 : StatusBar.currentHeight
const styles = StyleSheet.create({
statusBarUnderlay: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: STATUS_BAR_HEIGHT,
backgroundColor: 'white',
},
container: {
flex: 1,
backgroundColor: '#fff',

View File

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

View File

@ -0,0 +1,59 @@
import React from 'react'
import { PixelRatio, StyleSheet, View } from 'react-native'
import withCacheBust from './withCacheBust'
import FastImage from 'react-native-fast-image'
import Section from './Section'
import SectionFlex from './SectionFlex'
import FeatureText from './FeatureText'
const getImageUrl = (id, width, 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),
]
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>
)
const styles = StyleSheet.create({
image: {
flex: 1,
height: 100,
backgroundColor: '#ddd',
margin: 10,
},
})
export default withCacheBust(PriorityExample)

View File

@ -0,0 +1,49 @@
import React from 'react'
import { StyleSheet, View } from 'react-native'
import withCacheBust from './withCacheBust'
import SectionFlex from './SectionFlex'
import FastImage from 'react-native-fast-image'
import Section from './Section'
import FeatureText from './FeatureText'
const IMAGE_URL = 'https://media.giphy.com/media/GEsoqZDGVoisw/giphy.gif'
const getTestProgressCallbacks = label => ({
onLoadStart: () => console.log(`${label} - onLoadStart`),
onProgress: e =>
console.log(
`${label} - onProgress - ${e.nativeEvent.loaded / e.nativeEvent.total}`,
),
onLoad: () => console.log(`${label} - onLoad`),
onError: () => console.log(`${label} - onError`),
onLoadEnd: () => console.log(`${label} - onLoadEnd`),
})
const ProgressExample = ({ onPressReload, bust }) => (
<View>
<Section>
<FeatureText text="• Progress callbacks." />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage
style={styles.image}
source={{
uri: IMAGE_URL + bust,
}}
{...getTestProgressCallbacks('ProgressExample')}
/>
</SectionFlex>
</View>
)
const styles = StyleSheet.create({
image: {
height: 100,
backgroundColor: '#ddd',
margin: 20,
width: 100,
flex: 0,
},
})
export default withCacheBust(ProgressExample)

View File

@ -0,0 +1,13 @@
import React from 'react'
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,
},
})

View File

@ -0,0 +1,20 @@
import React from 'react'
import { StyleSheet, TouchableOpacity } from 'react-native'
export default ({ children, onPress, style }) => (
<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,
},
})

View File

@ -0,0 +1,18 @@
import React from 'react'
import { Platform, StatusBar, StyleSheet, View } from 'react-native'
export const STATUS_BAR_HEIGHT =
Platform.OS === 'ios' ? 20 : StatusBar.currentHeight
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',
},
})

View File

@ -0,0 +1,28 @@
import React, { Component } from 'react'
import uuid from 'uuid/v4'
export default BaseComponent => {
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 })
}
render() {
return (
<BaseComponent
bust={this.state.bust}
onPressReload={this.onPressReload}
/>
)
}
}
WithCacheBust.displayName = `withCacheBust${BaseComponent.displayName}`
return WithCacheBust
}

101
index.d.ts vendored Normal file
View File

@ -0,0 +1,101 @@
import * as React from 'react'
import { FlexStyle, LayoutChangeEvent, ShadowStyleIOS, StyleProp, TransformsStyle } from 'react-native'
declare namespace FastImage {
namespace priority {
type low = 'low'
type normal = 'normal'
type high = 'high'
}
namespace resizeMode {
type contain = 'contain'
type cover = 'cover'
type stretch = 'stretch'
type center = 'center'
}
export type Priority =
FastImage.priority.low |
FastImage.priority.normal |
FastImage.priority.high
export type ResizeMode =
FastImage.resizeMode.contain |
FastImage.resizeMode.cover |
FastImage.resizeMode.stretch |
FastImage.resizeMode.center
}
export type FastImageSource = {
uri?: string,
headers?: object
priority?: FastImage.Priority
}
export interface ImageStyle extends FlexStyle, TransformsStyle, ShadowStyleIOS {
backfaceVisibility?: 'visible' | 'hidden'
backgroundColor?: string
borderColor?: string
overlayColor?: string
tintColor?: string
opacity?: number
}
export interface FastImageProperties {
source: FastImageSource | number
resizeMode?: FastImage.ResizeMode
onLoadStart?(): void
onProgress?(event: any): void
onLoad?(): void
onError?(): void
onLoadEnd?(): void
/**
* onLayout function
*
* Invoked on mount and layout changes with
*
* {nativeEvent: { layout: {x, y, width, height}}}.
*/
onLayout?: (event: LayoutChangeEvent) => void;
/**
*
* Style
*/
style?: StyleProp<ImageStyle>;
/**
* A unique identifier for this element to be used in UI Automation testing scripts.
*/
testID?: string;
}
interface FastImageStatic extends React.ComponentClass<FastImageProperties> {
resizeMode: {
contain: FastImage.resizeMode.contain
cover: FastImage.resizeMode.cover
stretch: FastImage.resizeMode.stretch
center: FastImage.resizeMode.center
}
priority: {
low: FastImage.priority.low
normal: FastImage.priority.normal
high: FastImage.priority.high
}
preload(sources: FastImageSource[]): void
}
declare var FastImage: FastImageStatic
type FastImage = FastImageStatic
export default FastImage

View File

@ -1,6 +1,6 @@
{
"name": "react-native-fast-image",
"version": "2.0.0",
"version": "2.2.4",
"description": "🚩 FastImage, performant React Native image component.",
"keywords": [
"cache",
@ -19,7 +19,8 @@
"ios",
"android",
"utils",
"FastImage.js"
"FastImage.js",
"index.d.ts"
],
"main": "FastImage.js",
"directories": {
@ -49,10 +50,6 @@
"react-native": "^0.50.4",
"react-test-renderer": "16.0.0"
},
"engines": {
"node": ">= 9.2.0",
"yarn": ">= 1.3.2"
},
"jest": {
"preset": "react-native",
"modulePathIgnorePatterns": [

View File

Before

Width:  |  Height:  |  Size: 8.9 MiB

After

Width:  |  Height:  |  Size: 8.9 MiB

View File

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

View File

Before

Width:  |  Height:  |  Size: 16 MiB

After

Width:  |  Height:  |  Size: 16 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 804 KiB