123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- /**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @flow
- * @format
- */
- 'use strict';
- const DeprecatedImageStylePropTypes = require('../DeprecatedPropTypes/DeprecatedImageStylePropTypes');
- const DeprecatedStyleSheetPropType = require('../DeprecatedPropTypes/DeprecatedStyleSheetPropType');
- const DeprecatedViewPropTypes = require('../DeprecatedPropTypes/DeprecatedViewPropTypes');
- import ImageViewNativeComponent from './ImageViewNativeComponent';
- const PropTypes = require('prop-types');
- 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');
- const ImageAnalyticsTagContext = require('./ImageAnalyticsTagContext').default;
- const flattenStyle = require('../StyleSheet/flattenStyle');
- const resolveAssetSource = require('./resolveAssetSource');
- import NativeImageLoaderAndroid from './NativeImageLoaderAndroid';
- const TextInlineImageNativeComponent = require('./TextInlineImageNativeComponent');
- import type {ImageProps as ImagePropsType} from './ImageProps';
- let _requestId = 1;
- function generateRequestId() {
- return _requestId++;
- }
- const ImageProps = {
- ...DeprecatedViewPropTypes,
- style: (DeprecatedStyleSheetPropType(
- DeprecatedImageStylePropTypes,
- ): ReactPropsCheckType),
- /**
- * See https://reactnative.dev/docs/image.html#source
- */
- source: (PropTypes.oneOfType([
- 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),
- }),
- ),
- ]): React$PropType$Primitive<
- | {
- headers?: {[string]: string, ...},
- uri?: string,
- ...
- }
- | number
- | Array<{
- headers?: {[string]: string, ...},
- height?: number,
- uri?: string,
- width?: number,
- ...
- }>,
- >),
- /**
- * blurRadius: the blur radius of the blur filter added to the image
- *
- * See https://reactnative.dev/docs/image.html#blurradius
- */
- blurRadius: PropTypes.number,
- /**
- * See https://reactnative.dev/docs/image.html#defaultsource
- */
- defaultSource: PropTypes.number,
- /**
- * See https://reactnative.dev/docs/image.html#loadingindicatorsource
- */
- loadingIndicatorSource: (PropTypes.oneOfType([
- PropTypes.shape({
- uri: PropTypes.string,
- }),
- // Opaque type returned by require('./image.jpg')
- PropTypes.number,
- ]): React$PropType$Primitive<{uri?: string, ...} | number>),
- progressiveRenderingEnabled: PropTypes.bool,
- fadeDuration: PropTypes.number,
- /**
- * Analytics Tag used by this Image
- */
- internal_analyticTag: PropTypes.string,
- /**
- * 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://reactnative.dev/docs/image.html#resizemethod
- */
- resizeMethod: (PropTypes.oneOf([
- 'auto',
- 'resize',
- 'scale',
- ]): React$PropType$Primitive<'auto' | 'resize' | 'scale'>),
- /**
- * Determines how to resize the image when the frame doesn't match the raw
- * image dimensions.
- *
- * See https://reactnative.dev/docs/image.html#resizemode
- */
- resizeMode: (PropTypes.oneOf([
- 'cover',
- 'contain',
- 'stretch',
- 'repeat',
- 'center',
- ]): React$PropType$Primitive<
- 'cover' | 'contain' | 'stretch' | 'repeat' | 'center',
- >),
- };
- /**
- * Retrieve the width and height (in pixels) of an image prior to displaying it
- *
- * See https://reactnative.dev/docs/image.html#getsize
- */
- function getSize(
- url: string,
- success: (width: number, height: number) => void,
- failure?: (error: any) => void,
- ): any {
- return NativeImageLoaderAndroid.getSize(url)
- .then(function(sizes) {
- success(sizes.width, sizes.height);
- })
- .catch(
- failure ||
- function() {
- console.warn('Failed to get size for image: ' + url);
- },
- );
- }
- /**
- * 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://reactnative.dev/docs/image.html#getsizewithheaders
- */
- function getSizeWithHeaders(
- url: string,
- headers: {[string]: string, ...},
- success: (width: number, height: number) => void,
- failure?: (error: any) => void,
- ): any {
- return NativeImageLoaderAndroid.getSizeWithHeaders(url, headers)
- .then(function(sizes) {
- success(sizes.width, sizes.height);
- })
- .catch(
- failure ||
- function() {
- console.warn('Failed to get size for image: ' + url);
- },
- );
- }
- function prefetch(url: string, callback: ?Function): any {
- const requestId = generateRequestId();
- callback && callback(requestId);
- return NativeImageLoaderAndroid.prefetchImage(url, requestId);
- }
- function abortPrefetch(requestId: number) {
- NativeImageLoaderAndroid.abortRequest(requestId);
- }
- /**
- * Perform cache interrogation.
- *
- * See https://reactnative.dev/docs/image.html#querycache
- */
- async function queryCache(
- urls: Array<string>,
- ): Promise<{[string]: 'memory' | 'disk' | 'disk/memory', ...}> {
- return await NativeImageLoaderAndroid.queryCache(urls);
- }
- type ImageComponentStatics = $ReadOnly<{|
- getSize: typeof getSize,
- getSizeWithHeaders: typeof getSizeWithHeaders,
- prefetch: typeof prefetch,
- abortPrefetch: typeof abortPrefetch,
- queryCache: typeof queryCache,
- resolveAssetSource: typeof resolveAssetSource,
- propTypes: typeof ImageProps,
- |}>;
- /**
- * 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://reactnative.dev/docs/image.html
- */
- let Image = (props: ImagePropsType, forwardedRef) => {
- let source = resolveAssetSource(props.source);
- 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.',
- );
- }
- if (source && !source.uri && !Array.isArray(source)) {
- source = null;
- }
- let style;
- let sources;
- if (source?.uri != null) {
- const {width, height} = source;
- style = flattenStyle([{width, height}, styles.base, props.style]);
- sources = [{uri: source.uri}];
- } else {
- style = flattenStyle([styles.base, props.style]);
- sources = source;
- }
- const {onLoadStart, onLoad, onLoadEnd, onError} = props;
- const nativeProps = {
- ...props,
- style,
- shouldNotifyLoadEvents: !!(onLoadStart || onLoad || onLoadEnd || onError),
- src: sources,
- /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found
- * when making Flow check .android.js files. */
- headers: source?.headers,
- defaultSrc: defaultSource ? defaultSource.uri : null,
- loadingIndicatorSrc: loadingIndicatorSource
- ? loadingIndicatorSource.uri
- : null,
- ref: forwardedRef,
- };
- return (
- <ImageAnalyticsTagContext.Consumer>
- {analyticTag => {
- const nativePropsWithAnalytics =
- analyticTag !== null
- ? {
- ...nativeProps,
- internal_analyticTag: analyticTag,
- }
- : nativeProps;
- return (
- <TextAncestor.Consumer>
- {hasTextAncestor =>
- hasTextAncestor ? (
- <TextInlineImageNativeComponent {...nativePropsWithAnalytics} />
- ) : (
- <ImageViewNativeComponent {...nativePropsWithAnalytics} />
- )
- }
- </TextAncestor.Consumer>
- );
- }}
- </ImageAnalyticsTagContext.Consumer>
- );
- };
- Image = React.forwardRef<
- ImagePropsType,
- | React.ElementRef<typeof TextInlineImageNativeComponent>
- | React.ElementRef<typeof ImageViewNativeComponent>,
- >(Image);
- Image.displayName = 'Image';
- /**
- * Retrieve the width and height (in pixels) of an image prior to displaying it
- *
- * See https://reactnative.dev/docs/image.html#getsize
- */
- /* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an
- * error found when Flow v0.89 was deployed. To see the error, delete this
- * comment and run Flow. */
- Image.getSize = getSize;
- /**
- * 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://reactnative.dev/docs/image.html#getsizewithheaders
- */
- /* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an
- * error found when Flow v0.89 was deployed. To see the error, delete this
- * comment and run Flow. */
- Image.getSizeWithHeaders = getSizeWithHeaders;
- /**
- * Prefetches a remote image for later use by downloading it to the disk
- * cache
- *
- * See https://reactnative.dev/docs/image.html#prefetch
- */
- /* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an
- * error found when Flow v0.89 was deployed. To see the error, delete this
- * comment and run Flow. */
- Image.prefetch = prefetch;
- /**
- * Abort prefetch request.
- *
- * See https://reactnative.dev/docs/image.html#abortprefetch
- */
- /* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an
- * error found when Flow v0.89 was deployed. To see the error, delete this
- * comment and run Flow. */
- Image.abortPrefetch = abortPrefetch;
- /**
- * Perform cache interrogation.
- *
- * See https://reactnative.dev/docs/image.html#querycache
- */
- /* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an
- * error found when Flow v0.89 was deployed. To see the error, delete this
- * comment and run Flow. */
- Image.queryCache = queryCache;
- /**
- * Resolves an asset reference into an object.
- *
- * See https://reactnative.dev/docs/image.html#resolveassetsource
- */
- /* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an
- * error found when Flow v0.89 was deployed. To see the error, delete this
- * comment and run Flow. */
- Image.resolveAssetSource = resolveAssetSource;
- /* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an
- * error found when Flow v0.89 was deployed. To see the error, delete this
- * comment and run Flow. */
- Image.propTypes = ImageProps;
- const styles = StyleSheet.create({
- base: {
- overflow: 'hidden',
- },
- });
- module.exports = ((Image: any): React.AbstractComponent<
- ImagePropsType,
- | React.ElementRef<typeof TextInlineImageNativeComponent>
- | React.ElementRef<typeof ImageViewNativeComponent>,
- > &
- ImageComponentStatics);
|