diff --git a/packages/assets/path-support.js b/packages/assets/path-support.js index 7d9388ad12567b..4ea50760fcd070 100644 --- a/packages/assets/path-support.js +++ b/packages/assets/path-support.js @@ -78,7 +78,7 @@ function getAndroidResourceIdentifier(asset: PackagerAsset): string { .toLowerCase() .replace(/\//g, '_') // Encode folder structure in file name .replace(/([^a-z0-9_])/g, '') // Remove illegal chars - .replace(/^assets_/, ''); // Remove "assets_" prefix + .replace(/^(?:assets|assetsunstable_path)_/, ''); // Remove "assets_" or "assetsunstable_path_" prefix } function getBasePath(asset: PackagerAsset): string { diff --git a/packages/react-native/Libraries/Image/AssetSourceResolver.js b/packages/react-native/Libraries/Image/AssetSourceResolver.js index e279212b49e5e5..c37fbe1fceb5e3 100644 --- a/packages/react-native/Libraries/Image/AssetSourceResolver.js +++ b/packages/react-native/Libraries/Image/AssetSourceResolver.js @@ -53,6 +53,13 @@ function getAssetPathInDrawableFolder(asset: PackagerAsset): string { return drawableFolder + '/' + fileName + '.' + asset.type; } +/** + * Returns true if the asset can be loaded over the network. + */ +function assetSupportsNetworkLoads(asset: PackagerAsset): boolean { + return !(asset.type === 'xml' && Platform.OS === 'android'); +} + class AssetSourceResolver { serverUrl: ?string; // where the jsbundle is being run from @@ -67,7 +74,11 @@ class AssetSourceResolver { } isLoadedFromServer(): boolean { - return !!this.serverUrl; + return ( + this.serverUrl != null && + this.serverUrl !== '' && + assetSupportsNetworkLoads(this.asset) + ); } isLoadedFromFileSystem(): boolean { diff --git a/packages/react-native/Libraries/Image/__tests__/resolveAssetSource-test.js b/packages/react-native/Libraries/Image/__tests__/resolveAssetSource-test.js index 3058f7154048ce..e924b3dc61c38f 100644 --- a/packages/react-native/Libraries/Image/__tests__/resolveAssetSource-test.js +++ b/packages/react-native/Libraries/Image/__tests__/resolveAssetSource-test.js @@ -109,6 +109,29 @@ describe('resolveAssetSource', () => { }, ); }); + + it('respects query parameters', () => { + expectResolvesAsset( + { + __packager_asset: true, + fileSystemLocation: '/root/app/assets/module/a', + httpServerLocation: '/assets?unstable_path=./module/a', + width: 100, + height: 200, + scales: [1, 2, 3], + hash: '5b6f00f', + name: 'logo', + type: 'png', + }, + { + __packager_asset: true, + width: 100, + height: 200, + uri: 'http://10.0.0.1:8081/assets?unstable_path=./module/a/logo@2x.png?platform=ios&hash=5b6f00f', + scale: 2, + }, + ); + }); }); describe('bundle was loaded from file on iOS', () => { diff --git a/packages/rn-tester/js/examples/Image/ImageExample.js b/packages/rn-tester/js/examples/Image/ImageExample.js index 610b84fc5b4385..13656e1aee8603 100644 --- a/packages/rn-tester/js/examples/Image/ImageExample.js +++ b/packages/rn-tester/js/examples/Image/ImageExample.js @@ -14,15 +14,9 @@ import type {LayoutEvent} from 'react-native/Libraries/Types/CoreEventTypes'; import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags'; -const ImageCapInsetsExample = require('./ImageCapInsetsExample'); -const React = require('react'); -const { - Image, - ImageBackground, - StyleSheet, - Text, - View, -} = require('react-native'); +import ImageCapInsetsExample from './ImageCapInsetsExample'; +import React from 'react'; +import {Image, ImageBackground, StyleSheet, Text, View} from 'react-native'; const IMAGE1 = 'https://www.facebook.com/assets/fb_lite_messaging/E2EE-settings@3x.png'; @@ -618,7 +612,9 @@ class VectorDrawableExample extends React.Component< return ( Enabled: {isEnabled ? 'true' : 'false'} - + + + ); } @@ -849,6 +845,14 @@ const styles = StyleSheet.create({ experimental_boxShadow: '80px 0px 10px 0px hotpink', transform: 'rotate(-15deg)', }, + vectorDrawableRow: { + flexDirection: 'row', + gap: 8, + }, + vectorDrawable: { + height: 64, + width: 64, + }, }); exports.displayName = (undefined: ?string);