2018-06-26 01:55:33 +03:00
/ * *
2018-09-12 01:27:47 +03:00
* Copyright ( c ) Facebook , Inc . and its affiliates .
2018-06-26 01:55:33 +03:00
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree .
*
2018-08-08 20:39:16 +03:00
* @ flow
2018-06-26 01:55:33 +03:00
* @ format
* /
'use strict' ;
2019-05-08 18:44:25 +03:00
const DeprecatedImageStylePropTypes = require ( '../DeprecatedPropTypes/DeprecatedImageStylePropTypes' ) ;
const DeprecatedStyleSheetPropType = require ( '../DeprecatedPropTypes/DeprecatedStyleSheetPropType' ) ;
const DeprecatedViewPropTypes = require ( '../DeprecatedPropTypes/DeprecatedViewPropTypes' ) ;
const ImageViewNativeComponent = require ( './ImageViewNativeComponent' ) ;
const NativeModules = require ( '../BatchedBridge/NativeModules' ) ;
2018-08-23 04:22:00 +03:00
const PropTypes = require ( 'prop-types' ) ;
2019-05-08 18:44:25 +03:00
const React = require ( 'react' ) ;
const ReactNative = require ( '../Renderer/shims/ReactNative' ) ; // eslint-disable-line no-unused-vars
const StyleSheet = require ( '../StyleSheet/StyleSheet' ) ;
const TextAncestor = require ( '../Text/TextAncestor' ) ;
2018-06-26 01:55:33 +03:00
2019-05-08 18:44:25 +03:00
const flattenStyle = require ( '../StyleSheet/flattenStyle' ) ;
const resolveAssetSource = require ( './resolveAssetSource' ) ;
2018-06-26 01:55:33 +03:00
const { ImageLoader } = NativeModules ;
2019-05-08 18:44:25 +03:00
const TextInlineImageNativeComponent = require ( './TextInlineImageNativeComponent' ) ;
2018-06-26 01:55:33 +03:00
2019-05-08 18:44:25 +03:00
import type { ImageProps as ImagePropsType } from './ImageProps' ;
2018-06-26 01:55:33 +03:00
let _requestId = 1 ;
function generateRequestId ( ) {
return _requestId ++ ;
}
const ImageProps = {
2018-08-23 04:22:00 +03:00
... DeprecatedViewPropTypes ,
2019-08-23 18:43:08 +03:00
style : ( DeprecatedStyleSheetPropType (
DeprecatedImageStylePropTypes ,
) : ReactPropsCheckType ) ,
2018-06-26 01:55:33 +03:00
/ * *
* See https : //facebook.github.io/react-native/docs/image.html#source
* /
2019-08-23 18:43:08 +03:00
source : ( PropTypes . oneOfType ( [
2018-06-26 01:55:33 +03:00
PropTypes . shape ( {
uri : PropTypes . string ,
headers : PropTypes . objectOf ( PropTypes . string ) ,
} ) ,
// Opaque type returned by require('./image.jpg')
PropTypes . number ,
// Multiple sources
PropTypes . arrayOf (
PropTypes . shape ( {
uri : PropTypes . string ,
width : PropTypes . number ,
height : PropTypes . number ,
headers : PropTypes . objectOf ( PropTypes . string ) ,
} ) ,
) ,
2019-08-23 18:43:08 +03:00
] ) : React$PropType$Primitive <
| { headers ? : { [ string ] : string } , uri ? : string }
| number
| Array < {
headers ? : { [ string ] : string } ,
height ? : number ,
uri ? : string ,
width ? : number ,
} > ,
> ) ,
2018-06-26 01:55:33 +03:00
/ * *
* blurRadius : the blur radius of the blur filter added to the image
*
* See https : //facebook.github.io/react-native/docs/image.html#blurradius
* /
blurRadius : PropTypes . number ,
/ * *
* See https : //facebook.github.io/react-native/docs/image.html#defaultsource
* /
defaultSource : PropTypes . number ,
/ * *
* See https : //facebook.github.io/react-native/docs/image.html#loadingindicatorsource
* /
2019-08-23 18:43:08 +03:00
loadingIndicatorSource : ( PropTypes . oneOfType ( [
2018-06-26 01:55:33 +03:00
PropTypes . shape ( {
uri : PropTypes . string ,
} ) ,
// Opaque type returned by require('./image.jpg')
PropTypes . number ,
2019-08-23 18:43:08 +03:00
] ) : React$PropType$Primitive < { uri ? : string } | number > ) ,
2018-06-26 01:55:33 +03:00
progressiveRenderingEnabled : PropTypes . bool ,
fadeDuration : PropTypes . number ,
/ * *
* Invoked on load start
* /
onLoadStart : PropTypes . func ,
/ * *
* Invoked on load error
* /
onError : PropTypes . func ,
/ * *
* Invoked when load completes successfully
* /
onLoad : PropTypes . func ,
/ * *
* Invoked when load either succeeds or fails
* /
onLoadEnd : PropTypes . func ,
/ * *
* Used to locate this view in end - to - end tests .
* /
testID : PropTypes . string ,
/ * *
* The mechanism that should be used to resize the image when the image ' s dimensions
* differ from the image view ' s dimensions . Defaults to ` auto ` .
*
* See https : //facebook.github.io/react-native/docs/image.html#resizemethod
* /
2019-08-23 18:43:08 +03:00
resizeMethod : ( PropTypes . oneOf ( [
'auto' ,
'resize' ,
'scale' ,
] ) : React$PropType$Primitive < 'auto' | 'resize' | 'scale' > ) ,
2018-06-26 01:55:33 +03:00
/ * *
* Determines how to resize the image when the frame doesn ' t match the raw
* image dimensions .
*
* See https : //facebook.github.io/react-native/docs/image.html#resizemode
* /
2019-08-23 18:43:08 +03:00
resizeMode : ( PropTypes . oneOf ( [
2018-06-26 01:55:33 +03:00
'cover' ,
'contain' ,
'stretch' ,
'repeat' ,
'center' ,
2019-08-23 18:43:08 +03:00
] ) : React$PropType$Primitive <
'cover' | 'contain' | 'stretch' | 'repeat' | 'center' ,
> ) ,
2018-06-26 01:55:33 +03:00
} ;
2019-03-13 05:17:24 +03:00
/ * *
* Retrieve the width and height ( in pixels ) of an image prior to displaying it
*
* See https : //facebook.github.io/react-native/docs/image.html#getsize
* /
2018-06-26 01:55:33 +03:00
function getSize (
url : string ,
success : ( width : number , height : number ) => void ,
failure ? : ( error : any ) => void ,
2019-08-23 18:43:08 +03:00
) : any {
2018-06-26 01:55:33 +03:00
return ImageLoader . getSize ( url )
. then ( function ( sizes ) {
success ( sizes . width , sizes . height ) ;
} )
. catch (
failure ||
function ( ) {
console . warn ( 'Failed to get size for image: ' + url ) ;
} ,
) ;
}
2019-03-13 05:17:24 +03:00
/ * *
* Retrieve the width and height ( in pixels ) of an image prior to displaying it
* with the ability to provide the headers for the request
*
* See https : //facebook.github.io/react-native/docs/image.html#getsizewithheaders
* /
function getSizeWithHeaders (
url : string ,
headers : { [ string ] : string } ,
success : ( width : number , height : number ) => void ,
failure ? : ( error : any ) => void ,
2019-08-23 18:43:08 +03:00
) : any {
2019-03-13 05:17:24 +03:00
return ImageLoader . getSizeWithHeaders ( url , headers )
. then ( function ( sizes ) {
success ( sizes . width , sizes . height ) ;
} )
. catch (
failure ||
function ( ) {
console . warn ( 'Failed to get size for image: ' + url ) ;
} ,
) ;
}
2019-08-23 18:43:08 +03:00
function prefetch ( url : string , callback : ? Function ) : any {
2018-06-26 01:55:33 +03:00
const requestId = generateRequestId ( ) ;
callback && callback ( requestId ) ;
return ImageLoader . prefetchImage ( url , requestId ) ;
}
function abortPrefetch ( requestId : number ) {
ImageLoader . abortRequest ( requestId ) ;
}
/ * *
* Perform cache interrogation .
*
* See https : //facebook.github.io/react-native/docs/image.html#querycache
* /
async function queryCache (
urls : Array < string > ,
2019-02-26 07:31:42 +03:00
) : Promise < { [ string ] : 'memory' | 'disk' | 'disk/memory' } > {
2018-06-26 01:55:33 +03:00
return await ImageLoader . queryCache ( urls ) ;
}
2019-09-25 20:10:48 +03:00
type ImageComponentStatics = $ReadOnly < { |
getSize : typeof getSize ,
getSizeWithHeaders : typeof getSizeWithHeaders ,
prefetch : typeof prefetch ,
abortPrefetch : typeof abortPrefetch ,
queryCache : typeof queryCache ,
resolveAssetSource : typeof resolveAssetSource ,
propTypes : typeof ImageProps ,
| } > ;
2018-06-26 01:55:33 +03:00
/ * *
* A React component for displaying different types of images ,
* including network images , static resources , temporary local images , and
* images from local disk , such as the camera roll .
*
* See https : //facebook.github.io/react-native/docs/image.html
* /
2019-09-25 20:10:48 +03:00
let Image = ( props : ImagePropsType , forwardedRef ) => {
2018-07-31 21:49:07 +03:00
let source = resolveAssetSource ( props . source ) ;
2018-06-26 01:55:33 +03:00
const defaultSource = resolveAssetSource ( props . defaultSource ) ;
const loadingIndicatorSource = resolveAssetSource (
props . loadingIndicatorSource ,
) ;
if ( source && source . uri === '' ) {
console . warn ( 'source.uri should not be an empty string' ) ;
}
if ( props . src ) {
console . warn (
'The <Image> component requires a `source` property rather than `src`.' ,
) ;
}
if ( props . children ) {
throw new Error (
'The <Image> component cannot contain children. If you want to render content on top of the image, consider using the <ImageBackground> component or absolute positioning.' ,
) ;
}
if ( props . defaultSource && props . loadingIndicatorSource ) {
throw new Error (
'The <Image> component cannot have defaultSource and loadingIndicatorSource at the same time. Please use either defaultSource or loadingIndicatorSource.' ,
) ;
}
2018-07-31 21:49:07 +03:00
if ( source && ! source . uri && ! Array . isArray ( source ) ) {
source = null ;
2018-07-04 01:31:48 +03:00
}
2018-06-26 01:55:33 +03:00
let style ;
let sources ;
2018-07-31 21:49:07 +03:00
if ( source ? . uri != null ) {
2018-08-13 21:14:35 +03:00
/ * $ F l o w F i x M e ( > = 0 . 7 8 . 0 s i t e = r e a c t _ n a t i v e _ a n d r o i d _ f b ) T h i s i s s u e w a s f o u n d
* when making Flow check . android . js files . * /
2018-06-26 01:55:33 +03:00
const { width , height } = source ;
style = flattenStyle ( [ { width , height } , styles . base , props . style ] ) ;
2018-08-13 21:14:35 +03:00
/ * $ F l o w F i x M e ( > = 0 . 7 8 . 0 s i t e = r e a c t _ n a t i v e _ a n d r o i d _ f b ) T h i s i s s u e w a s f o u n d
* when making Flow check . android . js files . * /
2018-06-26 01:55:33 +03:00
sources = [ { uri : source . uri } ] ;
} else {
style = flattenStyle ( [ styles . base , props . style ] ) ;
sources = source ;
}
const { onLoadStart , onLoad , onLoadEnd , onError } = props ;
2019-10-13 01:47:17 +03:00
const nativeProps = {
... props ,
2018-06-26 01:55:33 +03:00
style ,
shouldNotifyLoadEvents : ! ! ( onLoadStart || onLoad || onLoadEnd || onError ) ,
src : sources ,
2018-08-13 21:14:35 +03:00
/ * $ F l o w F i x M e ( > = 0 . 7 8 . 0 s i t e = r e a c t _ n a t i v e _ a n d r o i d _ f b ) T h i s i s s u e w a s f o u n d
* when making Flow check . android . js files . * /
2018-07-31 21:49:07 +03:00
headers : source ? . headers ,
2018-06-26 01:55:33 +03:00
defaultSrc : defaultSource ? defaultSource . uri : null ,
loadingIndicatorSrc : loadingIndicatorSource
? loadingIndicatorSource . uri
: null ,
ref : forwardedRef ,
2019-10-13 01:47:17 +03:00
} ;
2018-06-26 01:55:33 +03:00
return (
< TextAncestor . Consumer >
{ hasTextAncestor =>
hasTextAncestor ? (
2018-08-24 07:35:12 +03:00
< TextInlineImageNativeComponent { ... nativeProps } / >
2018-06-26 01:55:33 +03:00
) : (
2018-08-24 07:35:16 +03:00
< ImageViewNativeComponent { ... nativeProps } / >
2018-06-26 01:55:33 +03:00
)
}
< / T e x t A n c e s t o r . C o n s u m e r >
) ;
} ;
2019-09-25 20:10:48 +03:00
Image = React . forwardRef <
ImagePropsType ,
| React . ElementRef < typeof TextInlineImageNativeComponent >
| React . ElementRef < typeof ImageViewNativeComponent > ,
> ( Image ) ;
2019-02-04 18:35:16 +03:00
Image . displayName = 'Image' ;
2018-06-26 01:55:33 +03:00
/ * *
2018-11-04 04:35:21 +03:00
* Retrieve the width and height ( in pixels ) of an image prior to displaying it
2018-06-26 01:55:33 +03:00
*
2018-11-04 04:35:21 +03:00
* See https : //facebook.github.io/react-native/docs/image.html#getsize
2018-06-26 01:55:33 +03:00
* /
2018-12-15 00:54:52 +03:00
/ * $ F l o w F i x M e ( > = 0 . 8 9 . 0 s i t e = r e a c t _ n a t i v e _ a n d r o i d _ f b ) T h i s c o m m e n t s u p p r e s s e s a n
* error found when Flow v0 . 89 was deployed . To see the error , delete this
* comment and run Flow . * /
2018-06-26 01:55:33 +03:00
Image . getSize = getSize ;
2019-03-13 05:17:24 +03:00
/ * *
* Retrieve the width and height ( in pixels ) of an image prior to displaying it
* with the ability to provide the headers for the request
*
* See https : //facebook.github.io/react-native/docs/image.html#getsizewithheaders
* /
/ * $ F l o w F i x M e ( > = 0 . 8 9 . 0 s i t e = r e a c t _ n a t i v e _ a n d r o i d _ f b ) T h i s c o m m e n t s u p p r e s s e s a n
* error found when Flow v0 . 89 was deployed . To see the error , delete this
* comment and run Flow . * /
Image . getSizeWithHeaders = getSizeWithHeaders ;
2018-06-26 01:55:33 +03:00
/ * *
* Prefetches a remote image for later use by downloading it to the disk
* cache
*
* See https : //facebook.github.io/react-native/docs/image.html#prefetch
* /
2018-12-15 00:54:52 +03:00
/ * $ F l o w F i x M e ( > = 0 . 8 9 . 0 s i t e = r e a c t _ n a t i v e _ a n d r o i d _ f b ) T h i s c o m m e n t s u p p r e s s e s a n
* error found when Flow v0 . 89 was deployed . To see the error , delete this
* comment and run Flow . * /
2018-06-26 01:55:33 +03:00
Image . prefetch = prefetch ;
/ * *
* Abort prefetch request .
*
* See https : //facebook.github.io/react-native/docs/image.html#abortprefetch
* /
2018-12-15 00:54:52 +03:00
/ * $ F l o w F i x M e ( > = 0 . 8 9 . 0 s i t e = r e a c t _ n a t i v e _ a n d r o i d _ f b ) T h i s c o m m e n t s u p p r e s s e s a n
* error found when Flow v0 . 89 was deployed . To see the error , delete this
* comment and run Flow . * /
2018-06-26 01:55:33 +03:00
Image . abortPrefetch = abortPrefetch ;
/ * *
* Perform cache interrogation .
*
* See https : //facebook.github.io/react-native/docs/image.html#querycache
* /
2018-12-15 00:54:52 +03:00
/ * $ F l o w F i x M e ( > = 0 . 8 9 . 0 s i t e = r e a c t _ n a t i v e _ a n d r o i d _ f b ) T h i s c o m m e n t s u p p r e s s e s a n
* error found when Flow v0 . 89 was deployed . To see the error , delete this
* comment and run Flow . * /
2018-06-26 01:55:33 +03:00
Image . queryCache = queryCache ;
/ * *
* Resolves an asset reference into an object .
*
* See https : //facebook.github.io/react-native/docs/image.html#resolveassetsource
* /
2018-12-15 00:54:52 +03:00
/ * $ F l o w F i x M e ( > = 0 . 8 9 . 0 s i t e = r e a c t _ n a t i v e _ a n d r o i d _ f b ) T h i s c o m m e n t s u p p r e s s e s a n
* error found when Flow v0 . 89 was deployed . To see the error , delete this
* comment and run Flow . * /
2018-06-26 01:55:33 +03:00
Image . resolveAssetSource = resolveAssetSource ;
2018-12-15 00:54:52 +03:00
/ * $ F l o w F i x M e ( > = 0 . 8 9 . 0 s i t e = r e a c t _ n a t i v e _ a n d r o i d _ f b ) T h i s c o m m e n t s u p p r e s s e s a n
* error found when Flow v0 . 89 was deployed . To see the error , delete this
* comment and run Flow . * /
2018-06-26 01:55:33 +03:00
Image . propTypes = ImageProps ;
const styles = StyleSheet . create ( {
base : {
overflow : 'hidden' ,
} ,
} ) ;
2019-09-25 20:10:48 +03:00
module . exports = ( ( Image : any ) : React . AbstractComponent <
ImagePropsType ,
| React . ElementRef < typeof TextInlineImageNativeComponent >
| React . ElementRef < typeof ImageViewNativeComponent > ,
> &
ImageComponentStatics ) ;