Merge pull request #1375 from vjeux/Updates_Fri_22_May
Updates fri 22 may
This commit is contained in:
commit
4673dca0b0
|
@ -13,6 +13,7 @@
|
||||||
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341802B1AA91779003F314A /* libRCTNetwork.a */; };
|
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341802B1AA91779003F314A /* libRCTNetwork.a */; };
|
||||||
134454601AAFCABD003F0779 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1344545A1AAFCAAE003F0779 /* libRCTAdSupport.a */; };
|
134454601AAFCABD003F0779 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1344545A1AAFCAAE003F0779 /* libRCTAdSupport.a */; };
|
||||||
134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 134A8A251AACED6A00945AAE /* libRCTGeolocation.a */; };
|
134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 134A8A251AACED6A00945AAE /* libRCTGeolocation.a */; };
|
||||||
|
1353F5461B0E64F9009B4FAC /* ClippingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1353F5451B0E64F9009B4FAC /* ClippingTests.m */; };
|
||||||
139FDEDB1B0651FB00C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDED91B0651EA00C62182 /* libRCTWebSocket.a */; };
|
139FDEDB1B0651FB00C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDED91B0651EA00C62182 /* libRCTWebSocket.a */; };
|
||||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||||
|
@ -129,6 +130,7 @@
|
||||||
134180261AA91779003F314A /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = "<group>"; };
|
134180261AA91779003F314A /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = "<group>"; };
|
||||||
134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = ../../Libraries/AdSupport/RCTAdSupport.xcodeproj; sourceTree = "<group>"; };
|
134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = ../../Libraries/AdSupport/RCTAdSupport.xcodeproj; sourceTree = "<group>"; };
|
||||||
134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../../Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = "<group>"; };
|
134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../../Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = "<group>"; };
|
||||||
|
1353F5451B0E64F9009B4FAC /* ClippingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ClippingTests.m; sourceTree = "<group>"; };
|
||||||
139FDECA1B0651EA00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../../Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = "<group>"; };
|
139FDECA1B0651EA00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../../Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = "<group>"; };
|
||||||
13B07F961A680F5B00A75B9A /* UIExplorer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIExplorer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
13B07F961A680F5B00A75B9A /* UIExplorer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIExplorer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = UIExplorer/AppDelegate.h; sourceTree = "<group>"; };
|
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = UIExplorer/AppDelegate.h; sourceTree = "<group>"; };
|
||||||
|
@ -179,6 +181,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
004D28A21AAF61C70097A701 /* UIExplorerTests.m */,
|
004D28A21AAF61C70097A701 /* UIExplorerTests.m */,
|
||||||
|
1353F5451B0E64F9009B4FAC /* ClippingTests.m */,
|
||||||
004D28A01AAF61C70097A701 /* Supporting Files */,
|
004D28A01AAF61C70097A701 /* Supporting Files */,
|
||||||
);
|
);
|
||||||
path = UIExplorerTests;
|
path = UIExplorerTests;
|
||||||
|
@ -575,6 +578,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
004D28A31AAF61C70097A701 /* UIExplorerTests.m in Sources */,
|
004D28A31AAF61C70097A701 /* UIExplorerTests.m in Sources */,
|
||||||
|
1353F5461B0E64F9009B4FAC /* ClippingTests.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
/**
|
||||||
|
* The examples provided by Facebook are for non-commercial testing and
|
||||||
|
* evaluation purposes only.
|
||||||
|
*
|
||||||
|
* Facebook reserves all rights not expressly granted.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <CoreGraphics/CoreGraphics.h>
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <UIKit/UIView.h>
|
||||||
|
#import <XCTest/XCTest.h>
|
||||||
|
|
||||||
|
extern CGRect RCTClipRect(CGSize contentSize, CGFloat contentScale,
|
||||||
|
CGSize targetSize, CGFloat targetScale,
|
||||||
|
UIViewContentMode resizeMode);
|
||||||
|
|
||||||
|
#define RCTAssertEqualPoints(a, b) { \
|
||||||
|
XCTAssertEqual(a.x, b.x); \
|
||||||
|
XCTAssertEqual(a.y, b.y); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RCTAssertEqualSizes(a, b) { \
|
||||||
|
XCTAssertEqual(a.width, b.width); \
|
||||||
|
XCTAssertEqual(a.height, b.height); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RCTAssertEqualRects(a, b) { \
|
||||||
|
RCTAssertEqualPoints(a.origin, b.origin); \
|
||||||
|
RCTAssertEqualSizes(a.size, b.size); \
|
||||||
|
}
|
||||||
|
|
||||||
|
@interface ClippingTests : XCTestCase
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ClippingTests
|
||||||
|
|
||||||
|
- (void)testLandscapeSourceLandscapeTarget
|
||||||
|
{
|
||||||
|
CGSize content = {1000, 100};
|
||||||
|
CGSize target = {100, 20};
|
||||||
|
|
||||||
|
{
|
||||||
|
CGRect expected = {CGPointZero, {100, 20}};
|
||||||
|
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleToFill);
|
||||||
|
RCTAssertEqualRects(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CGRect expected = {CGPointZero, {100, 10}};
|
||||||
|
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFit);
|
||||||
|
RCTAssertEqualRects(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CGRect expected = {{-50, 0}, {200, 20}};
|
||||||
|
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFill);
|
||||||
|
RCTAssertEqualRects(expected, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testPortraitSourceLandscapeTarget
|
||||||
|
{
|
||||||
|
CGSize content = {10, 100};
|
||||||
|
CGSize target = {100, 20};
|
||||||
|
|
||||||
|
{
|
||||||
|
CGRect expected = {CGPointZero, {10, 20}};
|
||||||
|
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleToFill);
|
||||||
|
RCTAssertEqualRects(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CGRect expected = {CGPointZero, {2, 20}};
|
||||||
|
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFit);
|
||||||
|
RCTAssertEqualRects(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CGRect expected = {{0, -49}, {10, 100}};
|
||||||
|
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFill);
|
||||||
|
RCTAssertEqualRects(expected, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testPortraitSourcePortraitTarget
|
||||||
|
{
|
||||||
|
CGSize content = {10, 100};
|
||||||
|
CGSize target = {20, 50};
|
||||||
|
|
||||||
|
{
|
||||||
|
CGRect expected = {CGPointZero, {10, 50}};
|
||||||
|
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleToFill);
|
||||||
|
RCTAssertEqualRects(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CGRect expected = {CGPointZero, {5, 50}};
|
||||||
|
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFit);
|
||||||
|
RCTAssertEqualRects(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CGRect expected = {{0, -37.5}, {10, 100}};
|
||||||
|
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFill);
|
||||||
|
RCTAssertEqualRects(expected, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testScaling
|
||||||
|
{
|
||||||
|
CGSize content = {2, 2};
|
||||||
|
CGSize target = {3, 3};
|
||||||
|
|
||||||
|
CGRect expected = {CGPointZero, {3, 3}};
|
||||||
|
CGRect result = RCTClipRect(content, 2, target, 1, UIViewContentModeScaleToFill);
|
||||||
|
RCTAssertEqualRects(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -1298,6 +1298,14 @@ var Navigator = React.createClass({
|
||||||
if (i !== this.state.presentedIndex) {
|
if (i !== this.state.presentedIndex) {
|
||||||
disabledSceneStyle = styles.disabledScene;
|
disabledSceneStyle = styles.disabledScene;
|
||||||
}
|
}
|
||||||
|
var originalRef = child.ref;
|
||||||
|
if (originalRef != null && typeof originalRef !== 'function') {
|
||||||
|
console.warn(
|
||||||
|
'String refs are not supported for navigator scenes. Use a callback ' +
|
||||||
|
'ref instead. Ignoring ref: ' + originalRef
|
||||||
|
);
|
||||||
|
originalRef = null;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
key={this.state.idStack[i]}
|
key={this.state.idStack[i]}
|
||||||
|
@ -1307,7 +1315,12 @@ var Navigator = React.createClass({
|
||||||
}}
|
}}
|
||||||
style={[styles.baseScene, this.props.sceneStyle, disabledSceneStyle]}>
|
style={[styles.baseScene, this.props.sceneStyle, disabledSceneStyle]}>
|
||||||
{React.cloneElement(child, {
|
{React.cloneElement(child, {
|
||||||
ref: this._handleItemRef.bind(null, this.state.idStack[i], route),
|
ref: component => {
|
||||||
|
this._handleItemRef(this.state.idStack[i], route, component);
|
||||||
|
if (originalRef) {
|
||||||
|
originalRef(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
})}
|
})}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -33,6 +33,8 @@ typedef void (^RCTImageDownloadBlock)(UIImage *image, NSError *error);
|
||||||
- (id)downloadImageForURL:(NSURL *)url
|
- (id)downloadImageForURL:(NSURL *)url
|
||||||
size:(CGSize)size
|
size:(CGSize)size
|
||||||
scale:(CGFloat)scale
|
scale:(CGFloat)scale
|
||||||
|
resizeMode:(UIViewContentMode)resizeMode
|
||||||
|
backgroundColor:(UIColor *)backgroundColor
|
||||||
block:(RCTImageDownloadBlock)block;
|
block:(RCTImageDownloadBlock)block;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#import "RCTImageDownloader.h"
|
#import "RCTImageDownloader.h"
|
||||||
|
|
||||||
#import "RCTCache.h"
|
#import "RCTCache.h"
|
||||||
|
#import "RCTLog.h"
|
||||||
#import "RCTUtils.h"
|
#import "RCTUtils.h"
|
||||||
|
|
||||||
typedef void (^RCTCachedDataDownloadBlock)(BOOL cached, NSData *data, NSError *error);
|
typedef void (^RCTCachedDataDownloadBlock)(BOOL cached, NSData *data, NSError *error);
|
||||||
|
@ -121,34 +122,134 @@ static NSString *RCTCacheKeyForURL(NSURL *url)
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)downloadImageForURL:(NSURL *)url size:(CGSize)size
|
/**
|
||||||
scale:(CGFloat)scale block:(RCTImageDownloadBlock)block
|
* Returns the optimal context size for an image drawn using the clip rect
|
||||||
|
* returned by RCTClipRect.
|
||||||
|
*/
|
||||||
|
CGSize RCTTargetSizeForClipRect(CGRect);
|
||||||
|
CGSize RCTTargetSizeForClipRect(CGRect clipRect)
|
||||||
|
{
|
||||||
|
return (CGSize){
|
||||||
|
clipRect.size.width + clipRect.origin.x * 2,
|
||||||
|
clipRect.size.height + clipRect.origin.y * 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function takes an input content size & scale (typically from an image),
|
||||||
|
* a target size & scale that it will be drawn into (typically a CGContext) and
|
||||||
|
* then calculates the optimal rectangle to draw the image into so that it will
|
||||||
|
* be sized and positioned correctly if drawn using the specified content mode.
|
||||||
|
*/
|
||||||
|
CGRect RCTClipRect(CGSize, CGFloat, CGSize, CGFloat, UIViewContentMode);
|
||||||
|
CGRect RCTClipRect(CGSize sourceSize, CGFloat sourceScale,
|
||||||
|
CGSize destSize, CGFloat destScale,
|
||||||
|
UIViewContentMode resizeMode)
|
||||||
|
{
|
||||||
|
// Precompensate for scale
|
||||||
|
CGFloat scale = sourceScale / destScale;
|
||||||
|
sourceSize.width *= scale;
|
||||||
|
sourceSize.height *= scale;
|
||||||
|
|
||||||
|
// Calculate aspect ratios if needed (don't bother is resizeMode == stretch)
|
||||||
|
CGFloat aspect = 0.0, targetAspect = 0.0;
|
||||||
|
if (resizeMode != UIViewContentModeScaleToFill) {
|
||||||
|
aspect = sourceSize.width / sourceSize.height;
|
||||||
|
targetAspect = destSize.width / destSize.height;
|
||||||
|
if (aspect == targetAspect) {
|
||||||
|
resizeMode = UIViewContentModeScaleToFill;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (resizeMode) {
|
||||||
|
case UIViewContentModeScaleToFill: // stretch
|
||||||
|
|
||||||
|
sourceSize.width = MIN(destSize.width, sourceSize.width);
|
||||||
|
sourceSize.height = MIN(destSize.height, sourceSize.height);
|
||||||
|
return (CGRect){CGPointZero, sourceSize};
|
||||||
|
|
||||||
|
case UIViewContentModeScaleAspectFit: // contain
|
||||||
|
|
||||||
|
if (targetAspect <= aspect) { // target is taller than content
|
||||||
|
sourceSize.width = destSize.width = MIN(sourceSize.width, destSize.width);
|
||||||
|
sourceSize.height = sourceSize.width / aspect;
|
||||||
|
} else { // target is wider than content
|
||||||
|
sourceSize.height = destSize.height = MIN(sourceSize.height, destSize.height);
|
||||||
|
sourceSize.width = sourceSize.height * aspect;
|
||||||
|
}
|
||||||
|
return (CGRect){CGPointZero, sourceSize};
|
||||||
|
|
||||||
|
case UIViewContentModeScaleAspectFill: // cover
|
||||||
|
|
||||||
|
if (targetAspect <= aspect) { // target is taller than content
|
||||||
|
|
||||||
|
sourceSize.height = destSize.height = MIN(sourceSize.height, destSize.height);
|
||||||
|
sourceSize.width = sourceSize.height * aspect;
|
||||||
|
destSize.width = destSize.height * targetAspect;
|
||||||
|
return (CGRect){{(destSize.width - sourceSize.width) / 2, 0}, sourceSize};
|
||||||
|
|
||||||
|
} else { // target is wider than content
|
||||||
|
|
||||||
|
sourceSize.width = destSize.width = MIN(sourceSize.width, destSize.width);
|
||||||
|
sourceSize.height = sourceSize.width / aspect;
|
||||||
|
destSize.height = destSize.width / targetAspect;
|
||||||
|
return (CGRect){{0, (destSize.height - sourceSize.height) / 2}, sourceSize};
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
RCTLogError(@"A resizeMode value of %zd is not supported", resizeMode);
|
||||||
|
return (CGRect){CGPointZero, destSize};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)downloadImageForURL:(NSURL *)url
|
||||||
|
size:(CGSize)size
|
||||||
|
scale:(CGFloat)scale
|
||||||
|
resizeMode:(UIViewContentMode)resizeMode
|
||||||
|
backgroundColor:(UIColor *)backgroundColor
|
||||||
|
block:(RCTImageDownloadBlock)block
|
||||||
{
|
{
|
||||||
return [self downloadDataForURL:url block:^(NSData *data, NSError *error) {
|
return [self downloadDataForURL:url block:^(NSData *data, NSError *error) {
|
||||||
|
|
||||||
|
if (!data || error) {
|
||||||
|
block(nil, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CGSizeEqualToSize(size, CGSizeZero)) {
|
||||||
|
// Target size wasn't available yet, so abort image drawing
|
||||||
|
block(nil, nil);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
UIImage *image = [UIImage imageWithData:data scale:scale];
|
UIImage *image = [UIImage imageWithData:data scale:scale];
|
||||||
if (image) {
|
if (image) {
|
||||||
|
|
||||||
// Resize (TODO: should we take aspect ratio into account?)
|
// Get scale and size
|
||||||
CGSize imageSize = size;
|
CGFloat destScale = scale ?: RCTScreenScale();
|
||||||
if (CGSizeEqualToSize(imageSize, CGSizeZero)) {
|
CGRect imageRect = RCTClipRect(image.size, image.scale, size, destScale, resizeMode);
|
||||||
imageSize = image.size;
|
CGSize destSize = RCTTargetSizeForClipRect(imageRect);
|
||||||
} else {
|
|
||||||
imageSize = (CGSize){
|
|
||||||
MIN(size.width, image.size.width),
|
|
||||||
MIN(size.height, image.size.height)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rescale image if required size is smaller
|
// Opacity optimizations
|
||||||
CGFloat imageScale = scale;
|
UIColor *blendColor = nil;
|
||||||
if (imageScale == 0 || imageScale < image.scale) {
|
BOOL opaque = !RCTImageHasAlpha(image.CGImage);
|
||||||
imageScale = image.scale;
|
if (!opaque && backgroundColor) {
|
||||||
|
CGFloat alpha;
|
||||||
|
[backgroundColor getRed:NULL green:NULL blue:NULL alpha:&alpha];
|
||||||
|
if (alpha > 0.999) { // no benefit to blending if background is translucent
|
||||||
|
opaque = YES;
|
||||||
|
blendColor = backgroundColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decompress image at required size
|
// Decompress image at required size
|
||||||
UIGraphicsBeginImageContextWithOptions(imageSize, NO, imageScale);
|
UIGraphicsBeginImageContextWithOptions(destSize, opaque, destScale);
|
||||||
[image drawInRect:(CGRect){{0, 0}, imageSize}];
|
if (blendColor) {
|
||||||
|
[blendColor setFill];
|
||||||
|
UIRectFill((CGRect){CGPointZero, destSize});
|
||||||
|
}
|
||||||
|
[image drawInRect:imageRect];
|
||||||
image = UIGraphicsGetImageFromCurrentImageContext();
|
image = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
UIGraphicsEndImageContext();
|
UIGraphicsEndImageContext();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,6 @@ static dispatch_queue_t RCTImageLoaderQueue(void)
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
queue = dispatch_queue_create("com.facebook.rctImageLoader", DISPATCH_QUEUE_SERIAL);
|
queue = dispatch_queue_create("com.facebook.rctImageLoader", DISPATCH_QUEUE_SERIAL);
|
||||||
dispatch_set_target_queue(queue,
|
|
||||||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return queue;
|
return queue;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#import "RCTGIFImage.h"
|
#import "RCTGIFImage.h"
|
||||||
#import "RCTImageDownloader.h"
|
#import "RCTImageDownloader.h"
|
||||||
#import "RCTUtils.h"
|
#import "RCTUtils.h"
|
||||||
|
#import "UIView+React.h"
|
||||||
|
|
||||||
@implementation RCTNetworkImageView
|
@implementation RCTNetworkImageView
|
||||||
{
|
{
|
||||||
|
@ -26,8 +27,7 @@
|
||||||
|
|
||||||
- (instancetype)initWithFrame:(CGRect)frame imageDownloader:(RCTImageDownloader *)imageDownloader
|
- (instancetype)initWithFrame:(CGRect)frame imageDownloader:(RCTImageDownloader *)imageDownloader
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:frame];
|
if ((self = [super initWithFrame:frame])) {
|
||||||
if (self) {
|
|
||||||
_deferSentinel = 0;
|
_deferSentinel = 0;
|
||||||
_imageDownloader = imageDownloader;
|
_imageDownloader = imageDownloader;
|
||||||
self.userInteractionEnabled = NO;
|
self.userInteractionEnabled = NO;
|
||||||
|
@ -37,20 +37,44 @@
|
||||||
|
|
||||||
- (NSURL *)imageURL
|
- (NSURL *)imageURL
|
||||||
{
|
{
|
||||||
// We clear our backing layer's imageURL when we are not in a window for a while,
|
// We clear our imageURL when we are not in a window for a while,
|
||||||
// to make sure we don't consume network resources while offscreen.
|
// to make sure we don't consume network resources while offscreen.
|
||||||
// However we don't want to expose this hackery externally.
|
// However we don't want to expose this hackery externally.
|
||||||
return _deferred ? _deferredImageURL : _imageURL;
|
return _deferred ? _deferredImageURL : _imageURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setBackgroundColor:(UIColor *)backgroundColor
|
||||||
|
{
|
||||||
|
super.backgroundColor = backgroundColor;
|
||||||
|
[self _updateImage];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)reactSetFrame:(CGRect)frame
|
||||||
|
{
|
||||||
|
[super reactSetFrame:frame];
|
||||||
|
[self _updateImage];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_updateImage
|
||||||
|
{
|
||||||
|
[self setImageURL:_imageURL resetToDefaultImageWhileLoading:NO];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setImageURL:(NSURL *)imageURL resetToDefaultImageWhileLoading:(BOOL)reset
|
- (void)setImageURL:(NSURL *)imageURL resetToDefaultImageWhileLoading:(BOOL)reset
|
||||||
{
|
{
|
||||||
|
if (![_imageURL isEqual:imageURL] && _downloadToken) {
|
||||||
|
[_imageDownloader cancelDownload:_downloadToken];
|
||||||
|
_downloadToken = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
_imageURL = imageURL;
|
||||||
|
|
||||||
if (_deferred) {
|
if (_deferred) {
|
||||||
_deferredImageURL = imageURL;
|
_deferredImageURL = imageURL;
|
||||||
} else {
|
} else {
|
||||||
if (_downloadToken) {
|
if (!imageURL) {
|
||||||
[_imageDownloader cancelDownload:_downloadToken];
|
self.layer.contents = nil;
|
||||||
_downloadToken = nil;
|
return;
|
||||||
}
|
}
|
||||||
if (reset) {
|
if (reset) {
|
||||||
self.layer.contentsScale = _defaultImage.scale;
|
self.layer.contentsScale = _defaultImage.scale;
|
||||||
|
@ -62,25 +86,35 @@
|
||||||
_downloadToken = [_imageDownloader downloadDataForURL:imageURL block:^(NSData *data, NSError *error) {
|
_downloadToken = [_imageDownloader downloadDataForURL:imageURL block:^(NSData *data, NSError *error) {
|
||||||
if (data) {
|
if (data) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
if (imageURL != self.imageURL) {
|
||||||
|
// Image has changed
|
||||||
|
return;
|
||||||
|
}
|
||||||
CAKeyframeAnimation *animation = RCTGIFImageWithData(data);
|
CAKeyframeAnimation *animation = RCTGIFImageWithData(data);
|
||||||
self.layer.contentsScale = 1.0;
|
self.layer.contentsScale = 1.0;
|
||||||
self.layer.minificationFilter = kCAFilterLinear;
|
self.layer.minificationFilter = kCAFilterLinear;
|
||||||
self.layer.magnificationFilter = kCAFilterLinear;
|
self.layer.magnificationFilter = kCAFilterLinear;
|
||||||
[self.layer addAnimation:animation forKey:@"contents"];
|
[self.layer addAnimation:animation forKey:@"contents"];
|
||||||
});
|
});
|
||||||
|
} else if (error) {
|
||||||
|
RCTLogWarn(@"Unable to download image data. Error: %@", error);
|
||||||
}
|
}
|
||||||
// TODO: handle errors
|
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
_downloadToken = [_imageDownloader downloadImageForURL:imageURL size:self.bounds.size scale:RCTScreenScale() block:^(UIImage *image, NSError *error) {
|
_downloadToken = [_imageDownloader downloadImageForURL:imageURL size:self.bounds.size scale:RCTScreenScale() resizeMode:self.contentMode backgroundColor:self.backgroundColor block:^(UIImage *image, NSError *error) {
|
||||||
if (image) {
|
if (image) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
if (imageURL != self.imageURL) {
|
||||||
|
// Image has changed
|
||||||
|
return;
|
||||||
|
}
|
||||||
[self.layer removeAnimationForKey:@"contents"];
|
[self.layer removeAnimationForKey:@"contents"];
|
||||||
self.layer.contentsScale = image.scale;
|
self.layer.contentsScale = image.scale;
|
||||||
self.layer.contents = (__bridge id)image.CGImage;
|
self.layer.contents = (__bridge id)image.CGImage;
|
||||||
});
|
});
|
||||||
|
} else if (error) {
|
||||||
|
RCTLogWarn(@"Unable to download image. Error: %@", error);
|
||||||
}
|
}
|
||||||
// TODO: handle errors
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,13 @@ var invariant = require('invariant');
|
||||||
var keyMirror = require('keyMirror');
|
var keyMirror = require('keyMirror');
|
||||||
var setImmediate = require('setImmediate');
|
var setImmediate = require('setImmediate');
|
||||||
|
|
||||||
|
type Handle = number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum time a handle can be open before warning in DEV.
|
||||||
|
*/
|
||||||
|
var DEV_TIMEOUT = 2000;
|
||||||
|
|
||||||
var _emitter = new EventEmitter();
|
var _emitter = new EventEmitter();
|
||||||
var _interactionSet = new Set();
|
var _interactionSet = new Set();
|
||||||
var _addInteractionSet = new Set();
|
var _addInteractionSet = new Set();
|
||||||
|
@ -83,17 +90,25 @@ var InteractionManager = {
|
||||||
/**
|
/**
|
||||||
* Notify manager that an interaction has started.
|
* Notify manager that an interaction has started.
|
||||||
*/
|
*/
|
||||||
createInteractionHandle(): number {
|
createInteractionHandle(): Handle {
|
||||||
scheduleUpdate();
|
scheduleUpdate();
|
||||||
var handle = ++_inc;
|
var handle = ++_inc;
|
||||||
_addInteractionSet.add(handle);
|
_addInteractionSet.add(handle);
|
||||||
|
if (__DEV__) {
|
||||||
|
// Capture the stack trace of what created the handle.
|
||||||
|
var error = new Error(
|
||||||
|
'InteractionManager: interaction handle not cleared within ' +
|
||||||
|
DEV_TIMEOUT + ' ms.'
|
||||||
|
);
|
||||||
|
setDevTimeoutHandle(handle, error, DEV_TIMEOUT);
|
||||||
|
}
|
||||||
return handle;
|
return handle;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify manager that an interaction has completed.
|
* Notify manager that an interaction has completed.
|
||||||
*/
|
*/
|
||||||
clearInteractionHandle(handle: number) {
|
clearInteractionHandle(handle: Handle) {
|
||||||
invariant(
|
invariant(
|
||||||
!!handle,
|
!!handle,
|
||||||
'Must provide a handle to clear.'
|
'Must provide a handle to clear.'
|
||||||
|
@ -151,4 +166,19 @@ function processUpdate() {
|
||||||
_deleteInteractionSet.clear();
|
_deleteInteractionSet.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait until `timeout` has passed and warn if the handle has not been cleared.
|
||||||
|
*/
|
||||||
|
function setDevTimeoutHandle(
|
||||||
|
handle: Handle,
|
||||||
|
error: Error,
|
||||||
|
timeout: number
|
||||||
|
): void {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (_interactionSet.has(handle)) {
|
||||||
|
console.warn(error.message + '\n' + error.stack);
|
||||||
|
}
|
||||||
|
}, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = InteractionManager;
|
module.exports = InteractionManager;
|
||||||
|
|
|
@ -43,7 +43,6 @@ var JSTimers = {
|
||||||
var newID = JSTimersExecution.GUID++;
|
var newID = JSTimersExecution.GUID++;
|
||||||
var freeIndex = JSTimers._getFreeIndex();
|
var freeIndex = JSTimers._getFreeIndex();
|
||||||
JSTimersExecution.timerIDs[freeIndex] = newID;
|
JSTimersExecution.timerIDs[freeIndex] = newID;
|
||||||
JSTimersExecution.callbacks[freeIndex] = func;
|
|
||||||
JSTimersExecution.callbacks[freeIndex] = function() {
|
JSTimersExecution.callbacks[freeIndex] = function() {
|
||||||
return func.apply(undefined, args);
|
return func.apply(undefined, args);
|
||||||
};
|
};
|
||||||
|
@ -60,12 +59,15 @@ var JSTimers = {
|
||||||
var newID = JSTimersExecution.GUID++;
|
var newID = JSTimersExecution.GUID++;
|
||||||
var freeIndex = JSTimers._getFreeIndex();
|
var freeIndex = JSTimers._getFreeIndex();
|
||||||
JSTimersExecution.timerIDs[freeIndex] = newID;
|
JSTimersExecution.timerIDs[freeIndex] = newID;
|
||||||
JSTimersExecution.callbacks[freeIndex] = func;
|
|
||||||
JSTimersExecution.callbacks[freeIndex] = function() {
|
JSTimersExecution.callbacks[freeIndex] = function() {
|
||||||
return func.apply(undefined, args);
|
var startTime = Date.now();
|
||||||
|
var ret = func.apply(undefined, args);
|
||||||
|
var endTime = Date.now();
|
||||||
|
RCTTiming.createTimer(newID, Math.max(0, duration - (endTime - startTime)), endTime, false);
|
||||||
|
return ret;
|
||||||
};
|
};
|
||||||
JSTimersExecution.types[freeIndex] = JSTimersExecution.Type.setInterval;
|
JSTimersExecution.types[freeIndex] = JSTimersExecution.Type.setInterval;
|
||||||
RCTTiming.createTimer(newID, duration, Date.now(), /** recurring */ true);
|
RCTTiming.createTimer(newID, duration, Date.now(), /** recurring */ false);
|
||||||
return newID;
|
return newID;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -77,7 +79,6 @@ var JSTimers = {
|
||||||
var newID = JSTimersExecution.GUID++;
|
var newID = JSTimersExecution.GUID++;
|
||||||
var freeIndex = JSTimers._getFreeIndex();
|
var freeIndex = JSTimers._getFreeIndex();
|
||||||
JSTimersExecution.timerIDs[freeIndex] = newID;
|
JSTimersExecution.timerIDs[freeIndex] = newID;
|
||||||
JSTimersExecution.callbacks[freeIndex] = func;
|
|
||||||
JSTimersExecution.callbacks[freeIndex] = function() {
|
JSTimersExecution.callbacks[freeIndex] = function() {
|
||||||
return func.apply(undefined, args);
|
return func.apply(undefined, args);
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#import "RCTJavaScriptLoader.h"
|
#import "RCTJavaScriptLoader.h"
|
||||||
#import "RCTKeyCommands.h"
|
#import "RCTKeyCommands.h"
|
||||||
#import "RCTLog.h"
|
#import "RCTLog.h"
|
||||||
|
#import "RCTPerfStats.h"
|
||||||
#import "RCTProfile.h"
|
#import "RCTProfile.h"
|
||||||
#import "RCTRedBox.h"
|
#import "RCTRedBox.h"
|
||||||
#import "RCTRootView.h"
|
#import "RCTRootView.h"
|
||||||
|
@ -930,6 +931,11 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
||||||
_queuesByID = [[RCTSparseArray alloc] init];
|
_queuesByID = [[RCTSparseArray alloc] init];
|
||||||
_jsDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_jsThreadUpdate:)];
|
_jsDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_jsThreadUpdate:)];
|
||||||
|
|
||||||
|
if (RCT_DEV) {
|
||||||
|
_mainDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_mainThreadUpdate:)];
|
||||||
|
[_mainDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize executor to allow enqueueing calls
|
* Initialize executor to allow enqueueing calls
|
||||||
*/
|
*/
|
||||||
|
@ -1560,6 +1566,8 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
||||||
}
|
}
|
||||||
|
|
||||||
RCTProfileEndEvent(@"DispatchFrameUpdate", @"objc_call", nil);
|
RCTProfileEndEvent(@"DispatchFrameUpdate", @"objc_call", nil);
|
||||||
|
|
||||||
|
[self.perfStats.jsGraph tick:displayLink.timestamp];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_mainThreadUpdate:(CADisplayLink *)displayLink
|
- (void)_mainThreadUpdate:(CADisplayLink *)displayLink
|
||||||
|
@ -1567,6 +1575,8 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
||||||
RCTAssertMainThread();
|
RCTAssertMainThread();
|
||||||
|
|
||||||
RCTProfileImmediateEvent(@"VSYNC", displayLink.timestamp, @"g");
|
RCTProfileImmediateEvent(@"VSYNC", displayLink.timestamp, @"g");
|
||||||
|
|
||||||
|
[self.perfStats.uiGraph tick:displayLink.timestamp];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)startProfiling
|
- (void)startProfiling
|
||||||
|
@ -1578,10 +1588,6 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[_mainDisplayLink invalidate];
|
|
||||||
_mainDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_mainThreadUpdate:)];
|
|
||||||
[_mainDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
|
||||||
|
|
||||||
RCTProfileInit();
|
RCTProfileInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1589,8 +1595,6 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
|
||||||
{
|
{
|
||||||
RCTAssertMainThread();
|
RCTAssertMainThread();
|
||||||
|
|
||||||
[_mainDisplayLink invalidate];
|
|
||||||
|
|
||||||
NSString *log = RCTProfileEnd();
|
NSString *log = RCTProfileEnd();
|
||||||
NSURL *bundleURL = _parentBridge.bundleURL;
|
NSURL *bundleURL = _parentBridge.bundleURL;
|
||||||
NSString *URLString = [NSString stringWithFormat:@"%@://%@:%@/profile", bundleURL.scheme, bundleURL.host, bundleURL.port];
|
NSString *URLString = [NSString stringWithFormat:@"%@://%@:%@/profile", bundleURL.scheme, bundleURL.host, bundleURL.port];
|
||||||
|
|
|
@ -35,6 +35,11 @@
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, assign) BOOL liveReloadEnabled;
|
@property (nonatomic, assign) BOOL liveReloadEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the FPS monitor for the JS and Main threads
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) BOOL showFPS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manually show the dev menu (can be called from JS).
|
* Manually show the dev menu (can be called from JS).
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#import "RCTDefines.h"
|
#import "RCTDefines.h"
|
||||||
#import "RCTKeyCommands.h"
|
#import "RCTKeyCommands.h"
|
||||||
#import "RCTLog.h"
|
#import "RCTLog.h"
|
||||||
|
#import "RCTPerfStats.h"
|
||||||
#import "RCTProfile.h"
|
#import "RCTProfile.h"
|
||||||
#import "RCTRootView.h"
|
#import "RCTRootView.h"
|
||||||
#import "RCTSourceCode.h"
|
#import "RCTSourceCode.h"
|
||||||
|
@ -145,6 +146,7 @@ RCT_EXPORT_MODULE()
|
||||||
self.shakeToShow = [_settings[@"shakeToShow"] ?: @YES boolValue];
|
self.shakeToShow = [_settings[@"shakeToShow"] ?: @YES boolValue];
|
||||||
self.profilingEnabled = [_settings[@"profilingEnabled"] ?: @NO boolValue];
|
self.profilingEnabled = [_settings[@"profilingEnabled"] ?: @NO boolValue];
|
||||||
self.liveReloadEnabled = [_settings[@"liveReloadEnabled"] ?: @NO boolValue];
|
self.liveReloadEnabled = [_settings[@"liveReloadEnabled"] ?: @NO boolValue];
|
||||||
|
self.showFPS = [_settings[@"showFPS"] ?: @NO boolValue];
|
||||||
self.executorClass = NSClassFromString(_settings[@"executorClass"]);
|
self.executorClass = NSClassFromString(_settings[@"executorClass"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,13 +232,14 @@ RCT_EXPORT_METHOD(show)
|
||||||
|
|
||||||
NSString *debugTitleChrome = _executorClass && _executorClass == NSClassFromString(@"RCTWebSocketExecutor") ? @"Disable Chrome Debugging" : @"Debug in Chrome";
|
NSString *debugTitleChrome = _executorClass && _executorClass == NSClassFromString(@"RCTWebSocketExecutor") ? @"Disable Chrome Debugging" : @"Debug in Chrome";
|
||||||
NSString *debugTitleSafari = _executorClass && _executorClass == NSClassFromString(@"RCTWebViewExecutor") ? @"Disable Safari Debugging" : @"Debug in Safari";
|
NSString *debugTitleSafari = _executorClass && _executorClass == NSClassFromString(@"RCTWebViewExecutor") ? @"Disable Safari Debugging" : @"Debug in Safari";
|
||||||
|
NSString *fpsMonitor = _showFPS ? @"Hide FPS Monitor" : @"Show FPS Monitor";
|
||||||
|
|
||||||
UIActionSheet *actionSheet =
|
UIActionSheet *actionSheet =
|
||||||
[[UIActionSheet alloc] initWithTitle:@"React Native: Development"
|
[[UIActionSheet alloc] initWithTitle:@"React Native: Development"
|
||||||
delegate:self
|
delegate:self
|
||||||
cancelButtonTitle:nil
|
cancelButtonTitle:nil
|
||||||
destructiveButtonTitle:nil
|
destructiveButtonTitle:nil
|
||||||
otherButtonTitles:@"Reload", debugTitleChrome, debugTitleSafari, nil];
|
otherButtonTitles:@"Reload", debugTitleChrome, debugTitleSafari, fpsMonitor, nil];
|
||||||
|
|
||||||
if (_liveReloadURL) {
|
if (_liveReloadURL) {
|
||||||
|
|
||||||
|
@ -293,10 +296,14 @@ RCT_EXPORT_METHOD(reload)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: {
|
case 3: {
|
||||||
self.liveReloadEnabled = !_liveReloadEnabled;
|
self.showFPS = !_showFPS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
case 4: {
|
||||||
|
self.liveReloadEnabled = !_liveReloadEnabled;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5: {
|
||||||
self.profilingEnabled = !_profilingEnabled;
|
self.profilingEnabled = !_profilingEnabled;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -368,6 +375,21 @@ RCT_EXPORT_METHOD(reload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setShowFPS:(BOOL)showFPS
|
||||||
|
{
|
||||||
|
if (_showFPS != showFPS) {
|
||||||
|
_showFPS = showFPS;
|
||||||
|
|
||||||
|
if (showFPS) {
|
||||||
|
[_bridge.perfStats show];
|
||||||
|
} else {
|
||||||
|
[_bridge.perfStats hide];
|
||||||
|
}
|
||||||
|
|
||||||
|
[self updateSetting:@"showFPS" value:@(showFPS)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)checkForUpdates
|
- (void)checkForUpdates
|
||||||
{
|
{
|
||||||
if (!_jsLoaded || !_liveReloadEnabled || !_liveReloadURL) {
|
if (!_jsLoaded || !_liveReloadEnabled || !_liveReloadURL) {
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, RCTFPSGraphPosition) {
|
||||||
|
RCTFPSGraphPositionLeft = 1,
|
||||||
|
RCTFPSGraphPositionRight = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
@interface RCTFPSGraph : UIView
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(CGRect)frame graphPosition:(RCTFPSGraphPosition)position name:(NSString *)name color:(UIColor *)color NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
|
- (void)tick:(NSTimeInterval)timestamp;
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,132 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "RCTFPSGraph.h"
|
||||||
|
|
||||||
|
#import "RCTDefines.h"
|
||||||
|
|
||||||
|
#if RCT_DEV
|
||||||
|
|
||||||
|
@implementation RCTFPSGraph
|
||||||
|
{
|
||||||
|
CAShapeLayer *_graph;
|
||||||
|
NSString *_name;
|
||||||
|
NSTimeInterval _prevTime;
|
||||||
|
RCTFPSGraphPosition _position;
|
||||||
|
UILabel *_label;
|
||||||
|
|
||||||
|
float *_frames;
|
||||||
|
int _frameCount;
|
||||||
|
int _maxFPS;
|
||||||
|
int _minFPS;
|
||||||
|
int _length;
|
||||||
|
int _margin;
|
||||||
|
int _height;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(CGRect)frame graphPosition:(RCTFPSGraphPosition)position name:(NSString *)name color:(UIColor *)color
|
||||||
|
{
|
||||||
|
if (self = [super initWithFrame:frame]) {
|
||||||
|
_margin = 2;
|
||||||
|
_prevTime = -1;
|
||||||
|
_maxFPS = 0;
|
||||||
|
_minFPS = 60;
|
||||||
|
_length = (frame.size.width - 2 * _margin) / 2;
|
||||||
|
_height = frame.size.height - 2 * _margin;
|
||||||
|
_frames = malloc(sizeof(float) * _length);
|
||||||
|
memset(_frames, 0, sizeof(float) * _length);
|
||||||
|
|
||||||
|
_name = name;
|
||||||
|
_position = position;
|
||||||
|
_graph = [self createGraph:color];
|
||||||
|
_label = [self createLabel:color];
|
||||||
|
|
||||||
|
[self addSubview:_label];
|
||||||
|
[self.layer addSublayer:_graph];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
free(_frames);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)layoutSubviews
|
||||||
|
{
|
||||||
|
[super layoutSubviews];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CAShapeLayer *)createGraph:(UIColor *)color
|
||||||
|
{
|
||||||
|
CGFloat left = _position & RCTFPSGraphPositionLeft ? 0 : _length;
|
||||||
|
CAShapeLayer *graph = [[CAShapeLayer alloc] init];
|
||||||
|
graph.frame = CGRectMake(left, 0, 2 * _margin + _length, self.frame.size.height);
|
||||||
|
graph.backgroundColor = [[color colorWithAlphaComponent:.2] CGColor];
|
||||||
|
graph.fillColor = [color CGColor];
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UILabel *)createLabel:(UIColor *)color
|
||||||
|
{
|
||||||
|
CGFloat left = _position & RCTFPSGraphPositionLeft ? 2 * _margin + _length : 0;
|
||||||
|
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(left, 0, _length, self.frame.size.height)];
|
||||||
|
label.textColor = color;
|
||||||
|
label.font = [UIFont systemFontOfSize:9];
|
||||||
|
label.minimumScaleFactor = .5;
|
||||||
|
label.adjustsFontSizeToFitWidth = YES;
|
||||||
|
label.numberOfLines = 3;
|
||||||
|
label.lineBreakMode = NSLineBreakByWordWrapping;
|
||||||
|
label.textAlignment = NSTextAlignmentCenter;
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)tick:(NSTimeInterval)timestamp
|
||||||
|
{
|
||||||
|
_frameCount++;
|
||||||
|
if (_prevTime == -1) {
|
||||||
|
_prevTime = timestamp;
|
||||||
|
} else if (timestamp - _prevTime > 1) {
|
||||||
|
float fps = round(_frameCount / (timestamp - _prevTime));
|
||||||
|
_minFPS = MIN(_minFPS, fps);
|
||||||
|
_maxFPS = MAX(_maxFPS, fps);
|
||||||
|
|
||||||
|
_label.text = [NSString stringWithFormat:@"%@\n%d FPS\n(%d - %d)", _name, (int)fps, _minFPS, _maxFPS];
|
||||||
|
|
||||||
|
float scale = 60.0 / _height;
|
||||||
|
for (int i = 0; i < _length - 1; i++) {
|
||||||
|
_frames[i] = _frames[i + 1];
|
||||||
|
}
|
||||||
|
_frames[_length - 1] = fps / scale;
|
||||||
|
|
||||||
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
|
if (_position & RCTFPSGraphPositionLeft) {
|
||||||
|
CGPathMoveToPoint(path, NULL, _margin, _margin + _height);
|
||||||
|
for (int i = 0; i < _length; i++) {
|
||||||
|
CGPathAddLineToPoint(path, NULL, _margin + i, _margin + _height - _frames[i]);
|
||||||
|
}
|
||||||
|
CGPathAddLineToPoint(path, NULL, _margin + _length - 1, _margin + _height);
|
||||||
|
} else {
|
||||||
|
CGPathMoveToPoint(path, NULL, _margin + _length - 1, _margin + _height);
|
||||||
|
for (int i = 0; i < _length; i++) {
|
||||||
|
CGPathAddLineToPoint(path, NULL, _margin + _length - i - 1, _margin + _height - _frames[i]);
|
||||||
|
}
|
||||||
|
CGPathAddLineToPoint(path, NULL, _margin, _margin + _height);
|
||||||
|
}
|
||||||
|
_graph.path = path;
|
||||||
|
CGPathRelease(path);
|
||||||
|
|
||||||
|
_prevTime = timestamp;
|
||||||
|
_frameCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "RCTBridge.h"
|
||||||
|
#import "RCTFPSGraph.h"
|
||||||
|
|
||||||
|
@interface RCTPerfStats : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, strong) RCTFPSGraph *jsGraph;
|
||||||
|
@property (nonatomic, strong) RCTFPSGraph *uiGraph;
|
||||||
|
|
||||||
|
- (void)show;
|
||||||
|
- (void)hide;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface RCTBridge (RCTPerfStats)
|
||||||
|
|
||||||
|
@property (nonatomic, strong, readonly) RCTPerfStats *perfStats;
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,133 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "RCTPerfStats.h"
|
||||||
|
|
||||||
|
#import "RCTDefines.h"
|
||||||
|
|
||||||
|
#if RCT_DEV
|
||||||
|
|
||||||
|
@interface RCTPerfStats() <RCTBridgeModule>
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation RCTPerfStats
|
||||||
|
{
|
||||||
|
UIView *_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_MODULE()
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[self hide];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIView *)container
|
||||||
|
{
|
||||||
|
if (!_container) {
|
||||||
|
_container = [[UIView alloc] init];
|
||||||
|
_container.backgroundColor = [UIColor colorWithRed:0 green:0 blue:34/255.0 alpha:1];
|
||||||
|
_container.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
|
||||||
|
}
|
||||||
|
return _container;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (RCTFPSGraph *)jsGraph
|
||||||
|
{
|
||||||
|
if (!_jsGraph) {
|
||||||
|
UIColor *jsColor = [UIColor colorWithRed:0 green:1 blue:0 alpha:1];
|
||||||
|
_jsGraph = [[RCTFPSGraph alloc] initWithFrame:CGRectMake(2, 2, 124, 34)
|
||||||
|
graphPosition:RCTFPSGraphPositionRight
|
||||||
|
name:@"[ JS ]"
|
||||||
|
color:jsColor];
|
||||||
|
_jsGraph.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
|
||||||
|
}
|
||||||
|
return _jsGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (RCTFPSGraph *)uiGraph
|
||||||
|
{
|
||||||
|
if (!_uiGraph) {
|
||||||
|
UIColor *uiColor = [UIColor colorWithRed:0 green:1 blue:1 alpha:1];
|
||||||
|
_uiGraph = [[RCTFPSGraph alloc] initWithFrame:CGRectMake(2, 2, 124, 34)
|
||||||
|
graphPosition:RCTFPSGraphPositionLeft
|
||||||
|
name:@"[ UI ]"
|
||||||
|
color:uiColor];
|
||||||
|
}
|
||||||
|
return _uiGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)show
|
||||||
|
{
|
||||||
|
UIView *targetView = [[[[[UIApplication sharedApplication] delegate] window] rootViewController] view];
|
||||||
|
|
||||||
|
targetView.frame = (CGRect){
|
||||||
|
targetView.frame.origin,
|
||||||
|
{
|
||||||
|
targetView.frame.size.width,
|
||||||
|
targetView.frame.size.height - 38,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.container.frame = (CGRect){{0, targetView.frame.size.height}, {targetView.frame.size.width, 38}};
|
||||||
|
self.jsGraph.frame = (CGRect){
|
||||||
|
{
|
||||||
|
targetView.frame.size.width - self.uiGraph.frame.size.width - self.uiGraph.frame.origin.x,
|
||||||
|
self.uiGraph.frame.origin.x,
|
||||||
|
},
|
||||||
|
self.uiGraph.frame.size,
|
||||||
|
};
|
||||||
|
|
||||||
|
[self.container addSubview:self.jsGraph];
|
||||||
|
[self.container addSubview:self.uiGraph];
|
||||||
|
[targetView addSubview:self.container];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)hide
|
||||||
|
{
|
||||||
|
UIView *targetView = _container.superview;
|
||||||
|
|
||||||
|
targetView.frame = (CGRect){
|
||||||
|
targetView.frame.origin,
|
||||||
|
{
|
||||||
|
targetView.frame.size.width,
|
||||||
|
targetView.frame.size.height + _container.frame.size.height
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[_container removeFromSuperview];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (dispatch_queue_t)methodQueue
|
||||||
|
{
|
||||||
|
return dispatch_get_main_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
@implementation RCTPerfStats
|
||||||
|
|
||||||
|
- (void)show {}
|
||||||
|
- (void)hide {}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@implementation RCTBridge (RCTPerfStats)
|
||||||
|
|
||||||
|
- (RCTPerfStats *)perfStats
|
||||||
|
{
|
||||||
|
return self.modules[RCTBridgeModuleNameForClass([RCTPerfStats class])];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -52,3 +52,6 @@ RCT_EXTERN NSDictionary *RCTMakeAndLogError(NSString *message, id toStringify, N
|
||||||
|
|
||||||
// Returns YES if React is running in a test environment
|
// Returns YES if React is running in a test environment
|
||||||
RCT_EXTERN BOOL RCTRunningInTestEnvironment(void);
|
RCT_EXTERN BOOL RCTRunningInTestEnvironment(void);
|
||||||
|
|
||||||
|
// Return YES if image has an alpha component
|
||||||
|
RCT_EXTERN BOOL RCTImageHasAlpha(CGImageRef image);
|
||||||
|
|
|
@ -261,3 +261,15 @@ BOOL RCTRunningInTestEnvironment(void)
|
||||||
});
|
});
|
||||||
return _isTestEnvironment;
|
return _isTestEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL RCTImageHasAlpha(CGImageRef image)
|
||||||
|
{
|
||||||
|
switch (CGImageGetAlphaInfo(image)) {
|
||||||
|
case kCGImageAlphaNone:
|
||||||
|
case kCGImageAlphaNoneSkipLast:
|
||||||
|
case kCGImageAlphaNoneSkipFirst:
|
||||||
|
return NO;
|
||||||
|
default:
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -44,9 +44,11 @@
|
||||||
13E067561A70F44B002CDEE1 /* RCTViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E0674E1A70F44B002CDEE1 /* RCTViewManager.m */; };
|
13E067561A70F44B002CDEE1 /* RCTViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E0674E1A70F44B002CDEE1 /* RCTViewManager.m */; };
|
||||||
13E067571A70F44B002CDEE1 /* RCTView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067501A70F44B002CDEE1 /* RCTView.m */; };
|
13E067571A70F44B002CDEE1 /* RCTView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067501A70F44B002CDEE1 /* RCTView.m */; };
|
||||||
13E067591A70F44B002CDEE1 /* UIView+React.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067541A70F44B002CDEE1 /* UIView+React.m */; };
|
13E067591A70F44B002CDEE1 /* UIView+React.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067541A70F44B002CDEE1 /* UIView+React.m */; };
|
||||||
|
1403F2B31B0AE60700C2A9A4 /* RCTPerfStats.m in Sources */ = {isa = PBXBuildFile; fileRef = 1403F2B21B0AE60700C2A9A4 /* RCTPerfStats.m */; };
|
||||||
14200DAA1AC179B3008EE6BA /* RCTJavaScriptLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 14200DA91AC179B3008EE6BA /* RCTJavaScriptLoader.m */; };
|
14200DAA1AC179B3008EE6BA /* RCTJavaScriptLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 14200DA91AC179B3008EE6BA /* RCTJavaScriptLoader.m */; };
|
||||||
14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE21AAC4AE100FC20F4 /* RCTMap.m */; };
|
14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE21AAC4AE100FC20F4 /* RCTMap.m */; };
|
||||||
14435CE61AAC4AE100FC20F4 /* RCTMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE41AAC4AE100FC20F4 /* RCTMapManager.m */; };
|
14435CE61AAC4AE100FC20F4 /* RCTMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE41AAC4AE100FC20F4 /* RCTMapManager.m */; };
|
||||||
|
146459261B06C49500B389AA /* RCTFPSGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 146459251B06C49500B389AA /* RCTFPSGraph.m */; };
|
||||||
14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F362081AABD06A001CE568 /* RCTSwitch.m */; };
|
14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F362081AABD06A001CE568 /* RCTSwitch.m */; };
|
||||||
14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */; };
|
14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */; };
|
||||||
14F484561AABFCE100FDF6B9 /* RCTSliderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F484551AABFCE100FDF6B9 /* RCTSliderManager.m */; };
|
14F484561AABFCE100FDF6B9 /* RCTSliderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F484551AABFCE100FDF6B9 /* RCTSliderManager.m */; };
|
||||||
|
@ -163,6 +165,8 @@
|
||||||
13E067501A70F44B002CDEE1 /* RCTView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTView.m; sourceTree = "<group>"; };
|
13E067501A70F44B002CDEE1 /* RCTView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTView.m; sourceTree = "<group>"; };
|
||||||
13E067531A70F44B002CDEE1 /* UIView+React.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+React.h"; sourceTree = "<group>"; };
|
13E067531A70F44B002CDEE1 /* UIView+React.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+React.h"; sourceTree = "<group>"; };
|
||||||
13E067541A70F44B002CDEE1 /* UIView+React.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+React.m"; sourceTree = "<group>"; };
|
13E067541A70F44B002CDEE1 /* UIView+React.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+React.m"; sourceTree = "<group>"; };
|
||||||
|
1403F2B11B0AE60700C2A9A4 /* RCTPerfStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPerfStats.h; sourceTree = "<group>"; };
|
||||||
|
1403F2B21B0AE60700C2A9A4 /* RCTPerfStats.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPerfStats.m; sourceTree = "<group>"; };
|
||||||
14200DA81AC179B3008EE6BA /* RCTJavaScriptLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJavaScriptLoader.h; sourceTree = "<group>"; };
|
14200DA81AC179B3008EE6BA /* RCTJavaScriptLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJavaScriptLoader.h; sourceTree = "<group>"; };
|
||||||
14200DA91AC179B3008EE6BA /* RCTJavaScriptLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTJavaScriptLoader.m; sourceTree = "<group>"; };
|
14200DA91AC179B3008EE6BA /* RCTJavaScriptLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTJavaScriptLoader.m; sourceTree = "<group>"; };
|
||||||
1436DD071ADE7AA000A5ED7D /* RCTFrameUpdate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTFrameUpdate.h; sourceTree = "<group>"; };
|
1436DD071ADE7AA000A5ED7D /* RCTFrameUpdate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTFrameUpdate.h; sourceTree = "<group>"; };
|
||||||
|
@ -170,6 +174,8 @@
|
||||||
14435CE21AAC4AE100FC20F4 /* RCTMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMap.m; sourceTree = "<group>"; };
|
14435CE21AAC4AE100FC20F4 /* RCTMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMap.m; sourceTree = "<group>"; };
|
||||||
14435CE31AAC4AE100FC20F4 /* RCTMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMapManager.h; sourceTree = "<group>"; };
|
14435CE31AAC4AE100FC20F4 /* RCTMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMapManager.h; sourceTree = "<group>"; };
|
||||||
14435CE41AAC4AE100FC20F4 /* RCTMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMapManager.m; sourceTree = "<group>"; };
|
14435CE41AAC4AE100FC20F4 /* RCTMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMapManager.m; sourceTree = "<group>"; };
|
||||||
|
146459241B06C49500B389AA /* RCTFPSGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTFPSGraph.h; sourceTree = "<group>"; };
|
||||||
|
146459251B06C49500B389AA /* RCTFPSGraph.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTFPSGraph.m; sourceTree = "<group>"; };
|
||||||
14F362071AABD06A001CE568 /* RCTSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSwitch.h; sourceTree = "<group>"; };
|
14F362071AABD06A001CE568 /* RCTSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSwitch.h; sourceTree = "<group>"; };
|
||||||
14F362081AABD06A001CE568 /* RCTSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSwitch.m; sourceTree = "<group>"; };
|
14F362081AABD06A001CE568 /* RCTSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSwitch.m; sourceTree = "<group>"; };
|
||||||
14F362091AABD06A001CE568 /* RCTSwitchManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSwitchManager.h; sourceTree = "<group>"; };
|
14F362091AABD06A001CE568 /* RCTSwitchManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSwitchManager.h; sourceTree = "<group>"; };
|
||||||
|
@ -415,6 +421,10 @@
|
||||||
1436DD071ADE7AA000A5ED7D /* RCTFrameUpdate.h */,
|
1436DD071ADE7AA000A5ED7D /* RCTFrameUpdate.h */,
|
||||||
14F4D3891AE1B7E40049C042 /* RCTProfile.h */,
|
14F4D3891AE1B7E40049C042 /* RCTProfile.h */,
|
||||||
14F4D38A1AE1B7E40049C042 /* RCTProfile.m */,
|
14F4D38A1AE1B7E40049C042 /* RCTProfile.m */,
|
||||||
|
146459241B06C49500B389AA /* RCTFPSGraph.h */,
|
||||||
|
146459251B06C49500B389AA /* RCTFPSGraph.m */,
|
||||||
|
1403F2B11B0AE60700C2A9A4 /* RCTPerfStats.h */,
|
||||||
|
1403F2B21B0AE60700C2A9A4 /* RCTPerfStats.m */,
|
||||||
);
|
);
|
||||||
path = Base;
|
path = Base;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -514,6 +524,7 @@
|
||||||
13E067561A70F44B002CDEE1 /* RCTViewManager.m in Sources */,
|
13E067561A70F44B002CDEE1 /* RCTViewManager.m in Sources */,
|
||||||
58C571C11AA56C1900CDF9C8 /* RCTDatePickerManager.m in Sources */,
|
58C571C11AA56C1900CDF9C8 /* RCTDatePickerManager.m in Sources */,
|
||||||
13B080061A6947C200A75B9A /* RCTScrollViewManager.m in Sources */,
|
13B080061A6947C200A75B9A /* RCTScrollViewManager.m in Sources */,
|
||||||
|
146459261B06C49500B389AA /* RCTFPSGraph.m in Sources */,
|
||||||
14200DAA1AC179B3008EE6BA /* RCTJavaScriptLoader.m in Sources */,
|
14200DAA1AC179B3008EE6BA /* RCTJavaScriptLoader.m in Sources */,
|
||||||
137327EA1AA5CF210034F82E /* RCTTabBarManager.m in Sources */,
|
137327EA1AA5CF210034F82E /* RCTTabBarManager.m in Sources */,
|
||||||
13B080261A694A8400A75B9A /* RCTWrapperViewController.m in Sources */,
|
13B080261A694A8400A75B9A /* RCTWrapperViewController.m in Sources */,
|
||||||
|
@ -549,6 +560,7 @@
|
||||||
14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */,
|
14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */,
|
||||||
134FCB3E1A6E7F0800051CC8 /* RCTWebViewExecutor.m in Sources */,
|
134FCB3E1A6E7F0800051CC8 /* RCTWebViewExecutor.m in Sources */,
|
||||||
13B0801C1A69489C00A75B9A /* RCTNavItem.m in Sources */,
|
13B0801C1A69489C00A75B9A /* RCTNavItem.m in Sources */,
|
||||||
|
1403F2B31B0AE60700C2A9A4 /* RCTPerfStats.m in Sources */,
|
||||||
83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */,
|
83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */,
|
||||||
13E0674A1A70F434002CDEE1 /* RCTUIManager.m in Sources */,
|
13E0674A1A70F434002CDEE1 /* RCTUIManager.m in Sources */,
|
||||||
13B0801B1A69489C00A75B9A /* RCTNavigatorManager.m in Sources */,
|
13B0801B1A69489C00A75B9A /* RCTNavigatorManager.m in Sources */,
|
||||||
|
|
|
@ -127,7 +127,6 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
||||||
_borderBottomRightRadius = -1;
|
_borderBottomRightRadius = -1;
|
||||||
|
|
||||||
_backgroundColor = [super backgroundColor];
|
_backgroundColor = [super backgroundColor];
|
||||||
[super setBackgroundColor:[UIColor clearColor]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -443,6 +442,8 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
||||||
|
|
||||||
- (UIImage *)generateBorderImage:(out CGRect *)contentsCenter
|
- (UIImage *)generateBorderImage:(out CGRect *)contentsCenter
|
||||||
{
|
{
|
||||||
|
static const CGFloat threshold = 0.001;
|
||||||
|
|
||||||
const CGFloat maxRadius = MIN(self.bounds.size.height, self.bounds.size.width);
|
const CGFloat maxRadius = MIN(self.bounds.size.height, self.bounds.size.width);
|
||||||
const CGFloat radius = MAX(0, _borderRadius);
|
const CGFloat radius = MAX(0, _borderRadius);
|
||||||
const CGFloat topLeftRadius = MIN(_borderTopLeftRadius >= 0 ? _borderTopLeftRadius : radius, maxRadius);
|
const CGFloat topLeftRadius = MIN(_borderTopLeftRadius >= 0 ? _borderTopLeftRadius : radius, maxRadius);
|
||||||
|
@ -456,6 +457,17 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
||||||
const CGFloat bottomWidth = _borderBottomWidth >= 0 ? _borderBottomWidth : borderWidth;
|
const CGFloat bottomWidth = _borderBottomWidth >= 0 ? _borderBottomWidth : borderWidth;
|
||||||
const CGFloat leftWidth = _borderLeftWidth >= 0 ? _borderLeftWidth : borderWidth;
|
const CGFloat leftWidth = _borderLeftWidth >= 0 ? _borderLeftWidth : borderWidth;
|
||||||
|
|
||||||
|
if (topLeftRadius < threshold &&
|
||||||
|
topRightRadius < threshold &&
|
||||||
|
bottomLeftRadius < threshold &&
|
||||||
|
bottomRightRadius < threshold &&
|
||||||
|
topWidth < threshold &&
|
||||||
|
rightWidth < threshold &&
|
||||||
|
bottomWidth < threshold &&
|
||||||
|
leftWidth < threshold) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
const CGFloat innerTopLeftRadiusX = MAX(0, topLeftRadius - leftWidth);
|
const CGFloat innerTopLeftRadiusX = MAX(0, topLeftRadius - leftWidth);
|
||||||
const CGFloat innerTopLeftRadiusY = MAX(0, topLeftRadius - topWidth);
|
const CGFloat innerTopLeftRadiusY = MAX(0, topLeftRadius - topWidth);
|
||||||
|
|
||||||
|
@ -657,22 +669,21 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
||||||
|
|
||||||
- (void)displayLayer:(CALayer *)layer
|
- (void)displayLayer:(CALayer *)layer
|
||||||
{
|
{
|
||||||
CGRect contentsCenter;
|
CGRect contentsCenter = (CGRect){CGPointZero, {1, 1}};
|
||||||
UIImage *image = [self generateBorderImage:&contentsCenter];
|
UIImage *image = [self generateBorderImage:&contentsCenter];
|
||||||
|
|
||||||
if (RCTRunningInTestEnvironment()) {
|
if (image && RCTRunningInTestEnvironment()) {
|
||||||
const CGSize size = self.bounds.size;
|
const CGSize size = self.bounds.size;
|
||||||
UIGraphicsBeginImageContextWithOptions(size, NO, image.scale);
|
UIGraphicsBeginImageContextWithOptions(size, NO, image.scale);
|
||||||
[image drawInRect:(CGRect){CGPointZero, size}];
|
[image drawInRect:(CGRect){CGPointZero, size}];
|
||||||
image = UIGraphicsGetImageFromCurrentImageContext();
|
image = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
UIGraphicsEndImageContext();
|
UIGraphicsEndImageContext();
|
||||||
|
|
||||||
contentsCenter = CGRectMake(0, 0, 1, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layer.backgroundColor = [image ? [UIColor clearColor] : _backgroundColor CGColor];
|
||||||
layer.contents = (id)image.CGImage;
|
layer.contents = (id)image.CGImage;
|
||||||
layer.contentsCenter = contentsCenter;
|
layer.contentsCenter = contentsCenter;
|
||||||
layer.contentsScale = image.scale;
|
layer.contentsScale = image.scale ?: 1.0;
|
||||||
layer.magnificationFilter = kCAFilterNearest;
|
layer.magnificationFilter = kCAFilterNearest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
"stacktrace-parser": "git://github.com/frantic/stacktrace-parser.git#493c5e5638",
|
"stacktrace-parser": "git://github.com/frantic/stacktrace-parser.git#493c5e5638",
|
||||||
"uglify-js": "~2.4.16",
|
"uglify-js": "~2.4.16",
|
||||||
"underscore": "1.7.0",
|
"underscore": "1.7.0",
|
||||||
"worker-farm": "^1.3.0",
|
"worker-farm": "^1.3.1",
|
||||||
"ws": "0.4.31",
|
"ws": "0.4.31",
|
||||||
"yargs": "1.3.2"
|
"yargs": "1.3.2"
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,12 +24,21 @@ function parseCommandLine(config) {
|
||||||
// optimist default API requires you to write the command name three time
|
// optimist default API requires you to write the command name three time
|
||||||
// This is a small wrapper to accept an object instead
|
// This is a small wrapper to accept an object instead
|
||||||
for (var i = 0; i < config.length; ++i) {
|
for (var i = 0; i < config.length; ++i) {
|
||||||
|
if (config[i].type === 'string') {
|
||||||
|
optimist.string(config[i].command);
|
||||||
|
} else {
|
||||||
|
optimist.boolean(config[i].command);
|
||||||
|
}
|
||||||
|
|
||||||
optimist
|
optimist
|
||||||
.boolean(config[i].command)
|
|
||||||
.default(config[i].command, config[i].default)
|
.default(config[i].command, config[i].default)
|
||||||
.describe(config[i].command, config[i].description);
|
.describe(config[i].command, config[i].description);
|
||||||
|
|
||||||
|
if (config[i].required) {
|
||||||
|
optimist.demand(config[i].command);
|
||||||
}
|
}
|
||||||
var argv = optimist.argv;
|
}
|
||||||
|
var argv = optimist.parse(process.argv);
|
||||||
|
|
||||||
// optimist doesn't have support for --dev=false, instead it returns 'false'
|
// optimist doesn't have support for --dev=false, instead it returns 'false'
|
||||||
for (var i = 0; i < config.length; ++i) {
|
for (var i = 0; i < config.length; ++i) {
|
||||||
|
@ -43,6 +52,15 @@ function parseCommandLine(config) {
|
||||||
if (argv[command] === 'false') {
|
if (argv[command] === 'false') {
|
||||||
argv[command] = false;
|
argv[command] = false;
|
||||||
}
|
}
|
||||||
|
if (config[i].type === 'string') {
|
||||||
|
// According to https://github.com/substack/node-optimist#numbers,
|
||||||
|
// every argument that looks like a number should be converted to one.
|
||||||
|
var strValue = argv[command];
|
||||||
|
var numValue = strValue ? Number(strValue) : undefined;
|
||||||
|
if (typeof numValue === 'number' && !isNaN(numValue)) {
|
||||||
|
argv[command] = numValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show --help
|
// Show --help
|
||||||
|
|
|
@ -47,6 +47,32 @@ describe('AssetServer', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pit('should work for the simple case with jpg', function() {
|
||||||
|
var server = new AssetServer({
|
||||||
|
projectRoots: ['/root'],
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
imgs: {
|
||||||
|
'b.png': 'png image',
|
||||||
|
'b.jpg': 'jpeg image',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all([
|
||||||
|
server.get('imgs/b.jpg'),
|
||||||
|
server.get('imgs/b.png'),
|
||||||
|
]).then(function(data) {
|
||||||
|
expect(data).toEqual([
|
||||||
|
'jpeg image',
|
||||||
|
'png image',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
pit('should pick the bigger one', function() {
|
pit('should pick the bigger one', function() {
|
||||||
var server = new AssetServer({
|
var server = new AssetServer({
|
||||||
projectRoots: ['/root'],
|
projectRoots: ['/root'],
|
||||||
|
@ -136,5 +162,45 @@ describe('AssetServer', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pit('should get assetData for non-png images', function() {
|
||||||
|
var hash = {
|
||||||
|
update: jest.genMockFn(),
|
||||||
|
digest: jest.genMockFn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
hash.digest.mockImpl(function() {
|
||||||
|
return 'wow such hash';
|
||||||
|
});
|
||||||
|
crypto.createHash.mockImpl(function() {
|
||||||
|
return hash;
|
||||||
|
});
|
||||||
|
|
||||||
|
var server = new AssetServer({
|
||||||
|
projectRoots: ['/root'],
|
||||||
|
assetExts: ['png', 'jpeg'],
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
imgs: {
|
||||||
|
'b@1x.jpg': 'b1 image',
|
||||||
|
'b@2x.jpg': 'b2 image',
|
||||||
|
'b@4x.jpg': 'b4 image',
|
||||||
|
'b@4.5x.jpg': 'b4.5 image',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return server.getAssetData('imgs/b.jpg').then(function(data) {
|
||||||
|
expect(hash.update.mock.calls.length).toBe(4);
|
||||||
|
expect(data).toEqual({
|
||||||
|
type: 'jpg',
|
||||||
|
name: 'b',
|
||||||
|
scales: [1, 2, 4, 4.5],
|
||||||
|
hash: 'wow such hash',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,7 +28,7 @@ var validateOpts = declareOpts({
|
||||||
},
|
},
|
||||||
assetExts: {
|
assetExts: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
default: ['png'],
|
required: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ AssetServer.prototype.getAssetData = function(assetPath) {
|
||||||
var nameData = getAssetDataFromName(assetPath);
|
var nameData = getAssetDataFromName(assetPath);
|
||||||
var data = {
|
var data = {
|
||||||
name: nameData.name,
|
name: nameData.name,
|
||||||
type: 'png',
|
type: nameData.type,
|
||||||
};
|
};
|
||||||
|
|
||||||
return this._getAssetRecord(assetPath).then(function(record) {
|
return this._getAssetRecord(assetPath).then(function(record) {
|
||||||
|
|
|
@ -55,7 +55,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -91,7 +92,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -121,7 +123,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -161,6 +164,7 @@ describe('DependencyGraph', function() {
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher,
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
assetRoots_DEPRECATED: ['/root/imgs'],
|
assetRoots_DEPRECATED: ['/root/imgs'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
|
@ -199,6 +203,7 @@ describe('DependencyGraph', function() {
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher,
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -246,6 +251,7 @@ describe('DependencyGraph', function() {
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher,
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -308,6 +314,7 @@ describe('DependencyGraph', function() {
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher,
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
assetRoots_DEPRECATED: ['/root/imgs'],
|
assetRoots_DEPRECATED: ['/root/imgs'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
|
@ -358,7 +365,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -391,7 +399,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -421,7 +430,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -455,7 +465,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -489,7 +500,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -519,7 +531,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -552,7 +565,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -595,7 +609,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/somedir/somefile.js'))
|
expect(dgraph.getOrderedDependencies('/root/somedir/somefile.js'))
|
||||||
|
@ -641,7 +656,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -674,7 +690,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -712,7 +729,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -755,7 +773,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -798,7 +817,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -847,7 +867,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -888,7 +909,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -931,7 +953,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -974,7 +997,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -1027,7 +1051,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -1092,7 +1117,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
expect(dgraph.getOrderedDependencies('/root/index.js'))
|
||||||
|
@ -1158,7 +1184,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
filesystem.root['index.js'] =
|
filesystem.root['index.js'] =
|
||||||
|
@ -1209,7 +1236,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
filesystem.root['index.js'] =
|
filesystem.root['index.js'] =
|
||||||
|
@ -1260,7 +1288,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
delete filesystem.root.foo;
|
delete filesystem.root.foo;
|
||||||
|
@ -1310,7 +1339,8 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
filesystem.root['bar.js'] = [
|
filesystem.root['bar.js'] = [
|
||||||
|
@ -1367,7 +1397,7 @@ describe('DependencyGraph', function() {
|
||||||
roots: [root],
|
roots: [root],
|
||||||
assetRoots_DEPRECATED: [root],
|
assetRoots_DEPRECATED: [root],
|
||||||
assetExts: ['png'],
|
assetExts: ['png'],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
});
|
});
|
||||||
|
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
|
@ -1419,7 +1449,7 @@ describe('DependencyGraph', function() {
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
assetExts: ['png'],
|
assetExts: ['png'],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
});
|
});
|
||||||
|
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
|
@ -1482,6 +1512,7 @@ describe('DependencyGraph', function() {
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher,
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
ignoreFilePath: function(filePath) {
|
ignoreFilePath: function(filePath) {
|
||||||
if (filePath === '/root/bar.js') {
|
if (filePath === '/root/bar.js') {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1550,7 +1581,8 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
var dgraph = new DependencyGraph({
|
var dgraph = new DependencyGraph({
|
||||||
roots: [root],
|
roots: [root],
|
||||||
fileWatcher: fileWatcher
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
});
|
});
|
||||||
return dgraph.load().then(function() {
|
return dgraph.load().then(function() {
|
||||||
triggerFileChange('change', 'aPackage', '/root', {
|
triggerFileChange('change', 'aPackage', '/root', {
|
||||||
|
|
|
@ -44,7 +44,7 @@ var validateOpts = declareOpts({
|
||||||
},
|
},
|
||||||
assetExts: {
|
assetExts: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
default: ['png'],
|
required: true,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,10 @@ var validateOpts = declareOpts({
|
||||||
type: 'object',
|
type: 'object',
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
assetExts: {
|
||||||
|
type: 'array',
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function HasteDependencyResolver(options) {
|
function HasteDependencyResolver(options) {
|
||||||
|
@ -62,6 +66,7 @@ function HasteDependencyResolver(options) {
|
||||||
this._depGraph = new DependencyGraph({
|
this._depGraph = new DependencyGraph({
|
||||||
roots: opts.projectRoots,
|
roots: opts.projectRoots,
|
||||||
assetRoots_DEPRECATED: opts.assetRoots,
|
assetRoots_DEPRECATED: opts.assetRoots,
|
||||||
|
assetExts: opts.assetExts,
|
||||||
ignoreFilePath: function(filepath) {
|
ignoreFilePath: function(filepath) {
|
||||||
return filepath.indexOf('__tests__') !== -1 ||
|
return filepath.indexOf('__tests__') !== -1 ||
|
||||||
(opts.blacklistRE && opts.blacklistRE.test(filepath));
|
(opts.blacklistRE && opts.blacklistRE.test(filepath));
|
||||||
|
|
|
@ -249,6 +249,15 @@ Package.prototype._getMappings = function() {
|
||||||
return mappings;
|
return mappings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Package.prototype.getJSModulePaths = function() {
|
||||||
|
return this._modules.filter(function(module) {
|
||||||
|
// Filter out non-js files. Like images etc.
|
||||||
|
return !module.virtual;
|
||||||
|
}).map(function(module) {
|
||||||
|
return module.sourcePath;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
Package.prototype.getDebugInfo = function() {
|
Package.prototype.getDebugInfo = function() {
|
||||||
return [
|
return [
|
||||||
'<div><h3>Main Module:</h3> ' + this._mainModuleId + '</div>',
|
'<div><h3>Main Module:</h3> ' + this._mainModuleId + '</div>',
|
||||||
|
|
|
@ -204,8 +204,28 @@ describe('Package', function() {
|
||||||
expect(p.getAssets()).toEqual([asset1, asset2]);
|
expect(p.getAssets()).toEqual([asset1, asset2]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getJSModulePaths()', function() {
|
||||||
|
it('should return module paths', function() {
|
||||||
|
var p = new Package('test_url');
|
||||||
|
p.addModule(new ModuleTransport({
|
||||||
|
code: 'transformed foo;\n',
|
||||||
|
sourceCode: 'source foo',
|
||||||
|
sourcePath: 'foo path'
|
||||||
|
}));
|
||||||
|
p.addModule(new ModuleTransport({
|
||||||
|
code: 'image module;\nimage module;',
|
||||||
|
virtual: true,
|
||||||
|
sourceCode: 'image module;\nimage module;',
|
||||||
|
sourcePath: 'image.png',
|
||||||
|
}));
|
||||||
|
|
||||||
|
expect(p.getJSModulePaths()).toEqual(['foo path']);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function genSourceMap(modules) {
|
function genSourceMap(modules) {
|
||||||
var sourceMapGen = new SourceMapGenerator({file: 'bundle.js', version: 3});
|
var sourceMapGen = new SourceMapGenerator({file: 'bundle.js', version: 3});
|
||||||
var packageLineNo = 0;
|
var packageLineNo = 0;
|
||||||
|
|
|
@ -86,6 +86,7 @@ function Packager(options) {
|
||||||
moduleFormat: opts.moduleFormat,
|
moduleFormat: opts.moduleFormat,
|
||||||
assetRoots: opts.assetRoots,
|
assetRoots: opts.assetRoots,
|
||||||
fileWatcher: opts.fileWatcher,
|
fileWatcher: opts.fileWatcher,
|
||||||
|
assetExts: opts.assetExts,
|
||||||
});
|
});
|
||||||
|
|
||||||
this._transformer = new Transformer({
|
this._transformer = new Transformer({
|
||||||
|
|
|
@ -60,7 +60,7 @@ var validateOpts = declareOpts({
|
||||||
},
|
},
|
||||||
assetExts: {
|
assetExts: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
default: ['png'],
|
default: ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp'],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue