Skip to content

Commit

Permalink
Implement catalog conversion natively and add fallback
Browse files Browse the repository at this point in the history
  • Loading branch information
janicduplessis committed Oct 22, 2022
1 parent 1a87e54 commit 3894a46
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 26 deletions.
17 changes: 1 addition & 16 deletions Libraries/Image/AssetSourceResolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,6 @@ class AssetSourceResolver {
return !!(this.jsbundleUrl && this.jsbundleUrl.startsWith('file://'));
}

isCatalogAsset(): boolean {
return (
this.asset.__packager_asset &&
(this.asset.type === 'png' ||
this.asset.type === 'jpg' ||
this.asset.type === 'jpeg')
);
}

defaultAsset(): ResolvedAssetSource {
if (this.isLoadedFromServer()) {
return this.assetServerURL();
Expand All @@ -90,9 +81,7 @@ class AssetSourceResolver {
? this.drawableFolderInBundle()
: this.resourceIdentifierWithoutScale();
} else {
return this.isCatalogAsset()
? this.assetFromCatalog()
: this.scaledAssetURLNearBundle();
return this.scaledAssetURLNearBundle();
}
}

Expand Down Expand Up @@ -134,10 +123,6 @@ class AssetSourceResolver {
);
}

assetFromCatalog(): ResolvedAssetSource {
return this.fromSource(getAndroidResourceIdentifier(this.asset));
}

/**
* The default location of assets bundled with the app, located by
* resource identifier
Expand Down
4 changes: 2 additions & 2 deletions Libraries/Image/__tests__/resolveAssetSource-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ describe('resolveAssetSource', () => {
__packager_asset: true,
width: 100,
height: 200,
uri: 'module_a_logo',
uri: 'file:///Path/To/Sample.app/assets/module/a/logo.png',
scale: 1,
},
);
Expand All @@ -159,7 +159,7 @@ describe('resolveAssetSource', () => {
__packager_asset: true,
width: 100,
height: 200,
uri: '__module_a_logo',
uri: 'file:///Path/To/Sample.app/assets/__module/a/logo.png',
scale: 1,
},
);
Expand Down
3 changes: 3 additions & 0 deletions React/Base/RCTUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ RCT_EXTERN NSString *__nullable RCTLibraryPath(void);
// (or nil, if the URL does not specify a path within the Library directory)
RCT_EXTERN NSString *__nullable RCTLibraryPathForURL(NSURL *__nullable URL);

// Return the name of the asset in the catalog for a packager URL.
RCT_EXTERN NSString *__nullable RCTAssetCatalogNameForURL(NSURL *__nullable URL);

// Determines if a given image URL refers to a image in bundle
RCT_EXTERN BOOL RCTIsBundleAssetURL(NSURL *__nullable imageURL);

Expand Down
72 changes: 68 additions & 4 deletions React/Base/RCTUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -728,13 +728,66 @@ BOOL RCTIsGzippedData(NSData *__nullable data)
return RCTRelativePathForURL(RCTHomePath(), URL);
}

static BOOL RCTIsImageAssetsPath(NSString *path)
static NSRegularExpression *RCTAssetURLScaleRegex()
{
static dispatch_once_t onceToken;
static NSRegularExpression *regex;
dispatch_once(&onceToken, ^{
regex = [NSRegularExpression regularExpressionWithPattern:@"@\\dx$" options:0 error:nil];
});
return regex;
}

static NSRegularExpression *RCTAssetURLCharactersRegex()
{
static dispatch_once_t onceToken;
static NSRegularExpression *regex;
dispatch_once(&onceToken, ^{
regex = [NSRegularExpression regularExpressionWithPattern:@"[^a-z0-9_]" options:0 error:nil];
});
return regex;
}

NSString *__nullable RCTAssetCatalogNameForURL(NSURL *__nullable URL)
{
if (path == nil) {
return NO;
NSString *path = RCTBundlePathForURL(URL);
// Packager assets always start with assets/
if (path == nil || ![path hasPrefix:@"assets/"]) {
return nil;
}

// Remove extension
path = [path stringByDeletingPathExtension];

// Remove scale suffix
path = [RCTAssetURLScaleRegex() stringByReplacingMatchesInString:path
options:0
range:NSMakeRange(0, [path length])
withTemplate:@""];

path = [path lowercaseString];

// Encode folder structure in file name
path = [path stringByReplacingOccurrencesOfString:@"/" withString:@"_"];

// Remove illegal chars
path = [RCTAssetURLCharactersRegex() stringByReplacingMatchesInString:path
options:0
range:NSMakeRange(0, [path length])
withTemplate:@""];

// Remove "assets_" prefix
if ([path hasPrefix:@"assets_"]) {
path = [path substringFromIndex:@"assets_".length];
}

return path;
}

static BOOL RCTIsImageAssetsPath(NSString *path)
{
NSString *extension = [path pathExtension];
return extension.length == 0 || [extension isEqualToString:@"png"] || [extension isEqualToString:@"jpg"];
return [extension isEqualToString:@"png"] || [extension isEqualToString:@"jpg"];
}

BOOL RCTIsBundleAssetURL(NSURL *__nullable imageURL)
Expand Down Expand Up @@ -803,6 +856,17 @@ BOOL RCTIsLocalAssetURL(NSURL *__nullable imageURL)

UIImage *__nullable RCTImageFromLocalAssetURL(NSURL *imageURL)
{
NSString *catalogName = RCTAssetCatalogNameForURL(imageURL);
if (catalogName) {
UIImage *image = [UIImage imageNamed:catalogName];
if (image) {
return image;
} else {
RCTLogWarn(
@"Image %@ not found in the asset catalog. Make sure your app template is updated correctly.", catalogName);
}
}

NSString *imageName = RCTBundlePathForURL(imageURL);

NSBundle *bundle = nil;
Expand Down
Binary file not shown.
4 changes: 2 additions & 2 deletions packages/rn-tester/RNTester/RNAssets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
21 changes: 21 additions & 0 deletions packages/rn-tester/RNTesterUnitTests/RCTURLUtilsTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,25 @@ - (void)testIsLocalAssetsURLParam
XCTAssertFalse(RCTIsLocalAssetURL(otherAssetsURL));
}

- (void)testAssetCatalogNameForURL
{
NSString *validAssetPath =
[NSString stringWithFormat:@"file://%@/assets/AwesomeModule/icon@2x.png", [[NSBundle mainBundle] resourcePath]];
NSString *result = RCTAssetCatalogNameForURL([NSURL URLWithString:validAssetPath]);
XCTAssertEqualObjects(result, @"awesomemodule_icon");

NSString *validAssetNoScalePath =
[NSString stringWithFormat:@"file://%@/assets/AwesomeModule/icon.png", [[NSBundle mainBundle] resourcePath]];
result = RCTAssetCatalogNameForURL([NSURL URLWithString:validAssetNoScalePath]);
XCTAssertEqualObjects(result, @"awesomemodule_icon");

NSString *notPackagerAssetPath =
[NSString stringWithFormat:@"file://%@/icon.png", [[NSBundle mainBundle] resourcePath]];
result = RCTAssetCatalogNameForURL([NSURL URLWithString:notPackagerAssetPath]);
XCTAssertNil(result);

result = RCTAssetCatalogNameForURL(nil);
XCTAssertNil(result);
}

@end
4 changes: 2 additions & 2 deletions template/ios/HelloWorld/RNAssets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}

0 comments on commit 3894a46

Please sign in to comment.