Skip to content

Commit

Permalink
Load XML files on disk by default (facebook#46371)
Browse files Browse the repository at this point in the history
Summary:
X-link: facebook/metro#1348

Pull Request resolved: facebook#46371

## Internal

Vector drawable image support was added in D59530172 but importing vector drawable asset types was not supported out of the box. It required custom source transformers like the one added in D60021474. This is because Android cannot load vector drawable XML over the network. Vector drawables are compiled by AAPT as part of the build process. Even though Metro can serve XML, it would never load.

## Summary

This adds some minor checks in the `AssetSourceResolver` to only attempt loading XML asset types from disk on the Android platform. XML assets like vector drawables are precompiled and cannot be served over the network by Metro.

## Changelog

[Android] [Added] - Adds support for importing XML assets as images

Differential Revision: D62302929
  • Loading branch information
Abbondanzo authored and facebook-github-bot committed Sep 6, 2024
1 parent 0c90cfc commit 14459d0
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 12 deletions.
2 changes: 1 addition & 1 deletion packages/assets/path-support.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
14 changes: 13 additions & 1 deletion packages/react-native/Libraries/Image/AssetSourceResolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ function getAssetPathInDrawableFolder(asset: PackagerAsset): string {
return drawableFolder + '/' + fileName + '.' + asset.type;
}

/**
* Returns true if the asset should only be loaded from the file system since
* it cannot be served over the network.
*/
function shouldAssetOnlyLoadFromFileSystem(asset: PackagerAsset): boolean {
return asset.type === 'xml' && Platform.OS === 'android';
}

class AssetSourceResolver {
serverUrl: ?string;
// where the jsbundle is being run from
Expand All @@ -67,7 +75,11 @@ class AssetSourceResolver {
}

isLoadedFromServer(): boolean {
return !!this.serverUrl;
return (
this.serverUrl != null &&
this.serverUrl !== '' &&
!shouldAssetOnlyLoadFromFileSystem(this.asset)
);
}

isLoadedFromFileSystem(): boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
24 changes: 14 additions & 10 deletions packages/rn-tester/js/examples/Image/ImageExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -618,7 +612,9 @@ class VectorDrawableExample extends React.Component<
return (
<View style={styles.flex}>
<Text>Enabled: {isEnabled ? 'true' : 'false'}</Text>
<Image source={{uri: 'ic_android'}} style={{height: 64, width: 64}} />
<View style={styles.vectorDrawableRow}>
<Image source={{uri: 'ic_android'}} style={styles.vectorDrawable} />
</View>
</View>
);
}
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 14459d0

Please sign in to comment.