EUROPE\laprosek 1658a4c080 Implement Image.queryCache on iOS (#18782)
Summary:
The API was available only on Android (with no mention to that effect in the docs, AFAICT).
This commit adds a simple iOS implementation based on NSURLCache. It should be possible to
query the decoded image cache as well to provide higher fidelity (i.e. "disk", "memory",
"decoded") if the caller passes size, scale, etc. in addition to the image URL, but it's
probably not worth the complexity. The assumption is that callers are interested in the
durability rather than performance aspect of the returned information.

Tested with RNTester on iPhone emulator.

[IOS] [ENHANCEMENT] [Image] - Implemented queryCache
Pull Request resolved: https://github.com/facebook/react-native/pull/18782

Differential Revision: D9411533

Pulled By: hramos

fbshipit-source-id: b430263959bb5f9b8ed9e28bb0a95f8879df881a
2018-08-20 16:17:18 -07:00

164 lines
4.2 KiB
JavaScript

/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* 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 ImageProps = require('ImageProps');
const NativeModules = require('NativeModules');
const React = require('React');
const ReactNative = require('ReactNative');
const StyleSheet = require('StyleSheet');
const flattenStyle = require('flattenStyle');
const requireNativeComponent = require('requireNativeComponent');
const resolveAssetSource = require('resolveAssetSource');
const ImageViewManager = NativeModules.ImageViewManager;
const RCTImageView = requireNativeComponent('RCTImageView');
import type {ImageStyleProp} from 'StyleSheet';
import type {ImageProps as ImagePropsType} from 'ImageProps';
function getSize(
uri: string,
success: (width: number, height: number) => void,
failure?: (error: any) => void,
) {
ImageViewManager.getSize(
uri,
success,
failure ||
function() {
console.warn('Failed to get size for image: ' + uri);
},
);
}
function prefetch(url: string) {
return ImageViewManager.prefetchImage(url);
}
async function queryCache(urls: Array<string>): Promise<Map<string, 'memory' | 'disk'>> {
return await ImageViewManager.queryCache(urls);
}
declare class ImageComponentType extends ReactNative.NativeComponent<
ImagePropsType,
> {
static getSize: typeof getSize;
static prefetch: typeof prefetch;
static queryCache: typeof queryCache;
static resolveAssetSource: typeof resolveAssetSource;
static 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://facebook.github.io/react-native/docs/image.html
*/
let Image = (
props: ImagePropsType,
forwardedRef: ?React.Ref<'RCTImageView'>,
) => {
const source = resolveAssetSource(props.source) || {
uri: undefined,
width: undefined,
height: undefined,
};
let sources;
let style: ImageStyleProp;
if (Array.isArray(source)) {
// $FlowFixMe flattenStyle is not strong enough
style = flattenStyle([styles.base, props.style]) || {};
sources = source;
} else {
const {width, height, uri} = source;
// $FlowFixMe flattenStyle is not strong enough
style = flattenStyle([{width, height}, styles.base, props.style]) || {};
sources = [source];
if (uri === '') {
console.warn('source.uri should not be an empty string');
}
}
const resizeMode = props.resizeMode || style.resizeMode || 'cover';
const tintColor = style.tintColor;
if (props.src != null) {
console.warn(
'The <Image> component requires a `source` property rather than `src`.',
);
}
if (props.children != null) {
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.',
);
}
return (
<RCTImageView
{...props}
ref={forwardedRef}
style={style}
resizeMode={resizeMode}
tintColor={tintColor}
source={sources}
/>
);
};
// $FlowFixMe - TODO T29156721 `React.forwardRef` is not defined in Flow, yet.
Image = React.forwardRef(Image);
/**
* 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
*/
Image.getSize = getSize;
/**
* 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
*/
Image.prefetch = prefetch;
/**
* Performs cache interrogation.
*
* See https://facebook.github.io/react-native/docs/image.html#querycache
*/
Image.queryCache = queryCache;
/**
* Resolves an asset reference into an object.
*
* See https://facebook.github.io/react-native/docs/image.html#resolveassetsource
*/
Image.resolveAssetSource = resolveAssetSource;
Image.propTypes = ImageProps;
const styles = StyleSheet.create({
base: {
overflow: 'hidden',
},
});
module.exports = (Image: Class<ImageComponentType>);