Skip to content

Commit ffb3026

Browse files
committed
[ReactNative] Pick correct assets depending on device scale
1 parent b2e8dc9 commit ffb3026

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

Libraries/Image/__tests__/resolveAssetSource-test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,25 @@ describe('resolveAssetSource', () => {
5656
});
5757
});
5858

59+
it('picks matching scale', () => {
60+
expectResolvesAsset({
61+
__packager_asset: true,
62+
fileSystemLocation: '/root/app/module/a',
63+
httpServerLocation: '/assets/module/a',
64+
width: 100,
65+
height: 200,
66+
scales: [1, 2, 3],
67+
hash: '5b6f00f',
68+
name: 'logo',
69+
type: 'png',
70+
}, {
71+
isStatic: false,
72+
width: 100,
73+
height: 200,
74+
uri: 'http://10.0.0.1:8081/assets/module/a/logo@2x.png?hash=5b6f00f',
75+
});
76+
});
77+
5978
it('does not change deprecated assets', () => {
6079
expectResolvesAsset({
6180
__packager_asset: true,
@@ -103,3 +122,14 @@ describe('resolveAssetSource', () => {
103122
});
104123

105124
});
125+
126+
describe('resolveAssetSource.pickScale', () => {
127+
it('picks matching scale', () => {
128+
expect(resolveAssetSource.pickScale([1], 2)).toBe(1);
129+
expect(resolveAssetSource.pickScale([1, 2, 3], 2)).toBe(2);
130+
expect(resolveAssetSource.pickScale([1, 2], 3)).toBe(2);
131+
expect(resolveAssetSource.pickScale([1, 2, 3, 4], 3.5)).toBe(4);
132+
expect(resolveAssetSource.pickScale([3, 4], 2)).toBe(3);
133+
expect(resolveAssetSource.pickScale([], 2)).toBe(1);
134+
});
135+
});

Libraries/Image/resolveAssetSource.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111
'use strict';
1212

13+
var PixelRatio = require('PixelRatio');
1314
var SourceCode = require('NativeModules').SourceCode;
1415

1516
var _serverURL;
@@ -28,6 +29,20 @@ function getServerURL() {
2829
return _serverURL;
2930
}
3031

32+
function pickScale(scales, deviceScale) {
33+
// Packager guarantees that `scales` array is sorted
34+
for (var i = 0; i < scales.length; i++) {
35+
if (scales[i] >= deviceScale) {
36+
return scales[i];
37+
}
38+
}
39+
40+
// If nothing matches, device scale is larger than any available
41+
// scales, so we return the biggest one. Unless the array is empty,
42+
// in which case we default to 1
43+
return scales[scales.length - 1] || 1;
44+
}
45+
3146
// TODO(frantic):
3247
// * Pick best scale and append @Nx to file path
3348
// * We are currently using httpServerLocation for both http and in-app bundle
@@ -57,20 +72,24 @@ function resolveAssetSource(source) {
5772
path = path.substr(1);
5873
}
5974

75+
var scale = pickScale(source.scales, PixelRatio.get());
76+
var scaleSuffix = scale === 1 ? '' : '@' + scale + 'x';
77+
78+
var fileName = source.name + scaleSuffix + '.' + source.type;
6079
var serverURL = getServerURL();
6180
if (serverURL) {
6281
return {
6382
width: source.width,
6483
height: source.height,
65-
uri: serverURL + path + '/' + source.name + '.' + source.type +
84+
uri: serverURL + path + '/' + fileName +
6685
'?hash=' + source.hash,
6786
isStatic: false,
6887
};
6988
} else {
7089
return {
7190
width: source.width,
7291
height: source.height,
73-
uri: path + '/' + source.name + '.' + source.type,
92+
uri: path + '/' + fileName,
7493
isStatic: true,
7594
};
7695
}
@@ -79,3 +98,4 @@ function resolveAssetSource(source) {
7998
}
8099

81100
module.exports = resolveAssetSource;
101+
module.exports.pickScale = pickScale;

0 commit comments

Comments
 (0)