Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add placeholder functionality #409

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module.exports = {
parser: 'babel-eslint',
env: {
es6: true,
browser: true,
node: true,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, why did you modified the eslintrc? ^^

},
plugins: ['jest'],
overrides: {
Expand Down
2 changes: 1 addition & 1 deletion ios/Vendor/SDWebImage
17 changes: 16 additions & 1 deletion src/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ exports[`FastImage renders correctly. 1`] = `
}
>
<FastImageView
onFastImageError={[Function]}
onFastImageLoad={[Function]}
onFastImageLoadEnd={[Function]}
onFastImageLoadStart={[Function]}
onFastImageProgress={[Function]}
resizeMode="cover"
source={
Object {
Expand Down Expand Up @@ -52,7 +57,12 @@ exports[`Renders Image with fallback prop. 1`] = `
]
}
>
<Image
<FastImageView
onError={[Function]}
onLoad={[Function]}
onLoadEnd={[Function]}
onLoadStart={[Function]}
onProgress={[Function]}
resizeMode="cover"
source={
Object {
Expand Down Expand Up @@ -87,6 +97,11 @@ exports[`Renders a normal Image when not passed a uri. 1`] = `
}
>
<FastImageView
onFastImageError={[Function]}
onFastImageLoad={[Function]}
onFastImageLoadEnd={[Function]}
onFastImageLoadStart={[Function]}
onFastImageProgress={[Function]}
resizeMode="cover"
source={
Object {
Expand Down
1 change: 1 addition & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export interface OnProgressEvent {

export interface FastImageProperties {
source: FastImageSource | number
placeholder?: React.ReactNode
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you can allow number here too? So that one could write:

import myPlaceholderPicture from 'src/images/myPlaceholderPicture.png';

....
	<FastImage source={{ uri: myUri }} placeholder={myPlaceholderPicture} />

Instead of being forced to do this, for example:

import { Image } from 'react-native';
import myPlaceholderPicture from 'src/images/myPlaceholderPicture.png';

....
	<FastImage source={{ uri: myUri }} placeholder={<Image source={myPlaceHolderImage}} />} />

Though I am assuming that the default placeholder for an image is another image.

resizeMode?: FastImage.ResizeMode
fallback?: boolean

Expand Down
92 changes: 76 additions & 16 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { forwardRef } from 'react'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {
View,
Expand All @@ -11,9 +11,47 @@ import {

const FastImageViewNativeModule = NativeModules.FastImageView

const FastImage = forwardRef(
(
{
class FastImage extends Component {
componentDidMount() {
this.runTimer()
}

componentDidUpdate(prevProps) {
if (this.props.source.uri !== prevProps.source.uri) {
this.setState({
loaded: false,
error: null,
expired: false,
})

this.runTimer()
}
}

componentWillUnmount() {
clearTimeout(this.timeout)
}

runTimer() {
this.timeout = setTimeout(() => {
this.setState({ expired: true })
}, 1000)
}

state = {
loaded: false,
error: null,
expired: false,
}

setNativeProps(nativeProps) {
this._root.setNativeProps(nativeProps)
}

captureRef = e => (this._root = e)

render() {
const {
source,
onLoadStart,
onProgress,
Expand All @@ -23,16 +61,21 @@ const FastImage = forwardRef(
style,
children,
fallback,
placeholder,
...props
},
ref,
) => {
} = this.props

const { expired, loaded, error } = this.state
const resolvedSource = Image.resolveAssetSource(source)

if (fallback) {
return (
<View style={[styles.imageContainer, style]} ref={ref}>
<Image
<View
style={[styles.imageContainer, style]}
ref={this.captureRef}
>
{expired && (!loaded || error) && placeholder}
<FastImageView
{...props}
style={StyleSheet.absoluteFill}
source={resolvedSource}
Expand All @@ -48,24 +91,35 @@ const FastImage = forwardRef(
}

return (
<View style={[styles.imageContainer, style]} ref={ref}>
<View style={[styles.imageContainer, style]} ref={this.captureRef}>
{expired && (!loaded || error) && placeholder}
<FastImageView
{...props}
style={StyleSheet.absoluteFill}
source={resolvedSource}
onFastImageLoadStart={onLoadStart}
onFastImageProgress={onProgress}
onFastImageLoad={onLoad}
onFastImageError={onError}
onFastImageLoadEnd={onLoadEnd}
onFastImageError={data => {
this.setState({
error: true,
})

onError(data)
}}
onFastImageLoadEnd={data => {
this.setState({
loaded: true,
})

onLoadEnd(data)
}}
/>
{children}
</View>
)
},
)

FastImage.displayName = 'FastImage'
}
}

const styles = StyleSheet.create({
imageContainer: {
Expand Down Expand Up @@ -104,6 +158,11 @@ FastImage.preload = sources => {

FastImage.defaultProps = {
resizeMode: FastImage.resizeMode.cover,
onLoadStart: () => {},
onProgress: () => {},
onLoad: () => {},
onError: () => {},
onLoadEnd: () => {},
}

const FastImageSourcePropType = PropTypes.shape({
Expand All @@ -122,6 +181,7 @@ FastImage.propTypes = {
onError: PropTypes.func,
onLoadEnd: PropTypes.func,
fallback: PropTypes.bool,
placeholder: PropTypes.node,
}

const FastImageView = requireNativeComponent('FastImageView', FastImage, {
Expand Down
4 changes: 3 additions & 1 deletion src/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import type { ViewProps } from 'react-native/Libraries/Components/View/ViewPropTypes'
import type { SyntheticEvent } from 'react-native/Libraries/Types/CoreEventTypes'
import type { Node } from 'react';

export type OnLoadEvent = SyntheticEvent<
$ReadOnly<{
Expand Down Expand Up @@ -57,7 +58,8 @@ export type FastImageProps = $ReadOnly<{|
onProgress?: ?(event: OnProgressEvent) => void,

source: FastImageSource | number,

placeholder?: Node,

resizeMode?: ?ResizeModes,
fallback?: ?boolean,
testID?: ?string,
Expand Down