diff --git a/Libraries/Image/AssetSourceResolver.js b/Libraries/Image/AssetSourceResolver.js index 2183d1a98..a240b5af7 100644 --- a/Libraries/Image/AssetSourceResolver.js +++ b/Libraries/Image/AssetSourceResolver.js @@ -52,12 +52,19 @@ class AssetSourceResolver { serverUrl: ?string; // where the jsbundle is being run from jsbundleUrl: ?string; + // where the embedded bundle in the app is stored + embeddedBundleUrl: ?string; // the asset to resolve asset: PackagerAsset; - constructor(serverUrl: ?string, jsbundleUrl: ?string, asset: PackagerAsset) { + constructor(serverUrl: ?string, + jsbundleUrl: ?string, + embeddedBundleUrl: ?string, + asset: PackagerAsset + ) { this.serverUrl = serverUrl; this.jsbundleUrl = jsbundleUrl; + this.embeddedBundleUrl = embeddedBundleUrl; this.asset = asset; } @@ -69,6 +76,10 @@ class AssetSourceResolver { return !!this.jsbundleUrl; } + canLoadFromEmbeddedBundledLocation(): boolean { + return !!this.embeddedBundleUrl; + } + defaultAsset(): ResolvedAssetSource { if (this.isLoadedFromServer()) { return this.assetServerURL(); @@ -112,6 +123,15 @@ class AssetSourceResolver { return this.fromSource(path + getScaledAssetPath(this.asset)); } + /** + * Resolves to the asset that was bundled with the app, with a scaled asset filename + * E.g. 'file:///sdcard/bundle/assets/AwesomeModule/icon@2x.png' + */ + scaledAssetURLInEmbeddedBundleUrl(): ResolvedAssetSource { + const path = this.embeddedBundleUrl || 'file://'; + return this.fromSource(path + getScaledAssetPath(this.asset)); + } + /** * The default location of assets bundled with the app, located by * resource identifier diff --git a/Libraries/Image/resolveAssetSource.js b/Libraries/Image/resolveAssetSource.js index 18350ce2c..aba63045e 100644 --- a/Libraries/Image/resolveAssetSource.js +++ b/Libraries/Image/resolveAssetSource.js @@ -19,7 +19,7 @@ const NativeModules = require('NativeModules'); import type { ResolvedAssetSource } from 'AssetSourceResolver'; -let _customSourceTransformer, _serverURL, _scriptURL; +let _customSourceTransformer, _serverURL, _scriptURL, _embeddedBundleURL; function getDevServerURL(): ?string { if (_serverURL === undefined) { @@ -36,30 +36,38 @@ function getDevServerURL(): ?string { return _serverURL; } -function getScriptURL(): ?string { - if (_scriptURL === undefined) { - const scriptURL = NativeModules.SourceCode.scriptURL; - if (!scriptURL) { - // scriptURL is falsy, we have nothing to go on here - _scriptURL = null; - return _scriptURL; - } +function _coerceLocalScriptURL(scriptURL: ?string): ?string { + if (scriptURL) { if (scriptURL.startsWith('assets://')) { // android: running from within assets, no offline path to use - _scriptURL = null; - return _scriptURL; + return null; } - _scriptURL = scriptURL.substring(0, scriptURL.lastIndexOf('/') + 1); + scriptURL = scriptURL.substring(0, scriptURL.lastIndexOf('/') + 1); if (!scriptURL.startsWith('file://')) { // Add file protocol in case we have an absolute file path and not a URL. // This shouldn't really be necessary. scriptURL should be a URL. - _scriptURL = 'file://' + _scriptURL; + scriptURL = 'file://' + scriptURL; } } + return scriptURL; +} +function getScriptURL(): ?string { + if (_scriptURL === undefined) { + const scriptURL = NativeModules.SourceCode.scriptURL; + _scriptURL = _coerceLocalScriptURL(scriptURL); + } return _scriptURL; } +function getEmbeddedBundledURL(): ?string { + if (_embeddedBundleURL === undefined) { + const scriptURL = NativeModules.SourceCode.embeddedBundleURL; + _embeddedBundleURL = _coerceLocalScriptURL(scriptURL); + } + return _embeddedBundleURL; +} + function setCustomSourceTransformer( transformer: (resolver: AssetSourceResolver) => ResolvedAssetSource, ): void { @@ -80,7 +88,12 @@ function resolveAssetSource(source: any): ?ResolvedAssetSource { return null; } - const resolver = new AssetSourceResolver(getDevServerURL(), getScriptURL(), asset); + const resolver = new AssetSourceResolver( + getDevServerURL(), + getScriptURL(), + getEmbeddedBundledURL(), + asset, + ); if (_customSourceTransformer) { return _customSourceTransformer(resolver); }