Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce0ad9f712 | ||
|
|
4673dca0b0 | ||
|
|
800c62bb8b | ||
|
|
eec67aff4d | ||
|
|
fe4b4c2d83 | ||
|
|
7f51f9c8a9 | ||
|
|
c6670658f4 | ||
|
|
d20a6e9d2d | ||
|
|
b46c94aaf9 | ||
|
|
08844e3ddc | ||
|
|
1d5d01c3c9 | ||
|
|
9a76f224af | ||
|
|
8bb65215b1 | ||
|
|
0d227c0eb2 | ||
|
|
1b2975803b | ||
|
|
4cd5cad599 | ||
|
|
d211359aeb | ||
|
|
32666f0aa2 | ||
|
|
c1609bcab8 | ||
|
|
97137e8bcc | ||
|
|
11b515b1b0 | ||
|
|
a4f92ba3db | ||
|
|
1c70f33511 | ||
|
|
33ac55b2bd | ||
|
|
de27f1db54 | ||
|
|
a1193b7a93 | ||
|
|
214ae2062c | ||
|
|
f2b76566f3 | ||
|
|
f2ffaed4ca | ||
|
|
03905e69f4 | ||
|
|
6ef7eaf663 | ||
|
|
7219fcefc6 | ||
|
|
eedb880f6e | ||
|
|
a4e89d71a3 | ||
|
|
424d1318c8 | ||
|
|
407d8d4cf6 | ||
|
|
545edba913 | ||
|
|
5a83ffab94 | ||
|
|
d63eac4014 | ||
|
|
367638053a | ||
|
|
08d30e751b | ||
|
|
c668fd5be0 | ||
|
|
5f841a950e | ||
|
|
64c0bb0bd4 | ||
|
|
723e988416 | ||
|
|
7a1c52c8e9 | ||
|
|
0fbe091304 | ||
|
|
b5de997166 | ||
|
|
d9b7e63e47 | ||
|
|
40da7bb835 | ||
|
|
d72045932e | ||
|
|
d27e6fa7f8 | ||
|
|
2d9990ca2a | ||
|
|
4771806c44 | ||
|
|
e33fef8e42 | ||
|
|
857c30b502 | ||
|
|
243ef68199 | ||
|
|
ea8447e1c5 | ||
|
|
0312c30a73 | ||
|
|
396439bf86 | ||
|
|
80814f643f | ||
|
|
1c05aff424 | ||
|
|
2497c02e38 | ||
|
|
e467fb7202 | ||
|
|
aa439b7e39 | ||
|
|
623eb05bf6 | ||
|
|
d2eaa51509 | ||
|
|
97aad167a6 | ||
|
|
1f8b97aeff | ||
|
|
da1aa962e2 | ||
|
|
22fb03d7e0 | ||
|
|
9c8e085677 | ||
|
|
d2f79d835d | ||
|
|
7c3070628a | ||
|
|
b2d1d6f3e9 | ||
|
|
04832e5aa4 | ||
|
|
766983f69b | ||
|
|
75ed1dd49e | ||
|
|
4e412381f2 | ||
|
|
e9db0338d2 | ||
|
|
711dd6602e | ||
|
|
babdc21614 | ||
|
|
55e280d200 | ||
|
|
29325d7cb3 | ||
|
|
f865da26ba | ||
|
|
b1c93bb9fc | ||
|
|
661321fda7 | ||
|
|
9caee3248b | ||
|
|
2e2e577a09 | ||
|
|
132f8fa3ce | ||
|
|
e84e5710e4 | ||
|
|
425711927a | ||
|
|
69db752067 | ||
|
|
ec6aebabff | ||
|
|
6e179fb7cd | ||
|
|
71ce49b7a5 | ||
|
|
a6b29a0b1a | ||
|
|
9fde7d2828 | ||
|
|
b63905f7f9 | ||
|
|
ddde7e333c | ||
|
|
50a58e108a | ||
|
|
4b1f01ada2 | ||
|
|
fcf5cc3981 | ||
|
|
1b99c9976a | ||
|
|
5429b5f9cc | ||
|
|
fec81947bd | ||
|
|
8917f81cb5 | ||
|
|
5b01e41b24 | ||
|
|
bc4b118ede | ||
|
|
b47e89a397 | ||
|
|
1e42fea0af | ||
|
|
aceaaa69eb | ||
|
|
81ad810186 | ||
|
|
484f63b1db | ||
|
|
1497e42fc5 | ||
|
|
86709c15cb | ||
|
|
f40a7b4609 | ||
|
|
ba9ef00ab9 | ||
|
|
a0440daf98 | ||
|
|
a2f73b4d77 | ||
|
|
2ed2d20dfe | ||
|
|
89e26e92b6 | ||
|
|
6a699302c8 | ||
|
|
1a68585990 | ||
|
|
184bb1151a | ||
|
|
4a137aa840 | ||
|
|
92fc92835f | ||
|
|
369e30f685 | ||
|
|
6c812c8124 | ||
|
|
d230629e61 | ||
|
|
92d7324f15 | ||
|
|
a142ed50ff | ||
|
|
02d875869a | ||
|
|
ef339250b5 | ||
|
|
cfeae15c1f | ||
|
|
6b2c88feec | ||
|
|
f8b36491d7 | ||
|
|
5e160f168d | ||
|
|
792b2db23c | ||
|
|
aa19232609 | ||
|
|
709aa5f259 | ||
|
|
a852227279 | ||
|
|
ff00e1496c | ||
|
|
1db2f07192 | ||
|
|
4b5385b2f0 | ||
|
|
057f5ffc79 | ||
|
|
f0afbc237e | ||
|
|
f619988476 | ||
|
|
85a6734387 | ||
|
|
e0adedde78 | ||
|
|
120c32c52c | ||
|
|
0206ab2bac | ||
|
|
38c5be59b8 | ||
|
|
41612f37b0 | ||
|
|
4933034334 | ||
|
|
aff1841b3d | ||
|
|
7c0a332b81 |
@@ -1,3 +1,5 @@
|
||||
**/node_modules/**/.*js
|
||||
# node_modules ignored by default
|
||||
|
||||
**/staticBundle.js
|
||||
**/main.js
|
||||
Libraries/vendor/**/*
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"document": false,
|
||||
"escape": false,
|
||||
"exports": false,
|
||||
"fetch": false,
|
||||
"global": false,
|
||||
"jest": false,
|
||||
"Map": true,
|
||||
@@ -167,7 +168,7 @@
|
||||
"no-underscore-dangle": 0, // disallow dangling underscores in identifiers
|
||||
"no-wrap-func": 1, // disallow wrapping of non-IIFE statements in parens
|
||||
"no-mixed-spaces-and-tabs": 1, // disallow mixed spaces and tabs for indentation
|
||||
"quotes": [1, "single"], // specify whether double or single quotes should be used
|
||||
"quotes": [1, "single", "avoid-escape"], // specify whether double or single quotes should be used
|
||||
"quote-props": 0, // require quotes around object literal property names (off by default)
|
||||
"semi": 1, // require or disallow use of semicolons instead of ASI
|
||||
"sort-vars": 0, // sort variables within the same declaration block (off by default)
|
||||
|
||||
@@ -37,4 +37,4 @@ Examples/UIExplorer/ImageMocks.js
|
||||
module.system=haste
|
||||
|
||||
[version]
|
||||
0.10.0
|
||||
0.11.0
|
||||
|
||||
@@ -27,3 +27,4 @@ project.xcworkspace
|
||||
|
||||
# Node
|
||||
node_modules
|
||||
*.log
|
||||
|
||||
@@ -19,8 +19,8 @@ The core team will be monitoring for pull requests. When we get one, we'll run s
|
||||
1. Fork the repo and create your branch from `master`.
|
||||
2. If you've added code that should be tested, add tests!
|
||||
3. If you've changed APIs, update the documentation.
|
||||
4. Ensure the test suite passes.
|
||||
5. Make sure your code lints - we've done our best to make sure these rules match our internal linting guidelines.
|
||||
4. Ensure tests pass on Travis.
|
||||
5. Make sure your code lints (`node linter.js <files touched>`).
|
||||
6. If you haven't already, complete the CLA.
|
||||
|
||||
### Contributor License Agreement ("CLA")
|
||||
|
||||
@@ -150,7 +150,7 @@ class Game2048 extends React.Component {
|
||||
startX: number;
|
||||
startY: number;
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
this.state = {
|
||||
board: new GameBoard(),
|
||||
|
||||
@@ -7,10 +7,8 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
00481BE81AC0C86700671115 /* libRCTWebSocketDebugger.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00481BE61AC0C7FA00671115 /* libRCTWebSocketDebugger.a */; };
|
||||
008F07F31AC5B25A0029DE68 /* main.jsbundle in Resources */ = {isa = PBXBuildFile; fileRef = 008F07F21AC5B25A0029DE68 /* main.jsbundle */; };
|
||||
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
|
||||
00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */; };
|
||||
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
|
||||
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
|
||||
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
|
||||
@@ -18,6 +16,7 @@
|
||||
00E356F31AD99517003FC87E /* SampleAppTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* SampleAppTests.m */; };
|
||||
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
|
||||
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
|
||||
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
@@ -27,13 +26,6 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
00481BE51AC0C7FA00671115 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
|
||||
remoteInfo = RCTWebSocketDebugger;
|
||||
};
|
||||
00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
|
||||
@@ -41,13 +33,6 @@
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RCTActionSheet;
|
||||
};
|
||||
00C302B31ABCB8E700DB3ED1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
|
||||
remoteInfo = RCTAdSupport;
|
||||
};
|
||||
00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
|
||||
@@ -90,6 +75,13 @@
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RCTSettings;
|
||||
};
|
||||
139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
|
||||
remoteInfo = RCTWebSocket;
|
||||
};
|
||||
146834031AC3E56700842450 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
|
||||
@@ -114,10 +106,8 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocketDebugger.xcodeproj; path = ../../Libraries/RCTWebSocketDebugger/RCTWebSocketDebugger.xcodeproj; sourceTree = "<group>"; };
|
||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = main.jsbundle; path = iOS/main.jsbundle; sourceTree = "<group>"; };
|
||||
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../../Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = "<group>"; };
|
||||
00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = ../../Libraries/AdSupport/RCTAdSupport.xcodeproj; sourceTree = "<group>"; };
|
||||
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../../Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = "<group>"; };
|
||||
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = "<group>"; };
|
||||
00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = "<group>"; };
|
||||
@@ -126,6 +116,7 @@
|
||||
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
00E356F21AD99517003FC87E /* SampleAppTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleAppTests.m; sourceTree = "<group>"; };
|
||||
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = ../../Libraries/Settings/RCTSettings.xcodeproj; sourceTree = "<group>"; };
|
||||
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../../Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* SampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = iOS/AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = iOS/AppDelegate.m; sourceTree = "<group>"; };
|
||||
@@ -151,30 +142,21 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
146834051AC3E58100842450 /* libReact.a in Frameworks */,
|
||||
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,
|
||||
00481BE81AC0C86700671115 /* libRCTWebSocketDebugger.a in Frameworks */,
|
||||
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
|
||||
00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */,
|
||||
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
|
||||
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
|
||||
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,
|
||||
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,
|
||||
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
|
||||
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,
|
||||
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
|
||||
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
|
||||
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
00481BDC1AC0C7FA00671115 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00481BE61AC0C7FA00671115 /* libRCTWebSocketDebugger.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
00C302A81ABCB8CE00DB3ED1 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -183,14 +165,6 @@
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
00C302B01ABCB8E700DB3ED1 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
00C302B61ABCB90400DB3ED1 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -248,6 +222,14 @@
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
139FDEE71B06529A00C62182 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13B07FAE1A68108700A75B9A /* SampleApp */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -283,7 +265,6 @@
|
||||
children = (
|
||||
146833FF1AC3E56700842450 /* React.xcodeproj */,
|
||||
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
|
||||
00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */,
|
||||
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
|
||||
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,
|
||||
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,
|
||||
@@ -291,7 +272,7 @@
|
||||
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */,
|
||||
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
|
||||
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
|
||||
00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */,
|
||||
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
@@ -394,10 +375,6 @@
|
||||
ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;
|
||||
ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 00C302B01ABCB8E700DB3ED1 /* Products */;
|
||||
ProjectRef = 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;
|
||||
ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
|
||||
@@ -427,8 +404,8 @@
|
||||
ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 00481BDC1AC0C7FA00671115 /* Products */;
|
||||
ProjectRef = 00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */;
|
||||
ProductGroup = 139FDEE71B06529A00C62182 /* Products */;
|
||||
ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 146834001AC3E56700842450 /* Products */;
|
||||
@@ -444,13 +421,6 @@
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
00481BE61AC0C7FA00671115 /* libRCTWebSocketDebugger.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTWebSocketDebugger.a;
|
||||
remoteRef = 00481BE51AC0C7FA00671115 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
@@ -458,13 +428,6 @@
|
||||
remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTAdSupport.a;
|
||||
remoteRef = 00C302B31ABCB8E700DB3ED1 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
@@ -500,6 +463,13 @@
|
||||
remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTWebSocket.a;
|
||||
remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
146834041AC3E56700842450 /* libReact.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
|
||||
@@ -31,3 +31,6 @@ node_modules/react-native/Libraries/react-native/react-native-interface.js
|
||||
|
||||
[options]
|
||||
module.system=haste
|
||||
|
||||
[version]
|
||||
0.11.0
|
||||
|
||||
@@ -95,9 +95,98 @@ exports.examples = [{
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Prompt',
|
||||
render(): React.Component {
|
||||
return <PromptExample />
|
||||
}
|
||||
}];
|
||||
|
||||
class PromptExample extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.promptResponse = this.promptResponse.bind(this);
|
||||
this.state = {
|
||||
promptValue: undefined,
|
||||
};
|
||||
|
||||
this.title = 'Type a value';
|
||||
this.defaultValue = 'Default value';
|
||||
this.buttons = [{
|
||||
text: 'Custom cancel',
|
||||
}, {
|
||||
text: 'Custom OK',
|
||||
onPress: this.promptResponse
|
||||
}];
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{marginBottom: 10}}>
|
||||
<Text style={{fontWeight: 'bold'}}>Prompt value:</Text> {this.state.promptValue}
|
||||
</Text>
|
||||
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
onPress={this.prompt.bind(this, this.title, this.promptResponse)}>
|
||||
|
||||
<View style={styles.button}>
|
||||
<Text>
|
||||
prompt with title & callback
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
onPress={this.prompt.bind(this, this.title, this.buttons)}>
|
||||
|
||||
<View style={styles.button}>
|
||||
<Text>
|
||||
prompt with title & custom buttons
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
onPress={this.prompt.bind(this, this.title, this.defaultValue, this.promptResponse)}>
|
||||
|
||||
<View style={styles.button}>
|
||||
<Text>
|
||||
prompt with title, default value & callback
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
onPress={this.prompt.bind(this, this.title, this.defaultValue, this.buttons)}>
|
||||
|
||||
<View style={styles.button}>
|
||||
<Text>
|
||||
prompt with title, default value & custom buttons
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
prompt() {
|
||||
// Flow's apply support is broken: #7035621
|
||||
((AlertIOS.prompt: any).apply: any)(AlertIOS, arguments);
|
||||
}
|
||||
|
||||
promptResponse(promptValue) {
|
||||
this.setState({ promptValue });
|
||||
}
|
||||
}
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
wrapper: {
|
||||
borderRadius: 5,
|
||||
|
||||
@@ -68,6 +68,18 @@ var styles = StyleSheet.create({
|
||||
borderLeftWidth: 40,
|
||||
borderLeftColor: 'blue',
|
||||
},
|
||||
border6: {
|
||||
borderTopWidth: 10,
|
||||
borderTopColor: 'red',
|
||||
borderRightWidth: 20,
|
||||
borderRightColor: 'yellow',
|
||||
borderBottomWidth: 30,
|
||||
borderBottomColor: 'green',
|
||||
borderLeftWidth: 40,
|
||||
borderLeftColor: 'blue',
|
||||
|
||||
borderTopLeftRadius: 100,
|
||||
},
|
||||
});
|
||||
|
||||
exports.title = 'Border';
|
||||
@@ -115,4 +127,11 @@ exports.examples = [
|
||||
return <View style={[styles.box, styles.border5]} />;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Custom Borders',
|
||||
description: 'border*Width & border*Color',
|
||||
render() {
|
||||
return <View style={[styles.box, styles.border6]} />;
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @providesModule ExampleTypes
|
||||
* @flow
|
||||
*/
|
||||
|
||||
export type Example = {
|
||||
title: string,
|
||||
render: () => ?ReactElement<any, any, any>,
|
||||
description?: string,
|
||||
};
|
||||
|
||||
export type ExampleModule = {
|
||||
title: string;
|
||||
description: string;
|
||||
examples: Array<Example>;
|
||||
external?: bool;
|
||||
};
|
||||
@@ -29,7 +29,7 @@ var regionText = {
|
||||
longitude: '0',
|
||||
latitudeDelta: '0',
|
||||
longitudeDelta: '0',
|
||||
}
|
||||
};
|
||||
|
||||
var MapRegionInput = React.createClass({
|
||||
|
||||
@@ -168,7 +168,7 @@ var MapViewExample = React.createClass({
|
||||
/>
|
||||
<MapRegionInput
|
||||
onChange={this._onRegionInputChanged}
|
||||
region={this.state.mapRegionInput}
|
||||
region={this.state.mapRegionInput || undefined}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -45,7 +45,7 @@ var NavigatorIOSColors = React.createClass({
|
||||
|
||||
render: function() {
|
||||
// Set StatusBar with light contents to get better contrast
|
||||
StatusBarIOS.setStyle(StatusBarIOS.Style['lightContent']);
|
||||
StatusBarIOS.setStyle(StatusBarIOS.Style.lightContent);
|
||||
|
||||
return (
|
||||
<NavigatorIOS
|
||||
|
||||
@@ -181,7 +181,13 @@ var BoxOnlyExample = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
var exampleClasses = [
|
||||
type ExampleClass = {
|
||||
Component: ReactClass<any, any, any>,
|
||||
title: string,
|
||||
description: string,
|
||||
};
|
||||
|
||||
var exampleClasses: Array<ExampleClass> = [
|
||||
{
|
||||
Component: NoneExample,
|
||||
title: '`none`',
|
||||
|
||||
@@ -78,7 +78,7 @@ var TabBarExample = React.createClass({
|
||||
this.setState({
|
||||
selectedTab: 'greenTab',
|
||||
presses: this.state.presses + 1
|
||||
});
|
||||
});
|
||||
}}>
|
||||
{this._renderContent('#21551C', 'Green Tab')}
|
||||
</TabBarIOS.Item>
|
||||
|
||||
@@ -218,6 +218,26 @@ exports.examples = [
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Letter Spacing',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{letterSpacing: 0}}>
|
||||
letterSpacing = 0
|
||||
</Text>
|
||||
<Text style={{letterSpacing: 2, marginTop: 5}}>
|
||||
letterSpacing = 2
|
||||
</Text>
|
||||
<Text style={{letterSpacing: 9, marginTop: 5}}>
|
||||
letterSpacing = 9
|
||||
</Text>
|
||||
<Text style={{letterSpacing: -1, marginTop: 5}}>
|
||||
letterSpacing = -1
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Spaces',
|
||||
render: function() {
|
||||
|
||||
@@ -387,7 +387,7 @@ exports.examples = [
|
||||
<View style={styles.multilineChild}/>
|
||||
</TextInput>
|
||||
</View>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
004D28A31AAF61C70097A701 /* UIExplorerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 004D28A21AAF61C70097A701 /* UIExplorerTests.m */; };
|
||||
00D2771A1AB8C3E100DC1E48 /* libRCTWebSocketDebugger.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00D277131AB8C2C700DC1E48 /* libRCTWebSocketDebugger.a */; };
|
||||
13417FE91AA91432003F314A /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FE81AA91428003F314A /* libRCTImage.a */; };
|
||||
134180011AA9153C003F314A /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FEF1AA914B8003F314A /* libRCTText.a */; };
|
||||
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341802B1AA91779003F314A /* libRCTNetwork.a */; };
|
||||
134454601AAFCABD003F0779 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1344545A1AAFCAAE003F0779 /* libRCTAdSupport.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 */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
@@ -34,13 +35,6 @@
|
||||
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
||||
remoteInfo = UIExplorer;
|
||||
};
|
||||
00D277121AB8C2C700DC1E48 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 00D2770E1AB8C2C700DC1E48 /* RCTWebSocketDebugger.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
|
||||
remoteInfo = RCTWebSocketDebugger;
|
||||
};
|
||||
13417FE71AA91428003F314A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 13417FE31AA91428003F314A /* RCTImage.xcodeproj */;
|
||||
@@ -76,6 +70,13 @@
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RCTGeolocation;
|
||||
};
|
||||
139FDED81B0651EA00C62182 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 139FDECA1B0651EA00C62182 /* RCTWebSocket.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
|
||||
remoteInfo = RCTWebSocket;
|
||||
};
|
||||
147CED4A1AB34F8C00DA3E4C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */;
|
||||
@@ -124,12 +125,13 @@
|
||||
004D289E1AAF61C70097A701 /* UIExplorerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UIExplorerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
004D28A11AAF61C70097A701 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
004D28A21AAF61C70097A701 /* UIExplorerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UIExplorerTests.m; sourceTree = "<group>"; };
|
||||
00D2770E1AB8C2C700DC1E48 /* RCTWebSocketDebugger.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocketDebugger.xcodeproj; path = ../../Libraries/RCTWebSocketDebugger/RCTWebSocketDebugger.xcodeproj; sourceTree = "<group>"; };
|
||||
13417FE31AA91428003F314A /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = "<group>"; };
|
||||
13417FEA1AA914B8003F314A /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = UIExplorer/AppDelegate.m; sourceTree = "<group>"; };
|
||||
@@ -157,18 +159,18 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */,
|
||||
14AADF051AC3DBB1002390C9 /* libReact.a in Frameworks */,
|
||||
00D2771A1AB8C3E100DC1E48 /* libRCTWebSocketDebugger.a in Frameworks */,
|
||||
58005BF21ABA80A60062E044 /* libRCTTest.a in Frameworks */,
|
||||
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */,
|
||||
14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */,
|
||||
147CED4C1AB3532B00DA3E4C /* libRCTActionSheet.a in Frameworks */,
|
||||
134454601AAFCABD003F0779 /* libRCTAdSupport.a in Frameworks */,
|
||||
134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */,
|
||||
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */,
|
||||
134180011AA9153C003F314A /* libRCTText.a in Frameworks */,
|
||||
13417FE91AA91432003F314A /* libRCTImage.a in Frameworks */,
|
||||
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */,
|
||||
14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */,
|
||||
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */,
|
||||
58005BF21ABA80A60062E044 /* libRCTTest.a in Frameworks */,
|
||||
134180011AA9153C003F314A /* libRCTText.a in Frameworks */,
|
||||
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */,
|
||||
139FDEDB1B0651FB00C62182 /* libRCTWebSocket.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -179,6 +181,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
004D28A21AAF61C70097A701 /* UIExplorerTests.m */,
|
||||
1353F5451B0E64F9009B4FAC /* ClippingTests.m */,
|
||||
004D28A01AAF61C70097A701 /* Supporting Files */,
|
||||
);
|
||||
path = UIExplorerTests;
|
||||
@@ -192,14 +195,6 @@
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
00D2770F1AB8C2C700DC1E48 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00D277131AB8C2C700DC1E48 /* libRCTWebSocketDebugger.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1316A21D1AA397F400C0188E /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -213,8 +208,8 @@
|
||||
13CC9D481AEED2B90020D1C2 /* RCTSettings.xcodeproj */,
|
||||
58005BE41ABA80530062E044 /* RCTTest.xcodeproj */,
|
||||
13417FEA1AA914B8003F314A /* RCTText.xcodeproj */,
|
||||
00D2770E1AB8C2C700DC1E48 /* RCTWebSocketDebugger.xcodeproj */,
|
||||
D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */,
|
||||
139FDECA1B0651EA00C62182 /* RCTWebSocket.xcodeproj */,
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
@@ -259,6 +254,14 @@
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
139FDECB1B0651EA00C62182 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
139FDED91B0651EA00C62182 /* libRCTWebSocket.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13B07FAE1A68108700A75B9A /* UIExplorer */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -447,8 +450,8 @@
|
||||
ProjectRef = D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 00D2770F1AB8C2C700DC1E48 /* Products */;
|
||||
ProjectRef = 00D2770E1AB8C2C700DC1E48 /* RCTWebSocketDebugger.xcodeproj */;
|
||||
ProductGroup = 139FDECB1B0651EA00C62182 /* Products */;
|
||||
ProjectRef = 139FDECA1B0651EA00C62182 /* RCTWebSocket.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 14AADF001AC3DB95002390C9 /* Products */;
|
||||
@@ -464,13 +467,6 @@
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
00D277131AB8C2C700DC1E48 /* libRCTWebSocketDebugger.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTWebSocketDebugger.a;
|
||||
remoteRef = 00D277121AB8C2C700DC1E48 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
13417FE81AA91428003F314A /* libRCTImage.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
@@ -506,6 +502,13 @@
|
||||
remoteRef = 134A8A241AACED6A00945AAE /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
139FDED91B0651EA00C62182 /* libRCTWebSocket.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTWebSocket.a;
|
||||
remoteRef = 139FDED81B0651EA00C62182 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
147CED4B1AB34F8C00DA3E4C /* libRCTActionSheet.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
@@ -575,6 +578,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
004D28A31AAF61C70097A701 /* UIExplorerTests.m in Sources */,
|
||||
1353F5461B0E64F9009B4FAC /* ClippingTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -3,37 +3,37 @@
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x.png",
|
||||
"filename" : "Icon-Small@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-1.png",
|
||||
"filename" : "Icon-Small@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-2.png",
|
||||
"filename" : "Icon-40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-3.png",
|
||||
"filename" : "Icon-40@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-5.png",
|
||||
"filename" : "Icon-60@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-4.png",
|
||||
"filename" : "Icon-60@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
@@ -41,4 +41,4 @@
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 31 KiB |
@@ -69,9 +69,10 @@ var styles = StyleSheet.create({
|
||||
overflow: 'hidden',
|
||||
},
|
||||
titleContainer: {
|
||||
borderWidth: 0.5,
|
||||
borderRadius: 2.5,
|
||||
borderColor: '#d6d7da',
|
||||
borderBottomWidth: 0.5,
|
||||
borderTopLeftRadius: 3,
|
||||
borderTopRightRadius: 2.5,
|
||||
borderBottomColor: '#d6d7da',
|
||||
backgroundColor: '#f6f7f8',
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 5,
|
||||
|
||||
@@ -30,6 +30,8 @@ var {
|
||||
var { TestModule } = React.addons;
|
||||
var Settings = require('Settings');
|
||||
|
||||
import type { Example, ExampleModule } from 'ExampleTypes';
|
||||
|
||||
var createExamplePage = require('./createExamplePage');
|
||||
|
||||
var COMPONENTS = [
|
||||
@@ -107,9 +109,17 @@ COMPONENTS.concat(APIS).forEach((Example) => {
|
||||
}
|
||||
});
|
||||
|
||||
class UIExplorerList extends React.Component {
|
||||
type Props = {
|
||||
navigator: Array<{title: string, component: ReactClass<any,any,any>}>,
|
||||
onExternalExampleRequested: Function,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
|
||||
|
||||
class UIExplorerList extends React.Component {
|
||||
props: Props;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
dataSource: ds.cloneWithRowsAndSections({
|
||||
@@ -149,7 +159,7 @@ class UIExplorerList extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
_renderSectionHeader(data, section) {
|
||||
_renderSectionHeader(data: any, section: string) {
|
||||
return (
|
||||
<View style={styles.sectionHeader}>
|
||||
<Text style={styles.sectionHeaderTitle}>
|
||||
@@ -159,7 +169,7 @@ class UIExplorerList extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
_renderRow(example, i) {
|
||||
_renderRow(example: ExampleModule, i: number) {
|
||||
return (
|
||||
<View key={i}>
|
||||
<TouchableHighlight onPress={() => this._onPressRow(example)}>
|
||||
@@ -177,7 +187,7 @@ class UIExplorerList extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
_search(text) {
|
||||
_search(text: mixed) {
|
||||
var regex = new RegExp(text, 'i');
|
||||
var filter = (component) => regex.test(component.title);
|
||||
|
||||
@@ -191,7 +201,7 @@ class UIExplorerList extends React.Component {
|
||||
Settings.set({searchText: text});
|
||||
}
|
||||
|
||||
_onPressRow(example) {
|
||||
_onPressRow(example: ExampleModule) {
|
||||
if (example.external) {
|
||||
this.props.onExternalExampleRequested(example);
|
||||
return;
|
||||
|
||||
@@ -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
|
||||
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 264 KiB After Width: | Height: | Size: 352 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 140 KiB |
@@ -88,35 +88,19 @@
|
||||
XCTAssertTrue(foundElement, @"Cound't find element with '<View>' text in %d seconds", TIMEOUT_SECONDS);
|
||||
}
|
||||
|
||||
- (void)testViewExampleSnapshot
|
||||
{
|
||||
[_runner runTest:_cmd module:@"ViewExample"];
|
||||
#define RCT_SNAPSHOT_TEST(name, reRecord) \
|
||||
- (void)test##name##Snapshot \
|
||||
{ \
|
||||
_runner.recordMode |= reRecord; \
|
||||
[_runner runTest:_cmd module:@#name]; \
|
||||
}
|
||||
|
||||
- (void)testLayoutExampleSnapshot
|
||||
{
|
||||
[_runner runTest:_cmd module:@"LayoutExample"];
|
||||
}
|
||||
|
||||
- (void)testTextExampleSnapshot
|
||||
{
|
||||
[_runner runTest:_cmd module:@"TextExample"];
|
||||
}
|
||||
|
||||
- (void)testSwitchExampleSnapshot
|
||||
{
|
||||
[_runner runTest:_cmd module:@"SwitchExample"];
|
||||
}
|
||||
|
||||
- (void)testSliderExampleSnapshot
|
||||
{
|
||||
[_runner runTest:_cmd module:@"SliderExample"];
|
||||
}
|
||||
|
||||
- (void)testTabBarExampleSnapshot
|
||||
{
|
||||
[_runner runTest:_cmd module:@"TabBarExample"];
|
||||
}
|
||||
RCT_SNAPSHOT_TEST(ViewExample, NO)
|
||||
RCT_SNAPSHOT_TEST(LayoutExample, NO)
|
||||
RCT_SNAPSHOT_TEST(TextExample, NO)
|
||||
RCT_SNAPSHOT_TEST(SwitchExample, NO)
|
||||
RCT_SNAPSHOT_TEST(SliderExample, NO)
|
||||
RCT_SNAPSHOT_TEST(TabBarExample, NO)
|
||||
|
||||
// Make sure this test runs last
|
||||
- (void)testZZZ_NotInRecordMode
|
||||
|
||||
@@ -17,22 +17,13 @@
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var ReactIOS = require('ReactIOS');
|
||||
var ReactNative = require('ReactNative');
|
||||
var UIExplorerBlock = require('./UIExplorerBlock');
|
||||
var UIExplorerPage = require('./UIExplorerPage');
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
||||
class Example extends React.Component {
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
type ExampleModule = {
|
||||
title: string;
|
||||
description: string;
|
||||
examples: Array<Example>;
|
||||
};
|
||||
import type { Example, ExampleModule } from 'ExampleTypes';
|
||||
|
||||
var createExamplePage = function(title: ?string, exampleModule: ExampleModule)
|
||||
: ReactClass<any, any, any> {
|
||||
@@ -44,20 +35,20 @@ var createExamplePage = function(title: ?string, exampleModule: ExampleModule)
|
||||
description: exampleModule.description,
|
||||
},
|
||||
|
||||
getBlock: function(example, i) {
|
||||
getBlock: function(example: Example, i) {
|
||||
// Hack warning: This is a hack because the www UI explorer requires
|
||||
// renderComponent to be called.
|
||||
var originalRender = React.render;
|
||||
var originalRenderComponent = React.renderComponent;
|
||||
var originalIOSRender = ReactIOS.render;
|
||||
var originalIOSRenderComponent = ReactIOS.renderComponent;
|
||||
var originalIOSRender = ReactNative.render;
|
||||
var originalIOSRenderComponent = ReactNative.renderComponent;
|
||||
var renderedComponent;
|
||||
// TODO remove typecasts when Flow bug #6560135 is fixed
|
||||
// and workaround is removed from react-native.js
|
||||
(React: Object).render =
|
||||
(React: Object).renderComponent =
|
||||
(ReactIOS: Object).render =
|
||||
(ReactIOS: Object).renderComponent =
|
||||
(ReactNative: Object).render =
|
||||
(ReactNative: Object).renderComponent =
|
||||
function(element, container) {
|
||||
renderedComponent = element;
|
||||
};
|
||||
@@ -67,8 +58,8 @@ var createExamplePage = function(title: ?string, exampleModule: ExampleModule)
|
||||
}
|
||||
(React: Object).render = originalRender;
|
||||
(React: Object).renderComponent = originalRenderComponent;
|
||||
(ReactIOS: Object).render = originalIOSRender;
|
||||
(ReactIOS: Object).renderComponent = originalIOSRenderComponent;
|
||||
(ReactNative: Object).render = originalIOSRender;
|
||||
(ReactNative: Object).renderComponent = originalIOSRenderComponent;
|
||||
return (
|
||||
<UIExplorerBlock
|
||||
key={i}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @providesModule AppEventsTest
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
NativeAppEventEmitter,
|
||||
NativeModules,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
var TestModule = NativeModules.TestModule || NativeModules.SnapshotTestManager;
|
||||
|
||||
var deepDiffer = require('deepDiffer');
|
||||
|
||||
var TEST_PAYLOAD = {foo: 'bar'};
|
||||
|
||||
var AppEventsTest = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {sent: 'none', received: 'none'};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
NativeAppEventEmitter.addListener('testEvent', this.receiveEvent);
|
||||
var event = {data: TEST_PAYLOAD, ts: Date.now()};
|
||||
TestModule.sendAppEvent('testEvent', event);
|
||||
this.setState({sent: event});
|
||||
},
|
||||
receiveEvent: function(event: any) {
|
||||
if (deepDiffer(event.data, TEST_PAYLOAD)) {
|
||||
throw new Error('Received wrong event: ' + JSON.stringify(event));
|
||||
}
|
||||
var elapsed = (Date.now() - event.ts) + 'ms';
|
||||
this.setState({received: event, elapsed}, TestModule.markTestCompleted);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text>
|
||||
{JSON.stringify(this.state, null, ' ')}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
margin: 40,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = AppEventsTest;
|
||||
@@ -26,6 +26,7 @@ var TESTS = [
|
||||
require('./TimersTest'),
|
||||
require('./AsyncStorageTest'),
|
||||
require('./LayoutEventsTest'),
|
||||
require('./AppEventsTest'),
|
||||
require('./SimpleSnapshotTest'),
|
||||
];
|
||||
|
||||
|
||||
@@ -76,6 +76,11 @@
|
||||
[_runner runTest:_cmd module:@"LayoutEventsTest"];
|
||||
}
|
||||
|
||||
- (void)testAppEvents
|
||||
{
|
||||
[_runner runTest:_cmd module:@"AppEventsTest"];
|
||||
}
|
||||
|
||||
#pragma mark Snapshot Tests
|
||||
|
||||
- (void)testSimpleSnapshot
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
*
|
||||
* @providesModule ARTSerializablePath
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
// TODO: Move this into an ART mode called "serialized" or something
|
||||
|
||||
|
||||
@@ -6,19 +6,18 @@
|
||||
* 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.
|
||||
*
|
||||
* @providesModule ReactIOSART
|
||||
* @providesModule ReactNativeART
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var Color = require('art/core/color');
|
||||
var Path = require('ARTSerializablePath');
|
||||
var Transform = require('art/core/transform');
|
||||
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
|
||||
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
var merge = require('merge');
|
||||
|
||||
// Diff Helpers
|
||||
@@ -64,7 +63,7 @@ function fontAndLinesDiffer(a, b) {
|
||||
|
||||
// Native Attributes
|
||||
|
||||
var SurfaceViewAttributes = merge(ReactIOSViewAttributes.UIView, {
|
||||
var SurfaceViewAttributes = merge(ReactNativeViewAttributes.UIView, {
|
||||
// This should contain pixel information such as width, height and
|
||||
// resolution to know what kind of buffer needs to be allocated.
|
||||
// Currently we rely on UIViews and style to figure that out.
|
||||
@@ -100,22 +99,22 @@ var TextAttributes = merge(RenderableAttributes, {
|
||||
|
||||
// Native Components
|
||||
|
||||
var NativeSurfaceView = createReactIOSNativeComponentClass({
|
||||
var NativeSurfaceView = createReactNativeComponentClass({
|
||||
validAttributes: SurfaceViewAttributes,
|
||||
uiViewClassName: 'ARTSurfaceView',
|
||||
});
|
||||
|
||||
var NativeGroup = createReactIOSNativeComponentClass({
|
||||
var NativeGroup = createReactNativeComponentClass({
|
||||
validAttributes: GroupAttributes,
|
||||
uiViewClassName: 'ARTGroup',
|
||||
});
|
||||
|
||||
var NativeShape = createReactIOSNativeComponentClass({
|
||||
var NativeShape = createReactNativeComponentClass({
|
||||
validAttributes: ShapeAttributes,
|
||||
uiViewClassName: 'ARTShape',
|
||||
});
|
||||
|
||||
var NativeText = createReactIOSNativeComponentClass({
|
||||
var NativeText = createReactNativeComponentClass({
|
||||
validAttributes: TextAttributes,
|
||||
uiViewClassName: 'ARTText',
|
||||
});
|
||||
@@ -12,6 +12,7 @@
|
||||
'use strict';
|
||||
|
||||
var RCTAnimationManager = require('NativeModules').AnimationExperimentalManager;
|
||||
var React = require('React');
|
||||
var AnimationUtils = require('AnimationUtils');
|
||||
|
||||
type EasingFunction = (t: number) => number;
|
||||
@@ -47,7 +48,7 @@ var AnimationExperimental = {
|
||||
},
|
||||
callback?: ?(finished: bool) => void
|
||||
): number {
|
||||
var nodeHandle = anim.node.getNodeHandle();
|
||||
var nodeHandle = React.findNodeHandle(anim.node);
|
||||
var easingSample = AnimationUtils.evaluateEasingFunction(
|
||||
anim.duration,
|
||||
anim.easing
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
'use strict';
|
||||
|
||||
var POPAnimationOrNull = require('POPAnimation');
|
||||
var React = require('React');
|
||||
|
||||
if (!POPAnimationOrNull) {
|
||||
// POP animation isn't available in the OSS fork - this is a temporary
|
||||
@@ -83,7 +84,7 @@ var POPAnimationMixin = {
|
||||
'Invalid refKey ' + refKey + ' for anim:\n' + JSON.stringify(anim) +
|
||||
'\nvalid refs: ' + JSON.stringify(Object.keys(this.refs))
|
||||
);
|
||||
var refNodeHandle = this.refs[refKey].getNodeHandle();
|
||||
var refNodeHandle = React.findNodeHandle(this.refs[refKey]);
|
||||
this.startAnimationWithNodeHandle(refNodeHandle, animID, doneCallback);
|
||||
},
|
||||
|
||||
@@ -192,7 +193,7 @@ var POPAnimationMixin = {
|
||||
*/
|
||||
stopAnimations: function(refKey: string) {
|
||||
invariant(this.refs[refKey], 'invalid ref');
|
||||
this.stopNodeHandleAnimations(this.refs[refKey].getNodeHandle());
|
||||
this.stopNodeHandleAnimations(React.findNodeHandle(this.refs[refKey]));
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,9 @@ var RCTPOPAnimationManager = require('NativeModules').POPAnimationManager;
|
||||
if (!RCTPOPAnimationManager) {
|
||||
// POP animation isn't available in the OSS fork - this is a temporary
|
||||
// workaround to enable its availability to be determined at runtime.
|
||||
module.exports = (null: ?Object);
|
||||
// For Flow let's pretend like we always export POPAnimation
|
||||
// so all our users don't need to do null checks
|
||||
module.exports = ((null: any): typeof POPAnimation);
|
||||
} else {
|
||||
|
||||
var ReactPropTypes = require('ReactPropTypes');
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var ReactIOSEventEmitter = require('ReactIOSEventEmitter');
|
||||
var ReactNativeEventEmitter = require('ReactNativeEventEmitter');
|
||||
|
||||
// Completely locally implemented - no native hooks.
|
||||
module.exports = ReactIOSEventEmitter;
|
||||
module.exports = ReactNativeEventEmitter;
|
||||
|
||||
@@ -92,6 +92,8 @@ var getPhotosReturnChecker = createStrictShapeTypeChecker({
|
||||
});
|
||||
|
||||
class CameraRoll {
|
||||
|
||||
static GroupTypesOptions: Array<string>;
|
||||
/**
|
||||
* Saves the image with tag `tag` to the camera roll.
|
||||
*
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
'use strict';
|
||||
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var NativeModules = require('NativeModules');
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var React = require('React');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
@@ -53,6 +52,12 @@ var ActivityIndicatorIOS = React.createClass({
|
||||
'small',
|
||||
'large',
|
||||
]),
|
||||
/**
|
||||
* Invoked on mount and layout changes with
|
||||
*
|
||||
* {nativeEvent: { layout: {x, y, width, height}}}.
|
||||
*/
|
||||
onLayout: PropTypes.func,
|
||||
},
|
||||
|
||||
getDefaultProps: function(): DefaultProps {
|
||||
@@ -65,10 +70,12 @@ var ActivityIndicatorIOS = React.createClass({
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var {style, ...props} = this.props;
|
||||
var {onLayout, style, ...props} = this.props;
|
||||
var sizeStyle = (this.props.size === 'large') ? styles.sizeLarge : styles.sizeSmall;
|
||||
return (
|
||||
<View style={[styles.container, sizeStyle, style]}>
|
||||
<View
|
||||
onLayout={onLayout}
|
||||
style={[styles.container, sizeStyle, style]}>
|
||||
<RCTActivityIndicatorView {...props} />
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -15,10 +15,10 @@ var EdgeInsetsPropType = require('EdgeInsetsPropType');
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var Platform = require('Platform');
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var View = require('View');
|
||||
|
||||
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
var deepDiffer = require('deepDiffer');
|
||||
var insetsDiffer = require('insetsDiffer');
|
||||
var merge = require('merge');
|
||||
@@ -163,9 +163,9 @@ var MapView = React.createClass({
|
||||
});
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
var RCTMap = createReactIOSNativeComponentClass({
|
||||
var RCTMap = createReactNativeComponentClass({
|
||||
validAttributes: merge(
|
||||
ReactIOSViewAttributes.UIView, {
|
||||
ReactNativeViewAttributes.UIView, {
|
||||
showsUserLocation: true,
|
||||
zoomEnabled: true,
|
||||
rotateEnabled: true,
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
var EventEmitter = require('EventEmitter');
|
||||
var Image = require('Image');
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var RCTNavigatorManager = require('NativeModules').NavigatorManager;
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var StaticContainer = require('StaticContainer.react');
|
||||
var View = require('View');
|
||||
|
||||
var createReactIOSNativeComponentClass =
|
||||
require('createReactIOSNativeComponentClass');
|
||||
var createReactNativeComponentClass =
|
||||
require('createReactNativeComponentClass');
|
||||
var invariant = require('invariant');
|
||||
var logError = require('logError');
|
||||
var merge = require('merge');
|
||||
@@ -35,14 +35,14 @@ function getuid() {
|
||||
return __uid++;
|
||||
}
|
||||
|
||||
var RCTNavigator = createReactIOSNativeComponentClass({
|
||||
validAttributes: merge(ReactIOSViewAttributes.UIView, {
|
||||
var RCTNavigator = createReactNativeComponentClass({
|
||||
validAttributes: merge(ReactNativeViewAttributes.UIView, {
|
||||
requestedTopOfStack: true
|
||||
}),
|
||||
uiViewClassName: 'RCTNavigator',
|
||||
});
|
||||
|
||||
var RCTNavigatorItem = createReactIOSNativeComponentClass({
|
||||
var RCTNavigatorItem = createReactNativeComponentClass({
|
||||
validAttributes: {
|
||||
// TODO: Remove or fix the attributes that are not fully functional.
|
||||
// NavigatorIOS does not use them all, because some are problematic
|
||||
@@ -67,7 +67,7 @@ var RCTNavigatorItem = createReactIOSNativeComponentClass({
|
||||
var NavigatorTransitionerIOS = React.createClass({
|
||||
requestSchedulingNavigation: function(cb) {
|
||||
RCTNavigatorManager.requestSchedulingJavaScriptNavigation(
|
||||
(this: any).getNodeHandle(),
|
||||
React.findNodeHandle(this),
|
||||
logError,
|
||||
cb
|
||||
);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
var NativeModules = require('NativeModules');
|
||||
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||
var React = require('React');
|
||||
var Subscribable = require('Subscribable');
|
||||
var TextInputState = require('TextInputState');
|
||||
|
||||
@@ -182,7 +183,7 @@ var ScrollResponderMixin = {
|
||||
var currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
||||
if (!this.props.keyboardShouldPersistTaps &&
|
||||
currentlyFocusedTextInput != null &&
|
||||
e.target != currentlyFocusedTextInput) {
|
||||
e.target !== currentlyFocusedTextInput) {
|
||||
return true;
|
||||
}
|
||||
return this.scrollResponderIsAnimating();
|
||||
@@ -243,7 +244,7 @@ var ScrollResponderMixin = {
|
||||
var currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
||||
if (!this.props.keyboardShouldPersistTaps &&
|
||||
currentlyFocusedTextInput != null &&
|
||||
e.target != currentlyFocusedTextInput &&
|
||||
e.target !== currentlyFocusedTextInput &&
|
||||
!this.state.observedScrollSinceBecomingResponder &&
|
||||
!this.state.becameResponderWhileAnimating) {
|
||||
this.props.onScrollResponderKeyboardDismissed &&
|
||||
@@ -350,7 +351,7 @@ var ScrollResponderMixin = {
|
||||
* can also be used to quickly scroll to any element we want to focus
|
||||
*/
|
||||
scrollResponderScrollTo: function(offsetX: number, offsetY: number) {
|
||||
RCTUIManagerDeprecated.scrollTo(this.getNodeHandle(), offsetX, offsetY);
|
||||
RCTUIManagerDeprecated.scrollTo(React.findNodeHandle(this), offsetX, offsetY);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -358,7 +359,7 @@ var ScrollResponderMixin = {
|
||||
* @param {object} rect Should have shape {x, y, width, height}
|
||||
*/
|
||||
scrollResponderZoomTo: function(rect: { x: number; y: number; width: number; height: number; }) {
|
||||
RCTUIManagerDeprecated.zoomToRect(this.getNodeHandle(), rect);
|
||||
RCTUIManagerDeprecated.zoomToRect(React.findNodeHandle(this), rect);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -376,7 +377,7 @@ var ScrollResponderMixin = {
|
||||
this.preventNegativeScrollOffset = !!preventNegativeScrollOffset;
|
||||
RCTUIManager.measureLayout(
|
||||
nodeHandle,
|
||||
this.getNodeHandle(),
|
||||
React.findNodeHandle(this),
|
||||
this.scrollResponderTextInputFocusError,
|
||||
this.scrollResponderInputMeasureAndScrollToKeyboard
|
||||
);
|
||||
|
||||
@@ -17,7 +17,7 @@ var PointPropType = require('PointPropType');
|
||||
var RCTScrollView = require('NativeModules').UIManager.RCTScrollView;
|
||||
var RCTScrollViewConsts = RCTScrollView.Constants;
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var RCTUIManager = require('NativeModules').UIManager;
|
||||
var ScrollResponder = require('ScrollResponder');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
@@ -25,7 +25,7 @@ var StyleSheetPropType = require('StyleSheetPropType');
|
||||
var View = require('View');
|
||||
var ViewStylePropTypes = require('ViewStylePropTypes');
|
||||
|
||||
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
var deepDiffer = require('deepDiffer');
|
||||
var flattenStyle = require('flattenStyle');
|
||||
var insetsDiffer = require('insetsDiffer');
|
||||
@@ -207,19 +207,19 @@ var ScrollView = React.createClass({
|
||||
},
|
||||
|
||||
getInnerViewNode: function(): any {
|
||||
return this.refs[INNERVIEW].getNodeHandle();
|
||||
return React.findNodeHandle(this.refs[INNERVIEW]);
|
||||
},
|
||||
|
||||
scrollTo: function(destY?: number, destX?: number) {
|
||||
if (Platform.OS === 'android') {
|
||||
RCTUIManager.dispatchViewManagerCommand(
|
||||
this.getNodeHandle(),
|
||||
React.findNodeHandle(this),
|
||||
RCTUIManager.RCTScrollView.Commands.scrollTo,
|
||||
[destX || 0, destY || 0]
|
||||
);
|
||||
} else {
|
||||
RCTUIManager.scrollTo(
|
||||
this.getNodeHandle(),
|
||||
React.findNodeHandle(this),
|
||||
destX || 0,
|
||||
destY || 0
|
||||
);
|
||||
@@ -228,7 +228,7 @@ var ScrollView = React.createClass({
|
||||
|
||||
scrollWithoutAnimationTo: function(destY?: number, destX?: number) {
|
||||
RCTUIManager.scrollWithoutAnimationTo(
|
||||
this.getNodeHandle(),
|
||||
React.findNodeHandle(this),
|
||||
destX || 0,
|
||||
destY || 0
|
||||
);
|
||||
@@ -343,7 +343,7 @@ var styles = StyleSheet.create({
|
||||
});
|
||||
|
||||
var validAttributes = {
|
||||
...ReactIOSViewAttributes.UIView,
|
||||
...ReactNativeViewAttributes.UIView,
|
||||
alwaysBounceHorizontal: true,
|
||||
alwaysBounceVertical: true,
|
||||
automaticallyAdjustContentInsets: true,
|
||||
@@ -370,11 +370,11 @@ var validAttributes = {
|
||||
};
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
var AndroidScrollView = createReactIOSNativeComponentClass({
|
||||
var AndroidScrollView = createReactNativeComponentClass({
|
||||
validAttributes: validAttributes,
|
||||
uiViewClassName: 'RCTScrollView',
|
||||
});
|
||||
var AndroidHorizontalScrollView = createReactIOSNativeComponentClass({
|
||||
var AndroidHorizontalScrollView = createReactNativeComponentClass({
|
||||
validAttributes: validAttributes,
|
||||
uiViewClassName: 'AndroidHorizontalScrollView',
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* 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.
|
||||
*
|
||||
* @provides StaticRenderer
|
||||
* @providesModule StaticRenderer
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var EventEmitter = require('EventEmitter');
|
||||
import type EventEmitter from 'EventEmitter';
|
||||
|
||||
/**
|
||||
* Subscribable provides a mixin for safely subscribing a component to an
|
||||
|
||||
@@ -19,14 +19,14 @@ var Platform = require('Platform');
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var React = require('React');
|
||||
var ReactChildren = require('ReactChildren');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var Text = require('Text');
|
||||
var TextInputState = require('TextInputState');
|
||||
var TimerMixin = require('react-timer-mixin');
|
||||
var TouchableWithoutFeedback = require('TouchableWithoutFeedback');
|
||||
|
||||
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
var emptyFunction = require('emptyFunction');
|
||||
var invariant = require('invariant');
|
||||
var merge = require('merge');
|
||||
@@ -35,7 +35,7 @@ var autoCapitalizeConsts = RCTUIManager.UIText.AutocapitalizationType;
|
||||
var keyboardTypeConsts = RCTUIManager.UIKeyboardType;
|
||||
var returnKeyTypeConsts = RCTUIManager.UIReturnKeyType;
|
||||
|
||||
var RCTTextViewAttributes = merge(ReactIOSViewAttributes.UIView, {
|
||||
var RCTTextViewAttributes = merge(ReactNativeViewAttributes.UIView, {
|
||||
autoCorrect: true,
|
||||
autoCapitalize: true,
|
||||
clearTextOnFocus: true,
|
||||
@@ -179,12 +179,12 @@ var TextInput = React.createClass({
|
||||
'number-pad',
|
||||
'phone-pad',
|
||||
'name-phone-pad',
|
||||
'email-address',
|
||||
'decimal-pad',
|
||||
'twitter',
|
||||
'web-search',
|
||||
// Cross-platform
|
||||
'numeric',
|
||||
'email-address',
|
||||
]),
|
||||
/**
|
||||
* Determines how the return key should look.
|
||||
@@ -232,6 +232,10 @@ var TextInput = React.createClass({
|
||||
* Callback that is called when the text input's submit button is pressed.
|
||||
*/
|
||||
onSubmitEditing: PropTypes.func,
|
||||
/**
|
||||
* Invoked on mount and layout changes with {x, y, width, height}.
|
||||
*/
|
||||
onLayout: PropTypes.func,
|
||||
/**
|
||||
* If true, the text input obscures the text entered so that sensitive text
|
||||
* like passwords stay secure. Default value is false.
|
||||
@@ -305,7 +309,7 @@ var TextInput = React.createClass({
|
||||
|
||||
isFocused: function(): boolean {
|
||||
return TextInputState.currentlyFocusedField() ===
|
||||
this.refs.input.getNativeNode();
|
||||
React.findNodeHandle(this.refs.input);
|
||||
},
|
||||
|
||||
getDefaultProps: function(): DefaultProps {
|
||||
@@ -446,6 +450,7 @@ var TextInput = React.createClass({
|
||||
onEndEditing={this.props.onEndEditing}
|
||||
onSubmitEditing={this.props.onSubmitEditing}
|
||||
onSelectionChangeShouldSetResponder={() => true}
|
||||
onLayout={this.props.onLayout}
|
||||
placeholder={this.props.placeholder}
|
||||
placeholderTextColor={this.props.placeholderTextColor}
|
||||
text={this.state.bufferedValue}
|
||||
@@ -495,6 +500,7 @@ var TextInput = React.createClass({
|
||||
onSelectionChange={this._onSelectionChange}
|
||||
onTextInput={this._onTextInput}
|
||||
onSelectionChangeShouldSetResponder={emptyFunction.thatReturnsTrue}
|
||||
onLayout={this.props.onLayout}
|
||||
placeholder={this.props.placeholder}
|
||||
placeholderTextColor={this.props.placeholderTextColor}
|
||||
text={this.state.bufferedValue}
|
||||
@@ -530,6 +536,7 @@ var TextInput = React.createClass({
|
||||
onChange={this._onChange}
|
||||
onEndEditing={this.props.onEndEditing}
|
||||
onSubmitEditing={this.props.onSubmitEditing}
|
||||
onLayout={this.props.onLayout}
|
||||
password={this.props.password || this.props.secureTextEntry}
|
||||
placeholder={this.props.placeholder}
|
||||
text={this.state.bufferedValue}
|
||||
@@ -582,7 +589,7 @@ var TextInput = React.createClass({
|
||||
var counter = event.nativeEvent.eventCounter;
|
||||
if (counter > this.state.mostRecentEventCounter) {
|
||||
this.setState({mostRecentEventCounter: counter});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -592,17 +599,17 @@ var styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
var RCTTextView = createReactIOSNativeComponentClass({
|
||||
var RCTTextView = createReactNativeComponentClass({
|
||||
validAttributes: RCTTextViewAttributes,
|
||||
uiViewClassName: 'RCTTextView',
|
||||
});
|
||||
|
||||
var RCTTextField = createReactIOSNativeComponentClass({
|
||||
var RCTTextField = createReactNativeComponentClass({
|
||||
validAttributes: RCTTextFieldAttributes,
|
||||
uiViewClassName: 'RCTTextField',
|
||||
});
|
||||
|
||||
var AndroidTextInput = createReactIOSNativeComponentClass({
|
||||
var AndroidTextInput = createReactNativeComponentClass({
|
||||
validAttributes: AndroidTextInputAttributes,
|
||||
uiViewClassName: 'AndroidTextInput',
|
||||
});
|
||||
|
||||
@@ -21,22 +21,22 @@ var TextInputState = {
|
||||
/**
|
||||
* Internal state
|
||||
*/
|
||||
_currentlyFocusedID: (null: ?string),
|
||||
_currentlyFocusedID: (null: ?number),
|
||||
|
||||
/**
|
||||
* Returns the ID of the currently focused text field, if one exists
|
||||
* If no text field is focused it returns null
|
||||
*/
|
||||
currentlyFocusedField: function(): ?string {
|
||||
currentlyFocusedField: function(): ?number {
|
||||
return this._currentlyFocusedID;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} TextInputID id of the text field to focus
|
||||
* @param {number} TextInputID id of the text field to focus
|
||||
* Focuses the specified text field
|
||||
* noop if the text field was already focused
|
||||
*/
|
||||
focusTextInput: function(textFieldID: string) {
|
||||
focusTextInput: function(textFieldID: ?number) {
|
||||
if (this._currentlyFocusedID !== textFieldID && textFieldID !== null) {
|
||||
this._currentlyFocusedID = textFieldID;
|
||||
RCTUIManager.focus(textFieldID);
|
||||
@@ -44,11 +44,11 @@ var TextInputState = {
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} textFieldID id of the text field to focus
|
||||
* @param {number} textFieldID id of the text field to focus
|
||||
* Unfocuses the specified text field
|
||||
* noop if it wasn't focused
|
||||
*/
|
||||
blurTextInput: function(textFieldID: string) {
|
||||
blurTextInput: function(textFieldID: ?number) {
|
||||
if (this._currentlyFocusedID === textFieldID && textFieldID !== null) {
|
||||
this._currentlyFocusedID = null;
|
||||
RCTUIManager.blur(textFieldID);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var TimerMixin = require('react-timer-mixin');
|
||||
var Touchable = require('Touchable');
|
||||
@@ -120,7 +120,7 @@ var TouchableHighlight = React.createClass({
|
||||
|
||||
viewConfig: {
|
||||
uiViewClassName: 'RCTView',
|
||||
validAttributes: ReactIOSViewAttributes.RCTView
|
||||
validAttributes: ReactNativeViewAttributes.RCTView
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,15 +15,35 @@ var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var RCTUIManager = require('NativeModules').UIManager;
|
||||
var React = require('React');
|
||||
var ReactIOSStyleAttributes = require('ReactIOSStyleAttributes');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var StyleSheetPropType = require('StyleSheetPropType');
|
||||
var ViewStylePropTypes = require('ViewStylePropTypes');
|
||||
|
||||
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
|
||||
var stylePropType = StyleSheetPropType(ViewStylePropTypes);
|
||||
|
||||
var AccessibilityTraits = [
|
||||
'none',
|
||||
'button',
|
||||
'link',
|
||||
'header',
|
||||
'search',
|
||||
'image',
|
||||
'selected',
|
||||
'plays',
|
||||
'key',
|
||||
'text',
|
||||
'summary',
|
||||
'disabled',
|
||||
'frequentUpdates',
|
||||
'startsMedia',
|
||||
'adjustable',
|
||||
'allowsDirectInteraction',
|
||||
'pageTurn',
|
||||
];
|
||||
|
||||
/**
|
||||
* The most fundamental component for building UI, `View` is a
|
||||
* container that supports layout with flexbox, style, some touch handling, and
|
||||
@@ -53,7 +73,7 @@ var View = React.createClass({
|
||||
*/
|
||||
viewConfig: {
|
||||
uiViewClassName: 'RCTView',
|
||||
validAttributes: ReactIOSViewAttributes.RCTView
|
||||
validAttributes: ReactNativeViewAttributes.RCTView
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
@@ -70,6 +90,27 @@ var View = React.createClass({
|
||||
*/
|
||||
accessibilityLabel: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Provides additional traits to screen reader. By default no traits are
|
||||
* provided unless specified otherwise in element
|
||||
*/
|
||||
accessibilityTraits: PropTypes.oneOfType([
|
||||
PropTypes.oneOf(AccessibilityTraits),
|
||||
PropTypes.arrayOf(PropTypes.oneOf(AccessibilityTraits)),
|
||||
]),
|
||||
|
||||
/**
|
||||
* When `accessible` is true, the system will try to invoke this function
|
||||
* when the user performs accessibility tap gesture.
|
||||
*/
|
||||
onAcccessibilityTap: PropTypes.func,
|
||||
|
||||
/**
|
||||
* When `accessible` is true, the system will invoke this function when the
|
||||
* user performs the magic tap gesture.
|
||||
*/
|
||||
onMagicTap: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Used to locate this view in end-to-end tests.
|
||||
*/
|
||||
@@ -91,7 +132,9 @@ var View = React.createClass({
|
||||
onStartShouldSetResponderCapture: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Invoked on mount and layout changes with {x, y, width, height}.
|
||||
* Invoked on mount and layout changes with
|
||||
*
|
||||
* {nativeEvent: { layout: {x, y, width, height}}}.
|
||||
*/
|
||||
onLayout: PropTypes.func,
|
||||
|
||||
@@ -163,8 +206,8 @@ var View = React.createClass({
|
||||
},
|
||||
});
|
||||
|
||||
var RCTView = createReactIOSNativeComponentClass({
|
||||
validAttributes: ReactIOSViewAttributes.RCTView,
|
||||
var RCTView = createReactNativeComponentClass({
|
||||
validAttributes: ReactNativeViewAttributes.RCTView,
|
||||
uiViewClassName: 'RCTView',
|
||||
});
|
||||
RCTView.propTypes = View.propTypes;
|
||||
@@ -172,7 +215,7 @@ if (__DEV__) {
|
||||
var viewConfig = RCTUIManager.viewConfigs && RCTUIManager.viewConfigs.RCTView || {};
|
||||
for (var prop in viewConfig.nativeProps) {
|
||||
var viewAny: any = View; // Appease flow
|
||||
if (!viewAny.propTypes[prop] && !ReactIOSStyleAttributes[prop]) {
|
||||
if (!viewAny.propTypes[prop] && !ReactNativeStyleAttributes[prop]) {
|
||||
throw new Error(
|
||||
'View is missing propType for native prop `' + prop + '`'
|
||||
);
|
||||
|
||||
@@ -28,6 +28,10 @@ var ViewStylePropTypes = {
|
||||
borderBottomColor: ReactPropTypes.string,
|
||||
borderLeftColor: ReactPropTypes.string,
|
||||
borderRadius: ReactPropTypes.number,
|
||||
borderTopLeftRadius: ReactPropTypes.number,
|
||||
borderTopRightRadius: ReactPropTypes.number,
|
||||
borderBottomLeftRadius: ReactPropTypes.number,
|
||||
borderBottomRightRadius: ReactPropTypes.number,
|
||||
opacity: ReactPropTypes.number,
|
||||
overflow: ReactPropTypes.oneOf(['visible', 'hidden']),
|
||||
shadowColor: ReactPropTypes.string,
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
|
||||
var EdgeInsetsPropType = require('EdgeInsetsPropType');
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var View = require('View');
|
||||
|
||||
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
var keyMirror = require('keyMirror');
|
||||
var merge = require('merge');
|
||||
|
||||
@@ -75,7 +75,7 @@ var WebView = React.createClass({
|
||||
errorEvent.code,
|
||||
errorEvent.description);
|
||||
} else if (this.state.viewState !== WebViewState.IDLE) {
|
||||
console.error("RCTWebView invalid state encountered: " + this.state.loading);
|
||||
console.error('RCTWebView invalid state encountered: ' + this.state.loading);
|
||||
}
|
||||
|
||||
var webViewStyles = [styles.container, this.props.style];
|
||||
@@ -143,7 +143,7 @@ var WebView = React.createClass({
|
||||
},
|
||||
|
||||
getWebWiewHandle: function() {
|
||||
return this.refs[RCT_WEBVIEW_REF].getNodeHandle();
|
||||
return React.findNodeHandle(this.refs[RCT_WEBVIEW_REF]);
|
||||
},
|
||||
|
||||
onLoadingStart: function(event) {
|
||||
@@ -152,7 +152,7 @@ var WebView = React.createClass({
|
||||
|
||||
onLoadingError: function(event) {
|
||||
event.persist(); // persist this event because we need to store it
|
||||
console.error("encountered an error loading page", event.nativeEvent);
|
||||
console.error('Encountered an error loading page', event.nativeEvent);
|
||||
|
||||
this.setState({
|
||||
lastErrorEvent: event.nativeEvent,
|
||||
@@ -168,8 +168,8 @@ var WebView = React.createClass({
|
||||
},
|
||||
});
|
||||
|
||||
var RCTWebView = createReactIOSNativeComponentClass({
|
||||
validAttributes: merge(ReactIOSViewAttributes.UIView, {
|
||||
var RCTWebView = createReactNativeComponentClass({
|
||||
validAttributes: merge(ReactNativeViewAttributes.UIView, {
|
||||
url: true,
|
||||
javaScriptEnabledAndroid: true,
|
||||
}),
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
var ActivityIndicatorIOS = require('ActivityIndicatorIOS');
|
||||
var EdgeInsetsPropType = require('EdgeInsetsPropType');
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var Text = require('Text');
|
||||
var View = require('View');
|
||||
@@ -189,7 +188,7 @@ var WebView = React.createClass({
|
||||
},
|
||||
|
||||
getWebWiewHandle: function(): any {
|
||||
return this.refs[RCT_WEBVIEW_REF].getNodeHandle();
|
||||
return React.findNodeHandle(this.refs[RCT_WEBVIEW_REF]);
|
||||
},
|
||||
|
||||
onLoadingStart: function(event: Event) {
|
||||
@@ -198,7 +197,7 @@ var WebView = React.createClass({
|
||||
|
||||
onLoadingError: function(event: Event) {
|
||||
event.persist(); // persist this event because we need to store it
|
||||
console.error("encountered an error loading page", event.nativeEvent);
|
||||
console.error('Encountered an error loading page', event.nativeEvent);
|
||||
|
||||
this.setState({
|
||||
lastErrorEvent: event.nativeEvent,
|
||||
|
||||
@@ -87,7 +87,7 @@ var SCROLLVIEW_REF = 'listviewscroll';
|
||||
* smoothly while dynamically loading potentially very large (or conceptually
|
||||
* infinite) data sets:
|
||||
*
|
||||
* * Only re-render changed rows - the hasRowChanged function provided to the
|
||||
* * Only re-render changed rows - the rowHasChanged function provided to the
|
||||
* data source tells the ListView if it needs to re-render a row because the
|
||||
* source data has changed - see ListViewDataSource for more details.
|
||||
*
|
||||
@@ -346,12 +346,12 @@ var ListView = React.createClass({
|
||||
_measureAndUpdateScrollProps: function() {
|
||||
RCTUIManager.measureLayout(
|
||||
this.refs[SCROLLVIEW_REF].getInnerViewNode(),
|
||||
this.refs[SCROLLVIEW_REF].getNodeHandle(),
|
||||
React.findNodeHandle(this.refs[SCROLLVIEW_REF]),
|
||||
logError,
|
||||
this._setScrollContentHeight
|
||||
);
|
||||
RCTUIManager.measureLayoutRelativeToParent(
|
||||
this.refs[SCROLLVIEW_REF].getNodeHandle(),
|
||||
React.findNodeHandle(this.refs[SCROLLVIEW_REF]),
|
||||
logError,
|
||||
this._setScrollVisibleHeight
|
||||
);
|
||||
|
||||
@@ -103,6 +103,10 @@ class ListViewDataSource {
|
||||
*
|
||||
* or
|
||||
*
|
||||
* { sectionID_1: [ <rowData1>, <rowData2>, ... ], ... }
|
||||
*
|
||||
* or
|
||||
*
|
||||
* [ [ <rowData1>, <rowData2>, ... ], ... ]
|
||||
*
|
||||
* The constructor takes in a params argument that can contain any of the
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*
|
||||
* @providesModule Navigator
|
||||
*/
|
||||
/* eslint-disable no-extra-boolean-cast*/
|
||||
'use strict';
|
||||
|
||||
var AnimationsDebugModule = require('NativeModules').AnimationsDebugModule;
|
||||
@@ -48,8 +49,6 @@ var clamp = require('clamp');
|
||||
var flattenStyle = require('flattenStyle');
|
||||
var getNavigatorContext = require('getNavigatorContext');
|
||||
var invariant = require('invariant');
|
||||
var keyMirror = require('keyMirror');
|
||||
var merge = require('merge');
|
||||
var rebound = require('rebound');
|
||||
|
||||
var PropTypes = React.PropTypes;
|
||||
@@ -253,7 +252,7 @@ var Navigator = React.createClass({
|
||||
onDidFocus: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Will be called with (ref, indexInStack) when the scene ref changes
|
||||
* Will be called with (ref, indexInStack, route) when the scene ref changes
|
||||
*/
|
||||
onItemRef: PropTypes.func,
|
||||
|
||||
@@ -582,7 +581,7 @@ var Navigator = React.createClass({
|
||||
* This happens at the end of a transition started by transitionTo, and when the spring catches up to a pending gesture
|
||||
*/
|
||||
_completeTransition: function() {
|
||||
if (this.spring.getCurrentValue() !== 1) {
|
||||
if (this.spring.getCurrentValue() !== 1 && this.spring.getCurrentValue() !== 0) {
|
||||
// The spring has finished catching up to a gesture in progress. Remove the pending progress
|
||||
// and we will be in a normal activeGesture state
|
||||
if (this.state.pendingGestureProgress) {
|
||||
@@ -659,11 +658,17 @@ var Navigator = React.createClass({
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides scenes that we are not currently on or transitioning from
|
||||
* Hides all scenes that we are not currently on, gesturing to, or transitioning from
|
||||
*/
|
||||
_hideScenes: function() {
|
||||
var gesturingToIndex = null;
|
||||
if (this.state.activeGesture) {
|
||||
gesturingToIndex = this.state.presentedIndex + this._deltaForGestureAction(this.state.activeGesture);
|
||||
}
|
||||
for (var i = 0; i < this.state.routeStack.length; i++) {
|
||||
if (i === this.state.presentedIndex || i === this.state.transitionFromIndex) {
|
||||
if (i === this.state.presentedIndex ||
|
||||
i === this.state.transitionFromIndex ||
|
||||
i === gesturingToIndex) {
|
||||
continue;
|
||||
}
|
||||
this._disableScene(i);
|
||||
@@ -683,7 +688,7 @@ var Navigator = React.createClass({
|
||||
*/
|
||||
_enableScene: function(sceneIndex) {
|
||||
// First, determine what the defined styles are for scenes in this navigator
|
||||
var sceneStyle = flattenStyle(this.props.sceneStyle);
|
||||
var sceneStyle = flattenStyle([styles.baseScene, this.props.sceneStyle]);
|
||||
// Then restore the left value for this scene
|
||||
var enabledSceneNativeProps = {
|
||||
left: sceneStyle.left,
|
||||
@@ -734,10 +739,13 @@ var Navigator = React.createClass({
|
||||
viewAtIndex.setNativeProps({renderToHardwareTextureAndroid: shouldRenderToHardwareTexture});
|
||||
},
|
||||
|
||||
_handleTouchStart: function() {
|
||||
this._eligibleGestures = GESTURE_ACTIONS;
|
||||
},
|
||||
|
||||
_handleMoveShouldSetPanResponder: function(e, gestureState) {
|
||||
var currentRoute = this.state.routeStack[this.state.presentedIndex];
|
||||
var sceneConfig = this.state.sceneConfigStack[this.state.presentedIndex];
|
||||
this._expectingGestureGrant = this._matchGestureAction(sceneConfig.gestures, gestureState);
|
||||
this._expectingGestureGrant = this._matchGestureAction(this._eligibleGestures, sceneConfig.gestures, gestureState);
|
||||
return !! this._expectingGestureGrant;
|
||||
},
|
||||
|
||||
@@ -819,7 +827,16 @@ var Navigator = React.createClass({
|
||||
}
|
||||
} else {
|
||||
// The gesture has enough velocity to complete, so we transition to the gesture's destination
|
||||
this._transitionTo(destIndex, transitionVelocity);
|
||||
this._transitionTo(
|
||||
destIndex,
|
||||
transitionVelocity,
|
||||
null,
|
||||
() => {
|
||||
if (releaseGestureAction === 'pop') {
|
||||
this._cleanScenesPastIndex(destIndex);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
this._detachGesture();
|
||||
},
|
||||
@@ -855,7 +872,7 @@ var Navigator = React.createClass({
|
||||
var gesture = sceneConfig.gestures[this.state.activeGesture];
|
||||
return this._moveAttachedGesture(gesture, gestureState);
|
||||
}
|
||||
var matchedGesture = this._matchGestureAction(sceneConfig.gestures, gestureState);
|
||||
var matchedGesture = this._matchGestureAction(GESTURE_ACTIONS, sceneConfig.gestures, gestureState);
|
||||
if (matchedGesture) {
|
||||
this._attachGesture(matchedGesture);
|
||||
}
|
||||
@@ -870,8 +887,13 @@ var Navigator = React.createClass({
|
||||
var nextProgress = (distance - gestureDetectMovement) /
|
||||
(gesture.fullDistance - gestureDetectMovement);
|
||||
if (nextProgress < 0 && gesture.isDetachable) {
|
||||
var gesturingToIndex = this.state.presentedIndex + this._deltaForGestureAction(this.state.activeGesture);
|
||||
this._transitionBetween(this.state.presentedIndex, gesturingToIndex, 0);
|
||||
this._detachGesture();
|
||||
this.spring.setCurrentValue(0);
|
||||
if (this.state.pendingGestureProgress != null) {
|
||||
this.spring.setCurrentValue(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (this._doesGestureOverswipe(this.state.activeGesture)) {
|
||||
var frictionConstant = gesture.overswipe.frictionConstant;
|
||||
@@ -889,12 +911,12 @@ var Navigator = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
_matchGestureAction: function(gestures, gestureState) {
|
||||
_matchGestureAction: function(eligibleGestures, gestures, gestureState) {
|
||||
if (!gestures) {
|
||||
return null;
|
||||
}
|
||||
var matchedGesture = null;
|
||||
GESTURE_ACTIONS.some((gestureName) => {
|
||||
eligibleGestures.some((gestureName, gestureIndex) => {
|
||||
var gesture = gestures[gestureName];
|
||||
if (!gesture) {
|
||||
return;
|
||||
@@ -920,12 +942,19 @@ var Navigator = React.createClass({
|
||||
}
|
||||
var moveStartedInRegion = gesture.edgeHitWidth == null ||
|
||||
currentLoc < edgeHitWidth;
|
||||
var moveTravelledFarEnough =
|
||||
travelDist >= gesture.gestureDetectMovement &&
|
||||
travelDist > oppositeAxisTravelDist * gesture.directionRatio;
|
||||
if (moveStartedInRegion && moveTravelledFarEnough) {
|
||||
if (!moveStartedInRegion) {
|
||||
return false;
|
||||
}
|
||||
var moveTravelledFarEnough = travelDist >= gesture.gestureDetectMovement;
|
||||
if (!moveTravelledFarEnough) {
|
||||
return false;
|
||||
}
|
||||
var directionIsCorrect = Math.abs(travelDist) > Math.abs(oppositeAxisTravelDist) * gesture.directionRatio;
|
||||
if (directionIsCorrect) {
|
||||
matchedGesture = gestureName;
|
||||
return true;
|
||||
} else {
|
||||
this._eligibleGestures = this._eligibleGestures.slice().splice(gestureIndex, 1);
|
||||
}
|
||||
});
|
||||
return matchedGesture;
|
||||
@@ -1151,7 +1180,11 @@ var Navigator = React.createClass({
|
||||
resetTo: function(route) {
|
||||
invariant(!!route, 'Must supply route to push');
|
||||
this.replaceAtIndex(route, 0, () => {
|
||||
this.popToRoute(route);
|
||||
// Do not use popToRoute here, because race conditions could prevent the
|
||||
// route from existing at this time. Instead, just go to index 0
|
||||
if (this.state.presentedIndex > 0) {
|
||||
this._popN(this.state.presentedIndex);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1159,13 +1192,13 @@ var Navigator = React.createClass({
|
||||
return this.state.routeStack;
|
||||
},
|
||||
|
||||
_handleItemRef: function(itemId, ref) {
|
||||
_handleItemRef: function(itemId, route, ref) {
|
||||
this._itemRefs[itemId] = ref;
|
||||
var itemIndex = this.state.idStack.indexOf(itemId);
|
||||
if (itemIndex === -1) {
|
||||
return;
|
||||
}
|
||||
this.props.onItemRef && this.props.onItemRef(ref, itemIndex);
|
||||
this.props.onItemRef && this.props.onItemRef(ref, itemIndex, route);
|
||||
},
|
||||
|
||||
_cleanScenesPastIndex: function(index) {
|
||||
@@ -1202,6 +1235,7 @@ var Navigator = React.createClass({
|
||||
<View
|
||||
style={styles.transitioner}
|
||||
{...this.panGesture.panHandlers}
|
||||
onTouchStart={this._handleTouchStart}
|
||||
onResponderTerminationRequest={
|
||||
this._handleResponderTerminationRequest
|
||||
}>
|
||||
@@ -1264,6 +1298,14 @@ var Navigator = React.createClass({
|
||||
if (i !== this.state.presentedIndex) {
|
||||
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 (
|
||||
<View
|
||||
key={this.state.idStack[i]}
|
||||
@@ -1273,7 +1315,12 @@ var Navigator = React.createClass({
|
||||
}}
|
||||
style={[styles.baseScene, this.props.sceneStyle, disabledSceneStyle]}>
|
||||
{React.cloneElement(child, {
|
||||
ref: this._handleItemRef.bind(null, this.state.idStack[i]),
|
||||
ref: component => {
|
||||
this._handleItemRef(this.state.idStack[i], route, component);
|
||||
if (originalRef) {
|
||||
originalRef(component);
|
||||
}
|
||||
}
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -101,6 +101,18 @@ var FadeToTheLeft = {
|
||||
},
|
||||
};
|
||||
|
||||
var FadeToTheRight = {
|
||||
...FadeToTheLeft,
|
||||
transformTranslate: {
|
||||
from: {x: 0, y: 0, z: 0},
|
||||
to: {x: Math.round(SCREEN_WIDTH * 0.3), y: 0, z: 0},
|
||||
},
|
||||
translateX: {
|
||||
from: 0,
|
||||
to: Math.round(SCREEN_WIDTH * 0.3),
|
||||
}
|
||||
};
|
||||
|
||||
var FadeIn = {
|
||||
opacity: {
|
||||
from: 0,
|
||||
@@ -187,6 +199,27 @@ var FromTheRight = {
|
||||
},
|
||||
};
|
||||
|
||||
var FromTheLeft = {
|
||||
...FromTheRight,
|
||||
transformTranslate: {
|
||||
from: {x: -SCREEN_WIDTH, y: 0, z: 0},
|
||||
to: {x: 0, y: 0, z: 0},
|
||||
min: 0,
|
||||
max: 1,
|
||||
type: 'linear',
|
||||
extrapolate: true,
|
||||
round: PixelRatio.get(),
|
||||
},
|
||||
translateX: {
|
||||
from: -SCREEN_WIDTH,
|
||||
to: 0,
|
||||
min: 0,
|
||||
max: 1,
|
||||
type: 'linear',
|
||||
extrapolate: true,
|
||||
round: PixelRatio.get(),
|
||||
},
|
||||
};
|
||||
|
||||
var ToTheBack = {
|
||||
// Rotate *requires* you to break out each individual component of
|
||||
@@ -374,6 +407,13 @@ var NavigatorSceneConfigs = {
|
||||
...BaseConfig,
|
||||
// We will want to customize this soon
|
||||
},
|
||||
FloatFromLeft: {
|
||||
...BaseConfig,
|
||||
animationInterpolators: {
|
||||
into: buildStyleInterpolator(FromTheLeft),
|
||||
out: buildStyleInterpolator(FadeToTheRight),
|
||||
},
|
||||
},
|
||||
FloatFromBottom: {
|
||||
...BaseConfig,
|
||||
gestures: {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
* @providesModule fetch
|
||||
* @nolint
|
||||
*/
|
||||
/* eslint-disable */
|
||||
'use strict';
|
||||
|
||||
var self = {};
|
||||
|
||||
@@ -120,6 +120,6 @@ var Geolocation = {
|
||||
subscriptions = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Geolocation;
|
||||
|
||||
@@ -18,7 +18,7 @@ var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var NativeModules = require('NativeModules');
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var StyleSheetPropType = require('StyleSheetPropType');
|
||||
|
||||
@@ -60,7 +60,7 @@ var Image = React.createClass({
|
||||
/**
|
||||
* `uri` is a string representing the resource identifier for the image, which
|
||||
* could be an http address, a local file path, or the name of a static image
|
||||
* resource (which should be wrapped in the `required('image!name')` function).
|
||||
* resource (which should be wrapped in the `require('image!name')` function).
|
||||
*/
|
||||
source: PropTypes.shape({
|
||||
uri: PropTypes.string,
|
||||
@@ -99,6 +99,12 @@ var Image = React.createClass({
|
||||
* testing scripts.
|
||||
*/
|
||||
testID: PropTypes.string,
|
||||
/**
|
||||
* Invoked on mount and layout changes with
|
||||
*
|
||||
* {nativeEvent: { layout: {x, y, width, height}}}.
|
||||
*/
|
||||
onLayout: PropTypes.func,
|
||||
},
|
||||
|
||||
statics: {
|
||||
@@ -113,7 +119,7 @@ var Image = React.createClass({
|
||||
*/
|
||||
viewConfig: {
|
||||
uiViewClassName: 'UIView',
|
||||
validAttributes: ReactIOSViewAttributes.UIView
|
||||
validAttributes: ReactNativeViewAttributes.UIView
|
||||
},
|
||||
|
||||
render: function() {
|
||||
|
||||
@@ -33,6 +33,8 @@ typedef void (^RCTImageDownloadBlock)(UIImage *image, NSError *error);
|
||||
- (id)downloadImageForURL:(NSURL *)url
|
||||
size:(CGSize)size
|
||||
scale:(CGFloat)scale
|
||||
resizeMode:(UIViewContentMode)resizeMode
|
||||
backgroundColor:(UIColor *)backgroundColor
|
||||
block:(RCTImageDownloadBlock)block;
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#import "RCTImageDownloader.h"
|
||||
|
||||
#import "RCTCache.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
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) {
|
||||
|
||||
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];
|
||||
if (image) {
|
||||
|
||||
// Resize (TODO: should we take aspect ratio into account?)
|
||||
CGSize imageSize = size;
|
||||
if (CGSizeEqualToSize(imageSize, CGSizeZero)) {
|
||||
imageSize = image.size;
|
||||
} else {
|
||||
imageSize = (CGSize){
|
||||
MIN(size.width, image.size.width),
|
||||
MIN(size.height, image.size.height)
|
||||
};
|
||||
}
|
||||
// Get scale and size
|
||||
CGFloat destScale = scale ?: RCTScreenScale();
|
||||
CGRect imageRect = RCTClipRect(image.size, image.scale, size, destScale, resizeMode);
|
||||
CGSize destSize = RCTTargetSizeForClipRect(imageRect);
|
||||
|
||||
// Rescale image if required size is smaller
|
||||
CGFloat imageScale = scale;
|
||||
if (imageScale == 0 || imageScale < image.scale) {
|
||||
imageScale = image.scale;
|
||||
// Opacity optimizations
|
||||
UIColor *blendColor = nil;
|
||||
BOOL opaque = !RCTImageHasAlpha(image.CGImage);
|
||||
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
|
||||
UIGraphicsBeginImageContextWithOptions(imageSize, NO, imageScale);
|
||||
[image drawInRect:(CGRect){{0, 0}, imageSize}];
|
||||
UIGraphicsBeginImageContextWithOptions(destSize, opaque, destScale);
|
||||
if (blendColor) {
|
||||
[blendColor setFill];
|
||||
UIRectFill((CGRect){CGPointZero, destSize});
|
||||
}
|
||||
[image drawInRect:imageRect];
|
||||
image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,12 @@
|
||||
@interface RCTImageLoader : NSObject
|
||||
|
||||
+ (ALAssetsLibrary *)assetsLibrary;
|
||||
+ (void)loadImageWithTag:(NSString *)tag callback:(void (^)(NSError *error, UIImage *image))callback;
|
||||
|
||||
/**
|
||||
* Can be called from any thread.
|
||||
* Will always call callback on main thread.
|
||||
*/
|
||||
+ (void)loadImageWithTag:(NSString *)tag
|
||||
callback:(void (^)(NSError *error, id /* UIImage or CAAnimation */ image))callback;
|
||||
|
||||
@end
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTGIFImage.h"
|
||||
#import "RCTImageDownloader.h"
|
||||
#import "RCTLog.h"
|
||||
|
||||
@@ -25,20 +26,29 @@ static dispatch_queue_t RCTImageLoaderQueue(void)
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
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;
|
||||
}
|
||||
|
||||
NSError *errorWithMessage(NSString *message)
|
||||
static NSError *RCTErrorWithMessage(NSString *message)
|
||||
{
|
||||
NSDictionary *errorInfo = @{NSLocalizedDescriptionKey: message};
|
||||
NSError *error = [[NSError alloc] initWithDomain:RCTErrorDomain code:0 userInfo:errorInfo];
|
||||
return error;
|
||||
}
|
||||
|
||||
static void RCTDispatchCallbackOnMainQueue(void (^callback)(NSError *, id), NSError *error, UIImage *image)
|
||||
{
|
||||
if ([NSThread isMainThread]) {
|
||||
callback(error, image);
|
||||
} else {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
callback(error, image);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@implementation RCTImageLoader
|
||||
|
||||
+ (ALAssetsLibrary *)assetsLibrary
|
||||
@@ -51,7 +61,11 @@ NSError *errorWithMessage(NSString *message)
|
||||
return assetsLibrary;
|
||||
}
|
||||
|
||||
+ (void)loadImageWithTag:(NSString *)imageTag callback:(void (^)(NSError *error, UIImage *image))callback
|
||||
/**
|
||||
* Can be called from any thread.
|
||||
* Will always call callback on main thread.
|
||||
*/
|
||||
+ (void)loadImageWithTag:(NSString *)imageTag callback:(void (^)(NSError *error, id image))callback
|
||||
{
|
||||
if ([imageTag hasPrefix:@"assets-library"]) {
|
||||
[[RCTImageLoader assetsLibrary] assetForURL:[NSURL URLWithString:imageTag] resultBlock:^(ALAsset *asset) {
|
||||
@@ -67,18 +81,18 @@ NSError *errorWithMessage(NSString *message)
|
||||
ALAssetRepresentation *representation = [asset defaultRepresentation];
|
||||
ALAssetOrientation orientation = [representation orientation];
|
||||
UIImage *image = [UIImage imageWithCGImage:[representation fullResolutionImage] scale:1.0f orientation:(UIImageOrientation)orientation];
|
||||
callback(nil, image);
|
||||
RCTDispatchCallbackOnMainQueue(callback, nil, image);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
NSString *errorText = [NSString stringWithFormat:@"Failed to load asset at URL %@ with no error message.", imageTag];
|
||||
NSError *error = errorWithMessage(errorText);
|
||||
callback(error, nil);
|
||||
NSError *error = RCTErrorWithMessage(errorText);
|
||||
RCTDispatchCallbackOnMainQueue(callback, error, nil);
|
||||
}
|
||||
} failureBlock:^(NSError *loadError) {
|
||||
NSString *errorText = [NSString stringWithFormat:@"Failed to load asset at URL %@.\niOS Error: %@", imageTag, loadError];
|
||||
NSError *error = errorWithMessage(errorText);
|
||||
callback(error, nil);
|
||||
NSError *error = RCTErrorWithMessage(errorText);
|
||||
RCTDispatchCallbackOnMainQueue(callback, error, nil);
|
||||
}];
|
||||
} else if ([imageTag hasPrefix:@"ph://"]) {
|
||||
// Using PhotoKit for iOS 8+
|
||||
@@ -89,19 +103,19 @@ NSError *errorWithMessage(NSString *message)
|
||||
PHFetchResult *results = [PHAsset fetchAssetsWithLocalIdentifiers:@[phAssetID] options:nil];
|
||||
if (results.count == 0) {
|
||||
NSString *errorText = [NSString stringWithFormat:@"Failed to fetch PHAsset with local identifier %@ with no error message.", phAssetID];
|
||||
NSError *error = errorWithMessage(errorText);
|
||||
callback(error, nil);
|
||||
NSError *error = RCTErrorWithMessage(errorText);
|
||||
RCTDispatchCallbackOnMainQueue(callback, error, nil);
|
||||
return;
|
||||
}
|
||||
|
||||
PHAsset *asset = [results firstObject];
|
||||
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:nil resultHandler:^(UIImage *result, NSDictionary *info) {
|
||||
if (result) {
|
||||
callback(nil, result);
|
||||
RCTDispatchCallbackOnMainQueue(callback, nil, result);
|
||||
} else {
|
||||
NSString *errorText = [NSString stringWithFormat:@"Failed to load PHAsset with local identifier %@ with no error message.", phAssetID];
|
||||
NSError *error = errorWithMessage(errorText);
|
||||
callback(error, nil);
|
||||
NSError *error = RCTErrorWithMessage(errorText);
|
||||
RCTDispatchCallbackOnMainQueue(callback, error, nil);
|
||||
return;
|
||||
}
|
||||
}];
|
||||
@@ -109,20 +123,34 @@ NSError *errorWithMessage(NSString *message)
|
||||
NSURL *url = [NSURL URLWithString:imageTag];
|
||||
if (!url) {
|
||||
NSString *errorMessage = [NSString stringWithFormat:@"Invalid URL: %@", imageTag];
|
||||
callback(errorWithMessage(errorMessage), nil);
|
||||
RCTDispatchCallbackOnMainQueue(callback, RCTErrorWithMessage(errorMessage), nil);
|
||||
return;
|
||||
}
|
||||
[[RCTImageDownloader sharedInstance] downloadDataForURL:url block:^(NSData *data, NSError *error) {
|
||||
if (error) {
|
||||
callback(error, nil);
|
||||
RCTDispatchCallbackOnMainQueue(callback, error, nil);
|
||||
} else {
|
||||
callback(nil, [UIImage imageWithData:data]);
|
||||
RCTDispatchCallbackOnMainQueue(callback, nil, [UIImage imageWithData:data]);
|
||||
}
|
||||
}];
|
||||
} else if ([[imageTag lowercaseString] hasSuffix:@".gif"]) {
|
||||
id image = RCTGIFImageWithFileURL([RCTConvert NSURL:imageTag]);
|
||||
if (image) {
|
||||
RCTDispatchCallbackOnMainQueue(callback, nil, image);
|
||||
} else {
|
||||
NSString *errorMessage = [NSString stringWithFormat:@"Unable to load GIF image: %@", imageTag];
|
||||
NSError *error = RCTErrorWithMessage(errorMessage);
|
||||
RCTDispatchCallbackOnMainQueue(callback, error, nil);
|
||||
}
|
||||
} else {
|
||||
NSString *errorMessage = [NSString stringWithFormat:@"Unrecognized tag protocol: %@", imageTag];
|
||||
NSError *error = errorWithMessage(errorMessage);
|
||||
callback(error, nil);
|
||||
UIImage *image = [RCTConvert UIImage:imageTag];
|
||||
if (image) {
|
||||
RCTDispatchCallbackOnMainQueue(callback, nil, image);
|
||||
} else {
|
||||
NSString *errorMessage = [NSString stringWithFormat:@"Unrecognized tag protocol: %@", imageTag];
|
||||
NSError *error = RCTErrorWithMessage(errorMessage);
|
||||
RCTDispatchCallbackOnMainQueue(callback, error, nil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#import "RCTGIFImage.h"
|
||||
#import "RCTImageDownloader.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "UIView+React.h"
|
||||
|
||||
@implementation RCTNetworkImageView
|
||||
{
|
||||
@@ -26,8 +27,7 @@
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame imageDownloader:(RCTImageDownloader *)imageDownloader
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
_deferSentinel = 0;
|
||||
_imageDownloader = imageDownloader;
|
||||
self.userInteractionEnabled = NO;
|
||||
@@ -37,20 +37,44 @@
|
||||
|
||||
- (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.
|
||||
// However we don't want to expose this hackery externally.
|
||||
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
|
||||
{
|
||||
if (![_imageURL isEqual:imageURL] && _downloadToken) {
|
||||
[_imageDownloader cancelDownload:_downloadToken];
|
||||
_downloadToken = nil;
|
||||
}
|
||||
|
||||
_imageURL = imageURL;
|
||||
|
||||
if (_deferred) {
|
||||
_deferredImageURL = imageURL;
|
||||
} else {
|
||||
if (_downloadToken) {
|
||||
[_imageDownloader cancelDownload:_downloadToken];
|
||||
_downloadToken = nil;
|
||||
if (!imageURL) {
|
||||
self.layer.contents = nil;
|
||||
return;
|
||||
}
|
||||
if (reset) {
|
||||
self.layer.contentsScale = _defaultImage.scale;
|
||||
@@ -62,25 +86,35 @@
|
||||
_downloadToken = [_imageDownloader downloadDataForURL:imageURL block:^(NSData *data, NSError *error) {
|
||||
if (data) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (imageURL != self.imageURL) {
|
||||
// Image has changed
|
||||
return;
|
||||
}
|
||||
CAKeyframeAnimation *animation = RCTGIFImageWithData(data);
|
||||
self.layer.contentsScale = 1.0;
|
||||
self.layer.minificationFilter = kCAFilterLinear;
|
||||
self.layer.magnificationFilter = kCAFilterLinear;
|
||||
[self.layer addAnimation:animation forKey:@"contents"];
|
||||
});
|
||||
} else if (error) {
|
||||
RCTLogWarn(@"Unable to download image data. Error: %@", error);
|
||||
}
|
||||
// TODO: handle errors
|
||||
}];
|
||||
} 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) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (imageURL != self.imageURL) {
|
||||
// Image has changed
|
||||
return;
|
||||
}
|
||||
[self.layer removeAnimationForKey:@"contents"];
|
||||
self.layer.contentsScale = image.scale;
|
||||
self.layer.contents = (__bridge id)image.CGImage;
|
||||
});
|
||||
} else if (error) {
|
||||
RCTLogWarn(@"Unable to download image. Error: %@", error);
|
||||
}
|
||||
// TODO: handle errors
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +33,11 @@ RCT_CUSTOM_VIEW_PROPERTY(src, NSURL, RCTStaticImage)
|
||||
if ([[[json description] pathExtension] caseInsensitiveCompare:@"gif"] == NSOrderedSame) {
|
||||
[view.layer addAnimation:RCTGIFImageWithFileURL([RCTConvert NSURL:json]) forKey:@"contents"];
|
||||
} else {
|
||||
[view.layer removeAnimationForKey:@"contents"];
|
||||
view.image = [RCTConvert UIImage:json];
|
||||
}
|
||||
} else {
|
||||
[view.layer removeAnimationForKey:@"contents"];
|
||||
view.image = defaultView.image;
|
||||
}
|
||||
}
|
||||
@@ -52,13 +54,19 @@ RCT_CUSTOM_VIEW_PROPERTY(tintColor, UIColor, RCTStaticImage)
|
||||
RCT_CUSTOM_VIEW_PROPERTY(imageTag, NSString, RCTStaticImage)
|
||||
{
|
||||
if (json) {
|
||||
[RCTImageLoader loadImageWithTag:[RCTConvert NSString:json] callback:^(NSError *error, UIImage *image) {
|
||||
[RCTImageLoader loadImageWithTag:[RCTConvert NSString:json] callback:^(NSError *error, id image) {
|
||||
if (error) {
|
||||
RCTLogWarn(@"%@", error.localizedDescription);
|
||||
}
|
||||
view.image = image;
|
||||
if ([image isKindOfClass:[CAAnimation class]]) {
|
||||
[view.layer addAnimation:image forKey:@"contents"];
|
||||
} else {
|
||||
[view.layer removeAnimationForKey:@"contents"];
|
||||
view.image = image;
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
[view.layer removeAnimationForKey:@"contents"];
|
||||
view.image = defaultView.image;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,10 @@ jest
|
||||
.dontMock('AssetRegistry')
|
||||
.dontMock('../resolveAssetSource');
|
||||
|
||||
var resolveAssetSource;
|
||||
var SourceCode;
|
||||
var AssetRegistry;
|
||||
var Platform;
|
||||
var SourceCode;
|
||||
var resolveAssetSource;
|
||||
|
||||
function expectResolvesAsset(input, expectedSource) {
|
||||
var assetId = AssetRegistry.registerAsset(input);
|
||||
@@ -24,8 +25,9 @@ function expectResolvesAsset(input, expectedSource) {
|
||||
describe('resolveAssetSource', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModuleRegistry();
|
||||
SourceCode = require('NativeModules').SourceCode;
|
||||
AssetRegistry = require('AssetRegistry');
|
||||
Platform = require('Platform');
|
||||
SourceCode = require('NativeModules').SourceCode;
|
||||
resolveAssetSource = require('../resolveAssetSource');
|
||||
});
|
||||
|
||||
@@ -59,7 +61,7 @@ describe('resolveAssetSource', () => {
|
||||
expect(resolveAssetSource('nonsense')).toBe(null);
|
||||
});
|
||||
|
||||
describe('bundle was loaded from network', () => {
|
||||
describe('bundle was loaded from network (DEV)', () => {
|
||||
beforeEach(() => {
|
||||
SourceCode.scriptURL = 'http://10.0.0.1:8081/main.bundle';
|
||||
});
|
||||
@@ -104,9 +106,21 @@ describe('resolveAssetSource', () => {
|
||||
|
||||
});
|
||||
|
||||
describe('bundle was loaded from file', () => {
|
||||
describe('bundle was loaded from file (PROD) on iOS', () => {
|
||||
var originalDevMode;
|
||||
var originalPlatform;
|
||||
|
||||
beforeEach(() => {
|
||||
SourceCode.scriptURL = 'file:///Path/To/Simulator/main.bundle';
|
||||
originalDevMode = __DEV__;
|
||||
originalPlatform = Platform.OS;
|
||||
__DEV__ = false;
|
||||
Platform.OS = 'ios';
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
__DEV__ = originalDevMode;
|
||||
Platform.OS = originalPlatform;
|
||||
});
|
||||
|
||||
it('uses pre-packed image', () => {
|
||||
@@ -129,6 +143,43 @@ describe('resolveAssetSource', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('bundle was loaded from file (PROD) on Android', () => {
|
||||
var originalDevMode;
|
||||
var originalPlatform;
|
||||
|
||||
beforeEach(() => {
|
||||
SourceCode.scriptURL = 'file:///Path/To/Simulator/main.bundle';
|
||||
originalDevMode = __DEV__;
|
||||
originalPlatform = Platform.OS;
|
||||
__DEV__ = false;
|
||||
Platform.OS = 'android';
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
__DEV__ = originalDevMode;
|
||||
Platform.OS = originalPlatform;
|
||||
});
|
||||
|
||||
it('uses pre-packed image', () => {
|
||||
expectResolvesAsset({
|
||||
__packager_asset: true,
|
||||
fileSystemLocation: '/root/app/module/a',
|
||||
httpServerLocation: '/assets/AwesomeModule/Subdir',
|
||||
width: 100,
|
||||
height: 200,
|
||||
scales: [1],
|
||||
hash: '5b6f00f',
|
||||
name: '!@Logo#1_€', // Invalid chars shouldn't get passed to native
|
||||
type: 'png',
|
||||
}, {
|
||||
isStatic: true,
|
||||
width: 100,
|
||||
height: 200,
|
||||
uri: 'assets_awesomemodule_subdir_logo1_',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('resolveAssetSource.pickScale', () => {
|
||||
|
||||
@@ -7,22 +7,31 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule resolveAssetSource
|
||||
*
|
||||
* Resolves an asset into a `source` for `Image`.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var AssetRegistry = require('AssetRegistry');
|
||||
var PixelRatio = require('PixelRatio');
|
||||
var Platform = require('Platform');
|
||||
var SourceCode = require('NativeModules').SourceCode;
|
||||
|
||||
var _serverURL;
|
||||
|
||||
function getServerURL() {
|
||||
function getDevServerURL() {
|
||||
if (!__DEV__) {
|
||||
// In prod we want assets to be loaded from the archive
|
||||
return null;
|
||||
}
|
||||
if (_serverURL === undefined) {
|
||||
var scriptURL = SourceCode.scriptURL;
|
||||
var match = scriptURL && scriptURL.match(/^https?:\/\/.*?\//);
|
||||
if (match) {
|
||||
// Bundle was loaded from network
|
||||
_serverURL = match[0];
|
||||
} else {
|
||||
// Bundle was loaded from file
|
||||
_serverURL = null;
|
||||
}
|
||||
}
|
||||
@@ -30,6 +39,55 @@ function getServerURL() {
|
||||
return _serverURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path at which the asset can be found in the archive
|
||||
*/
|
||||
function getPathInArchive(asset) {
|
||||
if (Platform.OS === 'android') {
|
||||
var assetDir = getBasePath(asset);
|
||||
// E.g. 'assets_awesomemodule_icon'
|
||||
// The Android resource system picks the correct scale.
|
||||
return (assetDir + '/' + asset.name)
|
||||
.toLowerCase()
|
||||
.replace(/\//g, '_') // Encode folder structure in file name
|
||||
.replace(/([^a-z0-9_])/g, ''); // Remove illegal chars
|
||||
} else {
|
||||
// E.g. 'assets/AwesomeModule/icon@2x.png'
|
||||
return getScaledAssetPath(asset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an absolute URL which can be used to fetch the asset
|
||||
* from the devserver
|
||||
*/
|
||||
function getPathOnDevserver(devServerUrl, asset) {
|
||||
return devServerUrl + getScaledAssetPath(asset) + '?hash=' + asset.hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a path like 'assets/AwesomeModule'
|
||||
*/
|
||||
function getBasePath(asset) {
|
||||
// TODO(frantic): currently httpServerLocation is used both as
|
||||
// path in http URL and path within IPA. Should we have zipArchiveLocation?
|
||||
var path = asset.httpServerLocation;
|
||||
if (path[0] === '/') {
|
||||
path = path.substr(1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a path like 'assets/AwesomeModule/icon@2x.png'
|
||||
*/
|
||||
function getScaledAssetPath(asset) {
|
||||
var scale = pickScale(asset.scales, PixelRatio.get());
|
||||
var scaleSuffix = scale === 1 ? '' : '@' + scale + 'x';
|
||||
var assetDir = getBasePath(asset);
|
||||
return assetDir + '/' + asset.name + scaleSuffix + '.' + asset.type;
|
||||
}
|
||||
|
||||
function pickScale(scales, deviceScale) {
|
||||
// Packager guarantees that `scales` array is sorted
|
||||
for (var i = 0; i < scales.length; i++) {
|
||||
@@ -58,31 +116,19 @@ function resolveAssetSource(source) {
|
||||
}
|
||||
|
||||
function assetToImageSource(asset) {
|
||||
// TODO(frantic): currently httpServerLocation is used both as
|
||||
// path in http URL and path within IPA. Should we have zipArchiveLocation?
|
||||
var path = asset.httpServerLocation;
|
||||
if (path[0] === '/') {
|
||||
path = path.substr(1);
|
||||
}
|
||||
|
||||
var scale = pickScale(asset.scales, PixelRatio.get());
|
||||
var scaleSuffix = scale === 1 ? '' : '@' + scale + 'x';
|
||||
|
||||
var fileName = asset.name + scaleSuffix + '.' + asset.type;
|
||||
var serverURL = getServerURL();
|
||||
if (serverURL) {
|
||||
var devServerURL = getDevServerURL();
|
||||
if (devServerURL) {
|
||||
return {
|
||||
width: asset.width,
|
||||
height: asset.height,
|
||||
uri: serverURL + path + '/' + fileName +
|
||||
'?hash=' + asset.hash,
|
||||
uri: getPathOnDevserver(devServerURL, asset),
|
||||
isStatic: false,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
width: asset.width,
|
||||
height: asset.height,
|
||||
uri: path + '/' + fileName,
|
||||
uri: getPathInArchive(asset),
|
||||
isStatic: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,6 +19,13 @@ var invariant = require('invariant');
|
||||
var keyMirror = require('keyMirror');
|
||||
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 _interactionSet = new Set();
|
||||
var _addInteractionSet = new Set();
|
||||
@@ -83,17 +90,25 @@ var InteractionManager = {
|
||||
/**
|
||||
* Notify manager that an interaction has started.
|
||||
*/
|
||||
createInteractionHandle(): number {
|
||||
createInteractionHandle(): Handle {
|
||||
scheduleUpdate();
|
||||
var handle = ++_inc;
|
||||
_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;
|
||||
},
|
||||
|
||||
/**
|
||||
* Notify manager that an interaction has completed.
|
||||
*/
|
||||
clearInteractionHandle(handle: number) {
|
||||
clearInteractionHandle(handle: Handle) {
|
||||
invariant(
|
||||
!!handle,
|
||||
'Must provide a handle to clear.'
|
||||
@@ -151,4 +166,19 @@ function processUpdate() {
|
||||
_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;
|
||||
|
||||
@@ -25,26 +25,39 @@ type Exception = {
|
||||
message: string;
|
||||
}
|
||||
|
||||
function reportException(e: Exception, stack?: any) {
|
||||
function reportException(e: Exception, isFatal: bool, stack?: any) {
|
||||
if (RCTExceptionsManager) {
|
||||
if (!stack) {
|
||||
stack = parseErrorStack(e);
|
||||
}
|
||||
RCTExceptionsManager.reportUnhandledException(e.message, stack);
|
||||
if (!RCTExceptionsManager.reportFatalException ||
|
||||
!RCTExceptionsManager.reportSoftException) {
|
||||
// Backwards compatibility - no differentiation
|
||||
// TODO(#7049989): deprecate reportUnhandledException on Android
|
||||
RCTExceptionsManager.reportUnhandledException(e.message, stack);
|
||||
} else {
|
||||
if (isFatal) {
|
||||
RCTExceptionsManager.reportFatalException(e.message, stack);
|
||||
} else {
|
||||
RCTExceptionsManager.reportSoftException(e.message, stack);
|
||||
}
|
||||
}
|
||||
if (__DEV__) {
|
||||
(sourceMapPromise = sourceMapPromise || loadSourceMap())
|
||||
.then(map => {
|
||||
var prettyStack = parseErrorStack(e, map);
|
||||
RCTExceptionsManager.updateExceptionMessage(e.message, prettyStack);
|
||||
})
|
||||
.then(null, error => {
|
||||
console.error('#CLOWNTOWN (error while displaying error): ' + error.message);
|
||||
.catch(error => {
|
||||
// This can happen in a variety of normal situations, such as
|
||||
// Network module not being available, or when running locally
|
||||
console.warn('Unable to load source map: ' + error.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleException(e: Exception) {
|
||||
function handleException(e: Exception, isFatal: boolean) {
|
||||
var stack = parseErrorStack(e);
|
||||
var msg =
|
||||
'Error: ' + e.message +
|
||||
@@ -57,7 +70,7 @@ function handleException(e: Exception) {
|
||||
} else {
|
||||
console.error(msg);
|
||||
}
|
||||
reportException(e, stack);
|
||||
reportException(e, isFatal, stack);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +91,7 @@ function installConsoleErrorReporter() {
|
||||
var str = Array.prototype.map.call(arguments, stringifySafe).join(', ');
|
||||
var error: any = new Error('console.error: ' + str);
|
||||
error.framesToPop = 1;
|
||||
reportException(error);
|
||||
reportException(error, /* isFatal */ false);
|
||||
};
|
||||
if (console.reportErrorsAsExceptions === undefined) {
|
||||
console.reportErrorsAsExceptions = true; // Individual apps can disable this
|
||||
|
||||
@@ -33,53 +33,20 @@ if (typeof window === 'undefined') {
|
||||
window = GLOBAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* The document must be shimmed before anything else that might define the
|
||||
* `ExecutionEnvironment` module (which checks for `document.createElement`).
|
||||
*/
|
||||
function setupDocumentShim() {
|
||||
// The browser defines Text and Image globals by default. If you forget to
|
||||
// require them, then the error message is very confusing.
|
||||
function getInvalidGlobalUseError(name) {
|
||||
return new Error(
|
||||
'You are trying to render the global ' + name + ' variable as a ' +
|
||||
'React element. You probably forgot to require ' + name + '.'
|
||||
);
|
||||
}
|
||||
GLOBAL.Text = {
|
||||
get defaultProps() {
|
||||
throw getInvalidGlobalUseError('Text');
|
||||
}
|
||||
};
|
||||
GLOBAL.Image = {
|
||||
get defaultProps() {
|
||||
throw getInvalidGlobalUseError('Image');
|
||||
}
|
||||
};
|
||||
// Force `ExecutionEnvironment.canUseDOM` to be false.
|
||||
if (GLOBAL.document) {
|
||||
GLOBAL.document.createElement = null;
|
||||
}
|
||||
|
||||
// There is no DOM so MutationObserver doesn't make sense. It is used
|
||||
// as feature detection in Bluebird Promise implementation
|
||||
GLOBAL.MutationObserver = undefined;
|
||||
}
|
||||
|
||||
function handleErrorWithRedBox(e) {
|
||||
function handleErrorWithRedBox(e, isFatal) {
|
||||
try {
|
||||
require('ExceptionsManager').handleException(e);
|
||||
require('ExceptionsManager').handleException(e, isFatal);
|
||||
} catch(ee) {
|
||||
console.log('Failed to print error: ', ee.message);
|
||||
}
|
||||
}
|
||||
|
||||
function setupRedBoxErrorHandler() {
|
||||
function setUpRedBoxErrorHandler() {
|
||||
var ErrorUtils = require('ErrorUtils');
|
||||
ErrorUtils.setGlobalHandler(handleErrorWithRedBox);
|
||||
}
|
||||
|
||||
function setupRedBoxConsoleErrorHandler() {
|
||||
function setUpRedBoxConsoleErrorHandler() {
|
||||
// ExceptionsManager transitively requires Promise so we install it after
|
||||
var ExceptionsManager = require('ExceptionsManager');
|
||||
var Platform = require('Platform');
|
||||
@@ -96,7 +63,7 @@ function setupRedBoxConsoleErrorHandler() {
|
||||
* implement our own custom timing bridge that should be immune to
|
||||
* unexplainably dropped timing signals.
|
||||
*/
|
||||
function setupTimers() {
|
||||
function setUpTimers() {
|
||||
var JSTimers = require('JSTimers');
|
||||
GLOBAL.setTimeout = JSTimers.setTimeout;
|
||||
GLOBAL.setInterval = JSTimers.setInterval;
|
||||
@@ -111,7 +78,7 @@ function setupTimers() {
|
||||
};
|
||||
}
|
||||
|
||||
function setupAlert() {
|
||||
function setUpAlert() {
|
||||
var RCTAlertManager = require('NativeModules').AlertManager;
|
||||
if (!GLOBAL.alert) {
|
||||
GLOBAL.alert = function(text) {
|
||||
@@ -125,13 +92,13 @@ function setupAlert() {
|
||||
}
|
||||
}
|
||||
|
||||
function setupPromise() {
|
||||
function setUpPromise() {
|
||||
// The native Promise implementation throws the following error:
|
||||
// ERROR: Event loop not supported.
|
||||
GLOBAL.Promise = require('Promise');
|
||||
}
|
||||
|
||||
function setupXHR() {
|
||||
function setUpXHR() {
|
||||
// The native XMLHttpRequest in Chrome dev tools is CORS aware and won't
|
||||
// let you fetch anything from the internet
|
||||
GLOBAL.XMLHttpRequest = require('XMLHttpRequest');
|
||||
@@ -143,16 +110,26 @@ function setupXHR() {
|
||||
GLOBAL.Response = fetchPolyfill.Response;
|
||||
}
|
||||
|
||||
function setupGeolocation() {
|
||||
function setUpGeolocation() {
|
||||
GLOBAL.navigator = GLOBAL.navigator || {};
|
||||
GLOBAL.navigator.geolocation = require('Geolocation');
|
||||
}
|
||||
|
||||
setupDocumentShim();
|
||||
setupRedBoxErrorHandler();
|
||||
setupTimers();
|
||||
setupAlert();
|
||||
setupPromise();
|
||||
setupXHR();
|
||||
setupRedBoxConsoleErrorHandler();
|
||||
setupGeolocation();
|
||||
function setUpWebSockets() {
|
||||
GLOBAL.WebSocket = require('WebSocket');
|
||||
}
|
||||
|
||||
function setupProfile() {
|
||||
console.profile = console.profile || GLOBAL.consoleProfile || function () {};
|
||||
console.profileEnd = console.profileEnd || GLOBAL.consoleProfileEnd || function () {};
|
||||
}
|
||||
|
||||
setUpRedBoxErrorHandler();
|
||||
setUpTimers();
|
||||
setUpAlert();
|
||||
setUpPromise();
|
||||
setUpXHR();
|
||||
setUpRedBoxConsoleErrorHandler();
|
||||
setUpGeolocation();
|
||||
setUpWebSockets();
|
||||
setupProfile();
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
* and wrapping resulting file into `wrapper` function.
|
||||
*
|
||||
*/
|
||||
/*eslint-disable */
|
||||
|
||||
var scope = {};
|
||||
wrapper.call(scope);
|
||||
|
||||
@@ -13,10 +13,13 @@
|
||||
'use strict';
|
||||
|
||||
var Promise = require('Promise');
|
||||
var RCTSourceCode = require('NativeModules').SourceCode;
|
||||
var NativeModules = require('NativeModules');
|
||||
var SourceMapConsumer = require('SourceMap').SourceMapConsumer;
|
||||
var SourceMapURL = require('./source-map-url');
|
||||
|
||||
var RCTSourceCode = NativeModules.SourceCode;
|
||||
var RCTDataManager = NativeModules.DataManager;
|
||||
|
||||
function loadSourceMap(): Promise {
|
||||
return fetchSourceMap()
|
||||
.then(map => new SourceMapConsumer(map));
|
||||
@@ -31,17 +34,31 @@ function fetchSourceMap(): Promise {
|
||||
return Promise.reject(new Error('RCTSourceCode module is not available'));
|
||||
}
|
||||
|
||||
if (!RCTDataManager) {
|
||||
// Used internally by fetch
|
||||
return Promise.reject(new Error('RCTDataManager module is not available'));
|
||||
}
|
||||
|
||||
return new Promise(RCTSourceCode.getScriptText)
|
||||
.then(extractSourceMapURL)
|
||||
.then((url) => {
|
||||
if (url === null) {
|
||||
return Promise.reject(new Error('No source map URL found. May be running from bundled file.'));
|
||||
}
|
||||
return Promise.resolve(url);
|
||||
})
|
||||
.then(fetch)
|
||||
.then(response => response.text())
|
||||
}
|
||||
|
||||
function extractSourceMapURL({url, text, fullSourceMappingURL}): string {
|
||||
function extractSourceMapURL({url, text, fullSourceMappingURL}): ?string {
|
||||
if (fullSourceMappingURL) {
|
||||
return fullSourceMappingURL;
|
||||
}
|
||||
var mapURL = SourceMapURL.getFrom(text);
|
||||
if (!mapURL) {
|
||||
return null;
|
||||
}
|
||||
var baseURL = url.match(/(.+:\/\/.*?)\//)[1];
|
||||
return baseURL + mapURL;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*
|
||||
* @nolint
|
||||
*/
|
||||
/* eslint-disable */
|
||||
|
||||
(function() {
|
||||
var define = null; // Hack to make it work with our packager
|
||||
|
||||
@@ -43,7 +43,6 @@ var JSTimers = {
|
||||
var newID = JSTimersExecution.GUID++;
|
||||
var freeIndex = JSTimers._getFreeIndex();
|
||||
JSTimersExecution.timerIDs[freeIndex] = newID;
|
||||
JSTimersExecution.callbacks[freeIndex] = func;
|
||||
JSTimersExecution.callbacks[freeIndex] = function() {
|
||||
return func.apply(undefined, args);
|
||||
};
|
||||
@@ -60,12 +59,15 @@ var JSTimers = {
|
||||
var newID = JSTimersExecution.GUID++;
|
||||
var freeIndex = JSTimers._getFreeIndex();
|
||||
JSTimersExecution.timerIDs[freeIndex] = newID;
|
||||
JSTimersExecution.callbacks[freeIndex] = func;
|
||||
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;
|
||||
RCTTiming.createTimer(newID, duration, Date.now(), /** recurring */ true);
|
||||
RCTTiming.createTimer(newID, duration, Date.now(), /** recurring */ false);
|
||||
return newID;
|
||||
},
|
||||
|
||||
@@ -77,7 +79,6 @@ var JSTimers = {
|
||||
var newID = JSTimersExecution.GUID++;
|
||||
var freeIndex = JSTimers._getFreeIndex();
|
||||
JSTimersExecution.timerIDs[freeIndex] = newID;
|
||||
JSTimersExecution.callbacks[freeIndex] = func;
|
||||
JSTimersExecution.callbacks[freeIndex] = function() {
|
||||
return func.apply(undefined, args);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/* eslint global-strict: 0 */
|
||||
(function(GLOBAL) {
|
||||
/**
|
||||
* The document must be shimmed before anything else that might define the
|
||||
* `ExecutionEnvironment` module (which checks for `document.createElement`).
|
||||
*/
|
||||
|
||||
// The browser defines Text and Image globals by default. If you forget to
|
||||
// require them, then the error message is very confusing.
|
||||
function getInvalidGlobalUseError(name) {
|
||||
return new Error(
|
||||
'You are trying to render the global ' + name + ' variable as a ' +
|
||||
'React element. You probably forgot to require ' + name + '.'
|
||||
);
|
||||
}
|
||||
GLOBAL.Text = {
|
||||
get defaultProps() {
|
||||
throw getInvalidGlobalUseError('Text');
|
||||
}
|
||||
};
|
||||
GLOBAL.Image = {
|
||||
get defaultProps() {
|
||||
throw getInvalidGlobalUseError('Image');
|
||||
}
|
||||
};
|
||||
// Force `ExecutionEnvironment.canUseDOM` to be false.
|
||||
if (GLOBAL.document) {
|
||||
GLOBAL.document.createElement = null;
|
||||
}
|
||||
|
||||
// There is no DOM so MutationObserver doesn't make sense. It is used
|
||||
// as feature detection in Bluebird Promise implementation
|
||||
GLOBAL.MutationObserver = undefined;
|
||||
})(this);
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @providesModule RCTNativeAppEventEmitter
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var EventEmitter = require('EventEmitter');
|
||||
|
||||
var RCTNativeAppEventEmitter = new EventEmitter();
|
||||
|
||||
module.exports = RCTNativeAppEventEmitter;
|
||||
@@ -15,13 +15,13 @@
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var React = require('React');
|
||||
var ReactChildren = require('ReactChildren');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var RCTPickerIOSConsts = require('NativeModules').UIManager.RCTPicker.Constants;
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var View = require('View');
|
||||
|
||||
var createReactIOSNativeComponentClass =
|
||||
require('createReactIOSNativeComponentClass');
|
||||
var createReactNativeComponentClass =
|
||||
require('createReactNativeComponentClass');
|
||||
var merge = require('merge');
|
||||
|
||||
var PICKER = 'picker';
|
||||
@@ -112,12 +112,12 @@ var styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
var rkPickerIOSAttributes = merge(ReactIOSViewAttributes.UIView, {
|
||||
var rkPickerIOSAttributes = merge(ReactNativeViewAttributes.UIView, {
|
||||
items: true,
|
||||
selectedIndex: true,
|
||||
});
|
||||
|
||||
var RCTPickerIOS = createReactIOSNativeComponentClass({
|
||||
var RCTPickerIOS = createReactNativeComponentClass({
|
||||
validAttributes: rkPickerIOSAttributes,
|
||||
uiViewClassName: 'RCTPicker',
|
||||
});
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var NativeModules = require('NativeModules');
|
||||
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||
var RCTPushNotificationManager = require('NativeModules').PushNotificationManager;
|
||||
var invariant = require('invariant');
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#import "FBSnapshotTestController.h"
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTUIManager.h"
|
||||
|
||||
@@ -63,4 +64,9 @@ RCT_EXPORT_METHOD(markTestCompleted)
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(sendAppEvent:(NSString *)name body:(id)body)
|
||||
{
|
||||
[_bridge.eventDispatcher sendAppEventWithName:name body:body];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
//
|
||||
// Copyright 2012 Square Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Security/SecCertificate.h>
|
||||
|
||||
typedef enum {
|
||||
SR_CONNECTING = 0,
|
||||
SR_OPEN = 1,
|
||||
SR_CLOSING = 2,
|
||||
SR_CLOSED = 3,
|
||||
} SRReadyState;
|
||||
|
||||
typedef enum SRStatusCode : NSInteger {
|
||||
SRStatusCodeNormal = 1000,
|
||||
SRStatusCodeGoingAway = 1001,
|
||||
SRStatusCodeProtocolError = 1002,
|
||||
SRStatusCodeUnhandledType = 1003,
|
||||
// 1004 reserved.
|
||||
SRStatusNoStatusReceived = 1005,
|
||||
// 1004-1006 reserved.
|
||||
SRStatusCodeInvalidUTF8 = 1007,
|
||||
SRStatusCodePolicyViolated = 1008,
|
||||
SRStatusCodeMessageTooBig = 1009,
|
||||
} SRStatusCode;
|
||||
|
||||
@class SRWebSocket;
|
||||
|
||||
extern NSString *const SRWebSocketErrorDomain;
|
||||
extern NSString *const SRHTTPResponseErrorKey;
|
||||
|
||||
#pragma mark - SRWebSocketDelegate
|
||||
|
||||
@protocol SRWebSocketDelegate;
|
||||
|
||||
#pragma mark - SRWebSocket
|
||||
|
||||
@interface SRWebSocket : NSObject <NSStreamDelegate>
|
||||
|
||||
@property (nonatomic, weak) id <SRWebSocketDelegate> delegate;
|
||||
|
||||
@property (nonatomic, readonly) SRReadyState readyState;
|
||||
@property (nonatomic, readonly, retain) NSURL *url;
|
||||
|
||||
// This returns the negotiated protocol.
|
||||
// It will be nil until after the handshake completes.
|
||||
@property (nonatomic, readonly, copy) NSString *protocol;
|
||||
|
||||
// Protocols should be an array of strings that turn into Sec-WebSocket-Protocol.
|
||||
- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols;
|
||||
- (id)initWithURLRequest:(NSURLRequest *)request;
|
||||
|
||||
// Some helper constructors.
|
||||
- (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols;
|
||||
- (id)initWithURL:(NSURL *)url;
|
||||
|
||||
// Delegate queue will be dispatch_main_queue by default.
|
||||
// You cannot set both OperationQueue and dispatch_queue.
|
||||
- (void)setDelegateOperationQueue:(NSOperationQueue*) queue;
|
||||
- (void)setDelegateDispatchQueue:(dispatch_queue_t) queue;
|
||||
|
||||
// By default, it will schedule itself on +[NSRunLoop SR_networkRunLoop] using defaultModes.
|
||||
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
|
||||
- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
|
||||
|
||||
// SRWebSockets are intended for one-time-use only. Open should be called once and only once.
|
||||
- (void)open;
|
||||
|
||||
- (void)close;
|
||||
- (void)closeWithCode:(NSInteger)code reason:(NSString *)reason;
|
||||
|
||||
// Send a UTF8 String or Data.
|
||||
- (void)send:(id)data;
|
||||
|
||||
// Send Data (can be nil) in a ping message.
|
||||
- (void)sendPing:(NSData *)data;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - SRWebSocketDelegate
|
||||
|
||||
@protocol SRWebSocketDelegate <NSObject>
|
||||
|
||||
// message will either be an NSString if the server is using text
|
||||
// or NSData if the server is using binary.
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message;
|
||||
|
||||
@optional
|
||||
|
||||
- (void)webSocketDidOpen:(SRWebSocket *)webSocket;
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean;
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - NSURLRequest (CertificateAdditions)
|
||||
|
||||
@interface NSURLRequest (CertificateAdditions)
|
||||
|
||||
@property (nonatomic, retain, readonly) NSArray *SR_SSLPinnedCertificates;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - NSMutableURLRequest (CertificateAdditions)
|
||||
|
||||
@interface NSMutableURLRequest (CertificateAdditions)
|
||||
|
||||
@property (nonatomic, retain) NSArray *SR_SSLPinnedCertificates;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - NSRunLoop (SRWebSocket)
|
||||
|
||||
@interface NSRunLoop (SRWebSocket)
|
||||
|
||||
+ (NSRunLoop *)SR_networkRunLoop;
|
||||
|
||||
@end
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var ReactIOSTagHandles = require('ReactIOSTagHandles');
|
||||
var ReactNativeTagHandles = require('ReactNativeTagHandles');
|
||||
var RCTUIManager = require('NativeModules').UIManager;
|
||||
|
||||
type OnSuccessCallback = (
|
||||
@@ -52,10 +52,9 @@ var queryLayoutByID = function(
|
||||
): void {
|
||||
// Native bridge doesn't *yet* surface errors.
|
||||
RCTUIManager.measure(
|
||||
ReactIOSTagHandles.rootNodeIDToTag[rootNodeID],
|
||||
ReactNativeTagHandles.rootNodeIDToTag[rootNodeID],
|
||||
onSuccess
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = queryLayoutByID;
|
||||
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
* @providesModule IOSNativeBridgeEventPlugin
|
||||
* @flow
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var EventPropagators = require('EventPropagators');
|
||||
var NativeModules = require('NativeModules');
|
||||
@@ -33,7 +32,7 @@ for (var bubblingTypeName in customBubblingEventTypes) {
|
||||
for (var directTypeName in customDirectEventTypes) {
|
||||
warning(
|
||||
!customBubblingEventTypes[directTypeName],
|
||||
"Event cannot be both direct and bubbling: %s",
|
||||
'Event cannot be both direct and bubbling: %s',
|
||||
directTypeName
|
||||
);
|
||||
allTypesByEventName[directTypeName] = customDirectEventTypes[directTypeName];
|
||||
@@ -76,4 +75,3 @@ var IOSNativeBridgeEventPlugin = {
|
||||
};
|
||||
|
||||
module.exports = IOSNativeBridgeEventPlugin;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ var RCTPOPAnimationManager = NativeModules.POPAnimationManager;
|
||||
var RCTUIManager = NativeModules.UIManager;
|
||||
var TextInputState = require('TextInputState');
|
||||
|
||||
var findNodeHandle = require('findNodeHandle');
|
||||
var flattenStyle = require('flattenStyle');
|
||||
var invariant = require('invariant');
|
||||
var mergeFast = require('mergeFast');
|
||||
@@ -51,16 +52,23 @@ var animationIDInvariant = function(
|
||||
var NativeMethodsMixin = {
|
||||
addAnimation: function(anim: number, callback?: (finished: bool) => void) {
|
||||
animationIDInvariant('addAnimation', anim);
|
||||
RCTPOPAnimationManager.addAnimation(this.getNodeHandle(), anim, callback);
|
||||
RCTPOPAnimationManager.addAnimation(
|
||||
findNodeHandle(this),
|
||||
anim,
|
||||
mountSafeCallback(this, callback)
|
||||
);
|
||||
},
|
||||
|
||||
removeAnimation: function(anim: number) {
|
||||
animationIDInvariant('removeAnimation', anim);
|
||||
RCTPOPAnimationManager.removeAnimation(this.getNodeHandle(), anim);
|
||||
RCTPOPAnimationManager.removeAnimation(findNodeHandle(this), anim);
|
||||
},
|
||||
|
||||
measure: function(callback: MeasureOnSuccessCallback) {
|
||||
RCTUIManager.measure(this.getNodeHandle(), callback);
|
||||
RCTUIManager.measure(
|
||||
findNodeHandle(this),
|
||||
mountSafeCallback(this, callback)
|
||||
);
|
||||
},
|
||||
|
||||
measureLayout: function(
|
||||
@@ -69,10 +77,10 @@ var NativeMethodsMixin = {
|
||||
onFail: () => void /* currently unused */
|
||||
) {
|
||||
RCTUIManager.measureLayout(
|
||||
this.getNodeHandle(),
|
||||
findNodeHandle(this),
|
||||
relativeToNativeNode,
|
||||
onFail,
|
||||
onSuccess
|
||||
mountSafeCallback(this, onFail),
|
||||
mountSafeCallback(this, onSuccess)
|
||||
);
|
||||
},
|
||||
|
||||
@@ -106,18 +114,18 @@ var NativeMethodsMixin = {
|
||||
}
|
||||
|
||||
RCTUIManager.updateView(
|
||||
this.getNodeHandle(),
|
||||
findNodeHandle(this),
|
||||
this.viewConfig.uiViewClassName,
|
||||
props
|
||||
);
|
||||
},
|
||||
|
||||
focus: function() {
|
||||
TextInputState.focusTextInput(this.getNodeHandle());
|
||||
TextInputState.focusTextInput(findNodeHandle(this));
|
||||
},
|
||||
|
||||
blur: function() {
|
||||
TextInputState.blurTextInput(this.getNodeHandle());
|
||||
TextInputState.blurTextInput(findNodeHandle(this));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -152,4 +160,17 @@ if (__DEV__) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* In the future, we should cleanup callbacks by cancelling them instead of
|
||||
* using this.
|
||||
*/
|
||||
var mountSafeCallback = function(context: ReactComponent, callback: ?Function): any {
|
||||
return function() {
|
||||
if (!callback || (context.isMounted && !context.isMounted())) {
|
||||
return;
|
||||
}
|
||||
return callback.apply(context, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = NativeMethodsMixin;
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @providesModule ReactIOSComponentMixin
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var ReactIOSTagHandles = require('ReactIOSTagHandles');
|
||||
var ReactInstanceMap = require('ReactInstanceMap');
|
||||
|
||||
/**
|
||||
* ReactNative vs ReactWeb
|
||||
* -----------------------
|
||||
* React treats some pieces of data opaquely. This means that the information
|
||||
* is first class (it can be passed around), but cannot be inspected. This
|
||||
* allows us to build infrastructure that reasons about resources, without
|
||||
* making assumptions about the nature of those resources, and this allows that
|
||||
* infra to be shared across multiple platforms, where the resources are very
|
||||
* different. General infra (such as `ReactMultiChild`) reasons opaquely about
|
||||
* the data, but platform specific code (such as `ReactIOSNativeComponent`) can
|
||||
* make assumptions about the data.
|
||||
*
|
||||
*
|
||||
* `rootNodeID`, uniquely identifies a position in the generated native view
|
||||
* tree. Many layers of composite components (created with `React.createClass`)
|
||||
* can all share the same `rootNodeID`.
|
||||
*
|
||||
* `nodeHandle`: A sufficiently unambiguous way to refer to a lower level
|
||||
* resource (dom node, native view etc). The `rootNodeID` is sufficient for web
|
||||
* `nodeHandle`s, because the position in a tree is always enough to uniquely
|
||||
* identify a DOM node (we never have nodes in some bank outside of the
|
||||
* document). The same would be true for `ReactNative`, but we must maintain a
|
||||
* mapping that we can send efficiently serializable
|
||||
* strings across native boundaries.
|
||||
*
|
||||
* Opaque name TodaysWebReact FutureWebWorkerReact ReactNative
|
||||
* ----------------------------------------------------------------------------
|
||||
* nodeHandle N/A rootNodeID tag
|
||||
*
|
||||
*
|
||||
* `mountImage`: A way to represent the potential to create lower level
|
||||
* resources whos `nodeHandle` can be discovered immediately by knowing the
|
||||
* `rootNodeID`. Today's web React represents this with `innerHTML` annotated
|
||||
* with DOM ids that match the `rootNodeID`.
|
||||
*
|
||||
* Opaque name TodaysWebReact FutureWebWorkerReact ReactNative
|
||||
* ----------------------------------------------------------------------------
|
||||
* mountImage innerHTML innerHTML {rootNodeID, tag}
|
||||
*
|
||||
*/
|
||||
var ReactIOSComponentMixin = {
|
||||
/**
|
||||
* This has no particular meaning in ReactIOS. If this were in the DOM, this
|
||||
* would return the DOM node. There should be nothing that invokes this
|
||||
* method. Any current callers of this are mistaken - they should be invoking
|
||||
* `getNodeHandle`.
|
||||
*/
|
||||
getNativeNode: function() {
|
||||
// TODO (balpert): Wrap iOS native components in a composite wrapper, then
|
||||
// ReactInstanceMap.get here will always succeed
|
||||
return ReactIOSTagHandles.rootNodeIDToTag[
|
||||
(ReactInstanceMap.get(this) || this)._rootNodeID
|
||||
];
|
||||
},
|
||||
|
||||
getNodeHandle: function() {
|
||||
return ReactIOSTagHandles.rootNodeIDToTag[
|
||||
(ReactInstanceMap.get(this) || this)._rootNodeID
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = ReactIOSComponentMixin;
|
||||
@@ -14,7 +14,7 @@
|
||||
var RCTUIManager = require('NativeModules').UIManager;
|
||||
var UnimplementedView = require('UnimplementedView');
|
||||
|
||||
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
var deepDiffer = require('deepDiffer');
|
||||
var insetsDiffer = require('insetsDiffer');
|
||||
var pointsDiffer = require('pointsDiffer');
|
||||
@@ -59,7 +59,7 @@ function requireNativeComponent(
|
||||
if (__DEV__) {
|
||||
wrapperComponent && verifyPropTypes(wrapperComponent, viewConfig);
|
||||
}
|
||||
return createReactIOSNativeComponentClass(viewConfig);
|
||||
return createReactNativeComponentClass(viewConfig);
|
||||
}
|
||||
|
||||
var TypeToDifferMap = {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var ReactIOSStyleAttributes = require('ReactIOSStyleAttributes');
|
||||
var ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
|
||||
var View = require('View');
|
||||
|
||||
function verifyPropTypes(
|
||||
@@ -22,16 +22,23 @@ function verifyPropTypes(
|
||||
if (!viewConfig) {
|
||||
return; // This happens for UnimplementedView.
|
||||
}
|
||||
var componentName = component.name || component.displayName;
|
||||
if (!component.propTypes) {
|
||||
throw new Error(
|
||||
'`' + componentName + '` has no propTypes defined`'
|
||||
);
|
||||
}
|
||||
|
||||
var nativeProps = viewConfig.nativeProps;
|
||||
for (var prop in nativeProps) {
|
||||
if (!component.propTypes[prop] &&
|
||||
!View.propTypes[prop] &&
|
||||
!ReactIOSStyleAttributes[prop] &&
|
||||
!ReactNativeStyleAttributes[prop] &&
|
||||
(!nativePropsToIgnore || !nativePropsToIgnore[prop])) {
|
||||
throw new Error(
|
||||
'`' + component.displayName + '` has no propType for native prop `' +
|
||||
'`' + componentName + '` has no propType for native prop `' +
|
||||
viewConfig.uiViewClassName + '.' + prop + '` of native type `' +
|
||||
nativeProps[prop].type + '`'
|
||||
nativeProps[prop] + '`'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||