Prettier for View, Image and co.

Summary: Trivial beauty.

Reviewed By: sahrens

Differential Revision: D6715955

fbshipit-source-id: 3632750591f53d4673a2ce76309a0cc62946524d
This commit is contained in:
Valentin Shergin 2018-01-14 19:32:26 -08:00 committed by Facebook Github Bot
parent bf9cabb03c
commit a5af841d25
12 changed files with 134 additions and 74 deletions

View File

@ -8,6 +8,7 @@
* *
* @providesModule View * @providesModule View
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';
@ -52,17 +53,18 @@ const View = createReactClass({
*/ */
viewConfig: { viewConfig: {
uiViewClassName: 'RCTView', uiViewClassName: 'RCTView',
validAttributes: ReactNativeViewAttributes.RCTView validAttributes: ReactNativeViewAttributes.RCTView,
}, },
contextTypes: { contextTypes: {
isInAParentText: PropTypes.bool, isInAParentText: PropTypes.bool,
}, },
render: function() { render() {
invariant( invariant(
!(this.context.isInAParentText && Platform.OS === 'android'), !(this.context.isInAParentText && Platform.OS === 'android'),
'Nesting of <View> within <Text> is not supported on Android.'); 'Nesting of <View> within <Text> is not supported on Android.',
);
// WARNING: This method will not be used in production mode as in that mode we // WARNING: This method will not be used in production mode as in that mode we
// replace wrapper component View with generated native wrapper RCTView. Avoid // replace wrapper component View with generated native wrapper RCTView. Avoid
@ -76,17 +78,18 @@ const RCTView = requireNativeComponent('RCTView', View, {
nativeOnly: { nativeOnly: {
nativeBackgroundAndroid: true, nativeBackgroundAndroid: true,
nativeForegroundAndroid: true, nativeForegroundAndroid: true,
} },
}); });
if (__DEV__) { if (__DEV__) {
const UIManager = require('UIManager'); const UIManager = require('UIManager');
const viewConfig = UIManager.viewConfigs && UIManager.viewConfigs.RCTView || {}; const viewConfig =
(UIManager.viewConfigs && UIManager.viewConfigs.RCTView) || {};
for (const prop in viewConfig.nativeProps) { for (const prop in viewConfig.nativeProps) {
const viewAny: any = View; // Appease flow const viewAny: any = View; // Appease flow
if (!viewAny.propTypes[prop] && !ReactNativeStyleAttributes[prop]) { if (!viewAny.propTypes[prop] && !ReactNativeStyleAttributes[prop]) {
throw new Error( throw new Error(
'View is missing propType for native prop `' + prop + '`' 'View is missing propType for native prop `' + prop + '`',
); );
} }
} }
@ -98,4 +101,4 @@ if (__DEV__) {
} }
// No one should depend on the DEV-mode createClass View wrapper. // No one should depend on the DEV-mode createClass View wrapper.
module.exports = ((ViewToExport : any) : typeof RCTView); module.exports = ((ViewToExport: any): typeof RCTView);

View File

@ -8,10 +8,10 @@
* *
* @providesModule AssetRegistry * @providesModule AssetRegistry
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';
export type PackagerAsset = { export type PackagerAsset = {
+__packager_asset: boolean, +__packager_asset: boolean,
+fileSystemLocation: string, +fileSystemLocation: string,
@ -24,7 +24,6 @@ export type PackagerAsset = {
+type: string, +type: string,
}; };
var assets: Array<PackagerAsset> = []; var assets: Array<PackagerAsset> = [];
function registerAsset(asset: PackagerAsset): number { function registerAsset(asset: PackagerAsset): number {
@ -37,4 +36,4 @@ function getAssetByID(assetId: number): PackagerAsset {
return assets[assetId - 1]; return assets[assetId - 1];
} }
module.exports = { registerAsset, getAssetByID }; module.exports = {registerAsset, getAssetByID};

View File

@ -8,6 +8,7 @@
* *
* @providesModule AssetSourceResolver * @providesModule AssetSourceResolver
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';
@ -19,7 +20,7 @@ export type ResolvedAssetSource = {
scale: number, scale: number,
}; };
import type { PackagerAsset } from 'AssetRegistry'; import type {PackagerAsset} from 'AssetRegistry';
const PixelRatio = require('PixelRatio'); const PixelRatio = require('PixelRatio');
const Platform = require('Platform'); const Platform = require('Platform');
@ -43,22 +44,18 @@ function getScaledAssetPath(asset): string {
function getAssetPathInDrawableFolder(asset): string { function getAssetPathInDrawableFolder(asset): string {
var scale = AssetSourceResolver.pickScale(asset.scales, PixelRatio.get()); var scale = AssetSourceResolver.pickScale(asset.scales, PixelRatio.get());
var drawbleFolder = assetPathUtils.getAndroidResourceFolderName(asset, scale); var drawbleFolder = assetPathUtils.getAndroidResourceFolderName(asset, scale);
var fileName = assetPathUtils.getAndroidResourceIdentifier(asset); var fileName = assetPathUtils.getAndroidResourceIdentifier(asset);
return drawbleFolder + '/' + fileName + '.' + asset.type; return drawbleFolder + '/' + fileName + '.' + asset.type;
} }
class AssetSourceResolver { class AssetSourceResolver {
serverUrl: ?string; serverUrl: ?string;
// where the jsbundle is being run from // where the jsbundle is being run from
jsbundleUrl: ?string; jsbundleUrl: ?string;
// the asset to resolve // the asset to resolve
asset: PackagerAsset; asset: PackagerAsset;
constructor(serverUrl: ?string, constructor(serverUrl: ?string, jsbundleUrl: ?string, asset: PackagerAsset) {
jsbundleUrl: ?string,
asset: PackagerAsset
) {
this.serverUrl = serverUrl; this.serverUrl = serverUrl;
this.jsbundleUrl = jsbundleUrl; this.jsbundleUrl = jsbundleUrl;
this.asset = asset; this.asset = asset;
@ -78,9 +75,9 @@ class AssetSourceResolver {
} }
if (Platform.OS === 'android') { if (Platform.OS === 'android') {
return this.isLoadedFromFileSystem() ? return this.isLoadedFromFileSystem()
this.drawableFolderInBundle() : ? this.drawableFolderInBundle()
this.resourceIdentifierWithoutScale(); : this.resourceIdentifierWithoutScale();
} else { } else {
return this.scaledAssetURLNearBundle(); return this.scaledAssetURLNearBundle();
} }
@ -93,8 +90,12 @@ class AssetSourceResolver {
assetServerURL(): ResolvedAssetSource { assetServerURL(): ResolvedAssetSource {
invariant(!!this.serverUrl, 'need server to load from'); invariant(!!this.serverUrl, 'need server to load from');
return this.fromSource( return this.fromSource(
this.serverUrl + getScaledAssetPath(this.asset) + this.serverUrl +
'?platform=' + Platform.OS + '&hash=' + this.asset.hash getScaledAssetPath(this.asset) +
'?platform=' +
Platform.OS +
'&hash=' +
this.asset.hash,
); );
} }
@ -122,8 +123,13 @@ class AssetSourceResolver {
* E.g. 'assets_awesomemodule_icon' * E.g. 'assets_awesomemodule_icon'
*/ */
resourceIdentifierWithoutScale(): ResolvedAssetSource { resourceIdentifierWithoutScale(): ResolvedAssetSource {
invariant(Platform.OS === 'android', 'resource identifiers work on Android'); invariant(
return this.fromSource(assetPathUtils.getAndroidResourceIdentifier(this.asset)); Platform.OS === 'android',
'resource identifiers work on Android',
);
return this.fromSource(
assetPathUtils.getAndroidResourceIdentifier(this.asset),
);
} }
/** /**
@ -133,9 +139,7 @@ class AssetSourceResolver {
*/ */
drawableFolderInBundle(): ResolvedAssetSource { drawableFolderInBundle(): ResolvedAssetSource {
const path = this.jsbundleUrl || 'file://'; const path = this.jsbundleUrl || 'file://';
return this.fromSource( return this.fromSource(path + getAssetPathInDrawableFolder(this.asset));
path + getAssetPathInDrawableFolder(this.asset)
);
} }
fromSource(source: string): ResolvedAssetSource { fromSource(source: string): ResolvedAssetSource {
@ -161,7 +165,6 @@ class AssetSourceResolver {
// in which case we default to 1 // in which case we default to 1
return scales[scales.length - 1] || 1; return scales[scales.length - 1] || 1;
} }
} }
module.exports = AssetSourceResolver; module.exports = AssetSourceResolver;

View File

@ -8,6 +8,7 @@
* *
* @providesModule Image * @providesModule Image
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';
@ -32,9 +33,7 @@ var merge = require('merge');
var requireNativeComponent = require('requireNativeComponent'); var requireNativeComponent = require('requireNativeComponent');
var resolveAssetSource = require('resolveAssetSource'); var resolveAssetSource = require('resolveAssetSource');
var { var {ImageLoader} = NativeModules;
ImageLoader,
} = NativeModules;
let _requestId = 1; let _requestId = 1;
function generateRequestId() { function generateRequestId() {
@ -75,14 +74,16 @@ var ImageViewAttributes = merge(ReactNativeViewAttributes.UIView, {
}); });
var ViewStyleKeys = new Set(Object.keys(ViewStylePropTypes)); var ViewStyleKeys = new Set(Object.keys(ViewStylePropTypes));
var ImageSpecificStyleKeys = new Set(Object.keys(ImageStylePropTypes).filter(x => !ViewStyleKeys.has(x))); var ImageSpecificStyleKeys = new Set(
Object.keys(ImageStylePropTypes).filter(x => !ViewStyleKeys.has(x)),
);
var Image = createReactClass({ var Image = createReactClass({
displayName: 'Image', displayName: 'Image',
propTypes: { propTypes: {
...ViewPropTypes, ...ViewPropTypes,
style: StyleSheetPropType(ImageStylePropTypes), style: StyleSheetPropType(ImageStylePropTypes),
/** /**
* `uri` is a string representing the resource identifier for the image, which * `uri` is a string representing the resource identifier for the image, which
* could be an http address, a local file path, or a static image * could be an http address, a local file path, or a static image
* resource (which should be wrapped in the `require('./path/to/image.png')` function). * resource (which should be wrapped in the `require('./path/to/image.png')` function).
@ -108,11 +109,12 @@ var Image = createReactClass({
width: PropTypes.number, width: PropTypes.number,
height: PropTypes.number, height: PropTypes.number,
headers: PropTypes.objectOf(PropTypes.string), headers: PropTypes.objectOf(PropTypes.string),
})) }),
),
]), ]),
/** /**
* blurRadius: the blur radius of the blur filter added to the image * blurRadius: the blur radius of the blur filter added to the image
*/ */
blurRadius: PropTypes.number, blurRadius: PropTypes.number,
/** /**
* similarly to `source`, this property represents the resource used to render * similarly to `source`, this property represents the resource used to render
@ -202,9 +204,12 @@ var Image = createReactClass({
.then(function(sizes) { .then(function(sizes) {
success(sizes.width, sizes.height); success(sizes.width, sizes.height);
}) })
.catch(failure || function() { .catch(
console.warn('Failed to get size for image: ' + url); failure ||
}); function() {
console.warn('Failed to get size for image: ' + url);
},
);
}, },
/** /**
@ -231,7 +236,9 @@ var Image = createReactClass({
* @return a mapping from url to cache status, such as "disk" or "memory". If a requested URL is * @return a mapping from url to cache status, such as "disk" or "memory". If a requested URL is
* not in the mapping, it means it's not in the cache. * not in the mapping, it means it's not in the cache.
*/ */
async queryCache(urls: Array<string>): Promise<Map<string, 'memory' | 'disk'>> { async queryCache(
urls: Array<string>,
): Promise<Map<string, 'memory' | 'disk'>> {
return await ImageLoader.queryCache(urls); return await ImageLoader.queryCache(urls);
}, },
@ -255,12 +262,14 @@ var Image = createReactClass({
}, },
contextTypes: { contextTypes: {
isInAParentText: PropTypes.bool isInAParentText: PropTypes.bool,
}, },
render: function() { render: function() {
const source = resolveAssetSource(this.props.source); const source = resolveAssetSource(this.props.source);
const loadingIndicatorSource = resolveAssetSource(this.props.loadingIndicatorSource); const loadingIndicatorSource = resolveAssetSource(
this.props.loadingIndicatorSource,
);
// As opposed to the ios version, here we render `null` when there is no source, source.uri // As opposed to the ios version, here we render `null` when there is no source, source.uri
// or source array. // or source array.
@ -270,11 +279,15 @@ var Image = createReactClass({
} }
if (this.props.src) { if (this.props.src) {
console.warn('The <Image> component requires a `source` property rather than `src`.'); console.warn(
'The <Image> component requires a `source` property rather than `src`.',
);
} }
if (this.props.children) { if (this.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.'); 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 (source && (source.uri || Array.isArray(source))) { if (source && (source.uri || Array.isArray(source))) {
@ -292,20 +305,27 @@ var Image = createReactClass({
const {onLoadStart, onLoad, onLoadEnd, onError} = this.props; const {onLoadStart, onLoad, onLoadEnd, onError} = this.props;
const nativeProps = merge(this.props, { const nativeProps = merge(this.props, {
style, style,
shouldNotifyLoadEvents: !!(onLoadStart || onLoad || onLoadEnd || onError), shouldNotifyLoadEvents: !!(
onLoadStart ||
onLoad ||
onLoadEnd ||
onError
),
src: sources, src: sources,
headers: source.headers, headers: source.headers,
loadingIndicatorSrc: loadingIndicatorSource ? loadingIndicatorSource.uri : null, loadingIndicatorSrc: loadingIndicatorSource
? loadingIndicatorSource.uri
: null,
}); });
if (this.context.isInAParentText) { if (this.context.isInAParentText) {
return <RCTTextInlineImage {...nativeProps}/>; return <RCTTextInlineImage {...nativeProps} />;
} else { } else {
return <RKImage {...nativeProps}/>; return <RKImage {...nativeProps} />;
} }
} }
return null; return null;
} },
}); });
var styles = StyleSheet.create({ var styles = StyleSheet.create({
@ -323,6 +343,10 @@ var cfg = {
}, },
}; };
var RKImage = requireNativeComponent('RCTImageView', Image, cfg); var RKImage = requireNativeComponent('RCTImageView', Image, cfg);
var RCTTextInlineImage = requireNativeComponent('RCTTextInlineImage', Image, cfg); var RCTTextInlineImage = requireNativeComponent(
'RCTTextInlineImage',
Image,
cfg,
);
module.exports = Image; module.exports = Image;

View File

@ -8,6 +8,7 @@
* *
* @providesModule Image * @providesModule Image
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';
@ -190,8 +191,8 @@ const Image = createReactClass({
*/ */
accessibilityLabel: PropTypes.node, accessibilityLabel: PropTypes.node,
/** /**
* blurRadius: the blur radius of the blur filter added to the image * blurRadius: the blur radius of the blur filter added to the image
*/ */
blurRadius: PropTypes.number, blurRadius: PropTypes.number,
/** /**
* When the image is resized, the corners of the size specified * When the image is resized, the corners of the size specified
@ -241,7 +242,13 @@ const Image = createReactClass({
* - `repeat`: Repeat the image to cover the frame of the view. The * - `repeat`: Repeat the image to cover the frame of the view. The
* image will keep it's size and aspect ratio. (iOS only) * image will keep it's size and aspect ratio. (iOS only)
*/ */
resizeMode: PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat', 'center']), resizeMode: PropTypes.oneOf([
'cover',
'contain',
'stretch',
'repeat',
'center',
]),
/** /**
* A unique identifier for this element to be used in UI Automation * A unique identifier for this element to be used in UI Automation
* testing scripts. * testing scripts.
@ -314,9 +321,14 @@ const Image = createReactClass({
success: (width: number, height: number) => void, success: (width: number, height: number) => void,
failure?: (error: any) => void, failure?: (error: any) => void,
) { ) {
ImageViewManager.getSize(uri, success, failure || function() { ImageViewManager.getSize(
console.warn('Failed to get size for image: ' + uri); uri,
}); success,
failure ||
function() {
console.warn('Failed to get size for image: ' + uri);
},
);
}, },
/** /**
* Prefetches a remote image for later use by downloading it to the disk * Prefetches a remote image for later use by downloading it to the disk
@ -345,11 +357,15 @@ const Image = createReactClass({
*/ */
viewConfig: { viewConfig: {
uiViewClassName: 'UIView', uiViewClassName: 'UIView',
validAttributes: ReactNativeViewAttributes.UIView validAttributes: ReactNativeViewAttributes.UIView,
}, },
render: function() { render: function() {
const source = resolveAssetSource(this.props.source) || { uri: undefined, width: undefined, height: undefined }; const source = resolveAssetSource(this.props.source) || {
uri: undefined,
width: undefined,
height: undefined,
};
let sources; let sources;
let style; let style;
@ -358,7 +374,8 @@ const Image = createReactClass({
sources = source; sources = source;
} else { } else {
const {width, height, uri} = source; const {width, height, uri} = source;
style = flattenStyle([{width, height}, styles.base, this.props.style]) || {}; style =
flattenStyle([{width, height}, styles.base, this.props.style]) || {};
sources = [source]; sources = [source];
if (uri === '') { if (uri === '') {
@ -366,15 +383,20 @@ const Image = createReactClass({
} }
} }
const resizeMode = this.props.resizeMode || (style || {}).resizeMode || 'cover'; // Workaround for flow bug t7737108 const resizeMode =
this.props.resizeMode || (style || {}).resizeMode || 'cover'; // Workaround for flow bug t7737108
const tintColor = (style || {}).tintColor; // Workaround for flow bug t7737108 const tintColor = (style || {}).tintColor; // Workaround for flow bug t7737108
if (this.props.src) { if (this.props.src) {
console.warn('The <Image> component requires a `source` property rather than `src`.'); console.warn(
'The <Image> component requires a `source` property rather than `src`.',
);
} }
if (this.props.children) { if (this.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.'); 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 ( return (

View File

@ -8,6 +8,7 @@
* *
* @providesModule ImageEditor * @providesModule ImageEditor
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';
@ -63,7 +64,7 @@ class ImageEditor {
uri: string, uri: string,
cropData: ImageCropData, cropData: ImageCropData,
success: (uri: string) => void, success: (uri: string) => void,
failure: (error: Object) => void failure: (error: Object) => void,
) { ) {
RCTImageEditingManager.cropImage(uri, cropData, success, failure); RCTImageEditingManager.cropImage(uri, cropData, success, failure);
} }

View File

@ -8,6 +8,7 @@
* *
* @providesModule ImageResizeMode * @providesModule ImageResizeMode
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';
@ -38,10 +39,10 @@ var ImageResizeMode = keyMirror({
*/ */
stretch: null, stretch: null,
/** /**
* center - The image will be scaled down such that it is completely visible, * center - The image will be scaled down such that it is completely visible,
* if bigger than the area of the view. * if bigger than the area of the view.
* The image will not be scaled up. * The image will not be scaled up.
*/ */
center: null, center: null,
/** /**

View File

@ -8,6 +8,7 @@
* *
* @providesModule ImageSource * @providesModule ImageSource
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';

View File

@ -8,6 +8,7 @@
* *
* @providesModule ImageSourcePropType * @providesModule ImageSourcePropType
* @no-flow * @no-flow
* @format
*/ */
'use strict'; 'use strict';

View File

@ -8,6 +8,7 @@
* *
* @providesModule ImageStore * @providesModule ImageStore
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';
@ -18,7 +19,7 @@ class ImageStore {
* Check if the ImageStore contains image data for the specified URI. * Check if the ImageStore contains image data for the specified URI.
* @platform ios * @platform ios
*/ */
static hasImageForTag(uri: string, callback: (hasImage: bool) => void) { static hasImageForTag(uri: string, callback: (hasImage: boolean) => void) {
if (RCTImageStoreManager.hasImageForTag) { if (RCTImageStoreManager.hasImageForTag) {
RCTImageStoreManager.hasImageForTag(uri, callback); RCTImageStoreManager.hasImageForTag(uri, callback);
} else { } else {
@ -56,7 +57,7 @@ class ImageStore {
static addImageFromBase64( static addImageFromBase64(
base64ImageData: string, base64ImageData: string,
success: (uri: string) => void, success: (uri: string) => void,
failure: (error: any) => void failure: (error: any) => void,
) { ) {
RCTImageStoreManager.addImageFromBase64(base64ImageData, success, failure); RCTImageStoreManager.addImageFromBase64(base64ImageData, success, failure);
} }
@ -75,7 +76,7 @@ class ImageStore {
static getBase64ForTag( static getBase64ForTag(
uri: string, uri: string,
success: (base64ImageData: string) => void, success: (base64ImageData: string) => void,
failure: (error: any) => void failure: (error: any) => void,
) { ) {
RCTImageStoreManager.getBase64ForTag(uri, success, failure); RCTImageStoreManager.getBase64ForTag(uri, success, failure);
} }

View File

@ -8,6 +8,7 @@
* *
* @providesModule ImageStylePropTypes * @providesModule ImageStylePropTypes
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';
@ -51,7 +52,7 @@ var ImageStylePropTypes = {
* http://frescolib.org/docs/rounded-corners-and-circles.html * http://frescolib.org/docs/rounded-corners-and-circles.html
* *
* @platform android * @platform android
*/ */
overlayColor: ReactPropTypes.string, overlayColor: ReactPropTypes.string,
// Android-Specific styles // Android-Specific styles

View File

@ -8,6 +8,7 @@
* *
* @providesModule nativeImageSource * @providesModule nativeImageSource
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';
@ -21,7 +22,7 @@ type SourceSpec = {
// http://facebook.github.io/react-native/docs/images.html#why-not-automatically-size-everything // http://facebook.github.io/react-native/docs/images.html#why-not-automatically-size-everything
width: number, width: number,
height: number, height: number,
} };
/** /**
* In hybrid apps, use `nativeImageSource` to access images that are already available * In hybrid apps, use `nativeImageSource` to access images that are already available
@ -40,7 +41,9 @@ type SourceSpec = {
function nativeImageSource(spec: SourceSpec): Object { function nativeImageSource(spec: SourceSpec): Object {
const uri = Platform.select(spec); const uri = Platform.select(spec);
if (!uri) { if (!uri) {
console.warn(`No image name given for ${Platform.OS}: ${JSON.stringify(spec)}`); console.warn(
`No image name given for ${Platform.OS}: ${JSON.stringify(spec)}`,
);
} }
return { return {