From c6ad7b85d1c67dd85ebc659f6560d061e1ade2d2 Mon Sep 17 00:00:00 2001 From: Alex Kotliarskyi Date: Tue, 21 Apr 2015 10:48:54 -0700 Subject: [PATCH] [ReactNative] Use network image for new image assets --- Libraries/Image/Image.ios.js | 20 +++-- .../__tests__/resolveAssetSource-test.js | 76 +++++++++++++++++++ Libraries/Image/resolveAssetSource.js | 66 ++++++++++++++++ 3 files changed, 155 insertions(+), 7 deletions(-) create mode 100644 Libraries/Image/__tests__/resolveAssetSource-test.js create mode 100644 Libraries/Image/resolveAssetSource.js diff --git a/Libraries/Image/Image.ios.js b/Libraries/Image/Image.ios.js index d519c1ac5..be95a3f3f 100644 --- a/Libraries/Image/Image.ios.js +++ b/Libraries/Image/Image.ios.js @@ -12,11 +12,11 @@ 'use strict'; var EdgeInsetsPropType = require('EdgeInsetsPropType'); +var ImageResizeMode = require('ImageResizeMode'); +var ImageStylePropTypes = require('ImageStylePropTypes'); var NativeMethodsMixin = require('NativeMethodsMixin'); var NativeModules = require('NativeModules'); var PropTypes = require('ReactPropTypes'); -var ImageResizeMode = require('ImageResizeMode'); -var ImageStylePropTypes = require('ImageStylePropTypes'); var React = require('React'); var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); var StyleSheet = require('StyleSheet'); @@ -26,8 +26,9 @@ var flattenStyle = require('flattenStyle'); var invariant = require('invariant'); var merge = require('merge'); var requireNativeComponent = require('requireNativeComponent'); -var warning = require('warning'); +var resolveAssetSource = require('resolveAssetSource'); var verifyPropTypes = require('verifyPropTypes'); +var warning = require('warning'); /** * A react component for displaying different types of images, @@ -122,10 +123,15 @@ var Image = React.createClass({ 'not be set directly on Image.'); } } - var style = flattenStyle([styles.base, this.props.style]); - invariant(style, "style must be initialized"); var source = this.props.source; - invariant(source, "source must be initialized"); + invariant(source, 'source must be initialized'); + + var {width, height} = source; + var style = flattenStyle([{width, height}, styles.base, this.props.style]); + invariant(style, 'style must be initialized'); + + source = resolveAssetSource(source); + var isNetwork = source.uri && source.uri.match(/^https?:/); invariant( !(isNetwork && source.isStatic), @@ -171,8 +177,8 @@ var styles = StyleSheet.create({ }, }); -var RCTStaticImage = requireNativeComponent('RCTStaticImage', null); var RCTNetworkImage = requireNativeComponent('RCTNetworkImageView', null); +var RCTStaticImage = requireNativeComponent('RCTStaticImage', null); var nativeOnlyProps = { src: true, diff --git a/Libraries/Image/__tests__/resolveAssetSource-test.js b/Libraries/Image/__tests__/resolveAssetSource-test.js new file mode 100644 index 000000000..69bcb116a --- /dev/null +++ b/Libraries/Image/__tests__/resolveAssetSource-test.js @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +'use strict'; + +jest.dontMock('../resolveAssetSource'); + +var resolveAssetSource; +var SourceCode; + +describe('resolveAssetSource', () => { + beforeEach(() => { + jest.resetModuleRegistry(); + SourceCode = require('NativeModules').SourceCode; + resolveAssetSource = require('../resolveAssetSource'); + }); + + it('returns same source for simple static and network images', () => { + var source1 = {uri: 'https://www.facebook.com/logo'}; + expect(resolveAssetSource(source1)).toBe(source1); + + var source2 = {isStatic: true, uri: 'logo'}; + expect(resolveAssetSource(source2)).toBe(source2); + }); + + describe('bundle was loaded from network', () => { + beforeEach(() => { + SourceCode.scriptURL = 'http://10.0.0.1:8081/main.bundle'; + }); + + it('uses network image', () => { + var source = { + path: '/Users/react/project/logo.png', + uri: 'assets/logo.png', + }; + expect(resolveAssetSource(source)).toEqual({ + isStatic: false, + uri: 'http://10.0.0.1:8081/assets/logo.png', + }); + }); + + it('does not change deprecated assets', () => { + // Deprecated require('image!logo') should stay unchanged + var source = { + path: '/Users/react/project/logo.png', + uri: 'logo', + deprecated: true, + }; + expect(resolveAssetSource(source)).toEqual({ + isStatic: true, + uri: 'logo', + }); + }); + }); + + describe('bundle was loaded from file', () => { + it('uses pre-packed image', () => { + SourceCode.scriptURL = 'file:///Path/To/Simulator/main.bundle'; + + var source = { + path: '/Users/react/project/logo.png', + uri: 'assets/logo.png', + }; + expect(resolveAssetSource(source)).toEqual({ + isStatic: true, + uri: 'assets/logo.png', + }); + }); + }); + +}); diff --git a/Libraries/Image/resolveAssetSource.js b/Libraries/Image/resolveAssetSource.js new file mode 100644 index 000000000..137f92f1c --- /dev/null +++ b/Libraries/Image/resolveAssetSource.js @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule resolveAssetSource + */ +'use strict'; + +var SourceCode = require('NativeModules').SourceCode; + +var _serverURL; + +function getServerURL() { + if (_serverURL === undefined) { + var scriptURL = SourceCode.scriptURL; + var serverURLMatch = scriptURL && scriptURL.match(/^https?:\/\/.*?\//); + if (serverURLMatch) { + _serverURL = serverURLMatch[0]; + } else { + _serverURL = null; + } + } + + return _serverURL; +} + +// TODO(frantic): +// * Use something other than `path`/`isStatic` for asset identification, `__packager_asset`? +// * Add cache invalidating hashsum +// * Move code that selects scale to client +function resolveAssetSource(source) { + if (source.deprecated) { + return { + ...source, + path: undefined, + isStatic: true, + deprecated: undefined, + }; + } + + var serverURL = getServerURL(); + if (source.path) { + if (serverURL) { + return { + ...source, + path: undefined, + uri: serverURL + source.uri, + isStatic: false, + }; + } else { + return { + ...source, + path: undefined, + isStatic: true, + }; + } + } + + return source; +} + +module.exports = resolveAssetSource;