Merge pull request #1184 from frantic/sync-2015-05-06
Updates from Wed 6 May
This commit is contained in:
commit
07937620c0
|
@ -17,6 +17,7 @@
|
||||||
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
|
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
|
||||||
00E356F31AD99517003FC87E /* SampleAppTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* SampleAppTests.m */; };
|
00E356F31AD99517003FC87E /* SampleAppTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* SampleAppTests.m */; };
|
||||||
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
|
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
|
||||||
|
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
|
||||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||||
|
@ -82,6 +83,13 @@
|
||||||
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
||||||
remoteInfo = SampleApp;
|
remoteInfo = SampleApp;
|
||||||
};
|
};
|
||||||
|
139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
|
||||||
|
proxyType = 2;
|
||||||
|
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||||
|
remoteInfo = RCTSettings;
|
||||||
|
};
|
||||||
146834031AC3E56700842450 /* PBXContainerItemProxy */ = {
|
146834031AC3E56700842450 /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
|
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
|
||||||
|
@ -117,6 +125,7 @@
|
||||||
00E356EE1AD99517003FC87E /* SampleAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
00E356EE1AD99517003FC87E /* SampleAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
||||||
13B07F961A680F5B00A75B9A /* SampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
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>"; };
|
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>"; };
|
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = iOS/AppDelegate.m; sourceTree = "<group>"; };
|
||||||
|
@ -142,6 +151,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
146834051AC3E58100842450 /* libReact.a in Frameworks */,
|
146834051AC3E58100842450 /* libReact.a in Frameworks */,
|
||||||
|
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,
|
||||||
00481BE81AC0C86700671115 /* libRCTWebSocketDebugger.a in Frameworks */,
|
00481BE81AC0C86700671115 /* libRCTWebSocketDebugger.a in Frameworks */,
|
||||||
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
|
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
|
||||||
00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */,
|
00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */,
|
||||||
|
@ -230,6 +240,14 @@
|
||||||
name = "Supporting Files";
|
name = "Supporting Files";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
139105B71AF99BAD00B5F7CC /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
139105C11AF99BAD00B5F7CC /* libRCTSettings.a */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
13B07FAE1A68108700A75B9A /* SampleApp */ = {
|
13B07FAE1A68108700A75B9A /* SampleApp */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -263,14 +281,15 @@
|
||||||
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
|
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,
|
|
||||||
146833FF1AC3E56700842450 /* React.xcodeproj */,
|
146833FF1AC3E56700842450 /* React.xcodeproj */,
|
||||||
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
|
|
||||||
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
|
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
|
||||||
00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */,
|
00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */,
|
||||||
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
|
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
|
||||||
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,
|
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,
|
||||||
|
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,
|
||||||
00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */,
|
00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */,
|
||||||
|
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */,
|
||||||
|
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
|
||||||
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
|
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
|
||||||
00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */,
|
00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */,
|
||||||
);
|
);
|
||||||
|
@ -395,6 +414,10 @@
|
||||||
ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */;
|
ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */;
|
||||||
ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
|
ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */;
|
||||||
|
ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ProductGroup = 832341B11AAA6A8300B99B32 /* Products */;
|
ProductGroup = 832341B11AAA6A8300B99B32 /* Products */;
|
||||||
ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
|
ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
|
||||||
|
@ -470,6 +493,13 @@
|
||||||
remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;
|
remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;
|
||||||
sourceTree = BUILT_PRODUCTS_DIR;
|
sourceTree = BUILT_PRODUCTS_DIR;
|
||||||
};
|
};
|
||||||
|
139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = {
|
||||||
|
isa = PBXReferenceProxy;
|
||||||
|
fileType = archive.ar;
|
||||||
|
path = libRCTSettings.a;
|
||||||
|
remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */;
|
||||||
|
sourceTree = BUILT_PRODUCTS_DIR;
|
||||||
|
};
|
||||||
146834041AC3E56700842450 /* libReact.a */ = {
|
146834041AC3E56700842450 /* libReact.a */ = {
|
||||||
isa = PBXReferenceProxy;
|
isa = PBXReferenceProxy;
|
||||||
fileType = archive.ar;
|
fileType = archive.ar;
|
||||||
|
|
|
@ -24,7 +24,7 @@ var SampleApp = React.createClass({
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={styles.instructions}>
|
<Text style={styles.instructions}>
|
||||||
Press Cmd+R to reload,{'\n'}
|
Press Cmd+R to reload,{'\n'}
|
||||||
Cmd+Control+Z for dev menu
|
Cmd+D or shake for dev menu
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,12 +13,14 @@
|
||||||
|
|
||||||
var LayoutPropTypes = require('LayoutPropTypes');
|
var LayoutPropTypes = require('LayoutPropTypes');
|
||||||
var ReactPropTypes = require('ReactPropTypes');
|
var ReactPropTypes = require('ReactPropTypes');
|
||||||
|
var TransformPropTypes = require('TransformPropTypes');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Warning: Some of these properties may not be supported in all releases.
|
* Warning: Some of these properties may not be supported in all releases.
|
||||||
*/
|
*/
|
||||||
var ViewStylePropTypes = {
|
var ViewStylePropTypes = {
|
||||||
...LayoutPropTypes,
|
...LayoutPropTypes,
|
||||||
|
...TransformPropTypes,
|
||||||
backgroundColor: ReactPropTypes.string,
|
backgroundColor: ReactPropTypes.string,
|
||||||
borderColor: ReactPropTypes.string,
|
borderColor: ReactPropTypes.string,
|
||||||
borderTopColor: ReactPropTypes.string,
|
borderTopColor: ReactPropTypes.string,
|
||||||
|
@ -34,15 +36,6 @@ var ViewStylePropTypes = {
|
||||||
),
|
),
|
||||||
shadowOpacity: ReactPropTypes.number,
|
shadowOpacity: ReactPropTypes.number,
|
||||||
shadowRadius: ReactPropTypes.number,
|
shadowRadius: ReactPropTypes.number,
|
||||||
transform: ReactPropTypes.arrayOf(ReactPropTypes.object),
|
|
||||||
transformMatrix: ReactPropTypes.arrayOf(ReactPropTypes.number),
|
|
||||||
|
|
||||||
// DEPRECATED
|
|
||||||
rotation: ReactPropTypes.number,
|
|
||||||
scaleX: ReactPropTypes.number,
|
|
||||||
scaleY: ReactPropTypes.number,
|
|
||||||
translateX: ReactPropTypes.number,
|
|
||||||
translateY: ReactPropTypes.number,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = ViewStylePropTypes;
|
module.exports = ViewStylePropTypes;
|
||||||
|
|
|
@ -227,15 +227,17 @@ var Navigator = React.createClass({
|
||||||
renderScene: PropTypes.func.isRequired,
|
renderScene: PropTypes.func.isRequired,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide a single "route" to start on. A route is an arbitrary object
|
* Specify a route to start on. A route is an object that the navigator
|
||||||
* that the navigator will use to identify each scene before rendering.
|
* will use to identify each scene to render. `initialRoute` must be
|
||||||
* Either initialRoute or initialRouteStack is required.
|
* a route in the `initialRouteStack` if both props are provided. The
|
||||||
|
* `initialRoute` will default to the last item in the `initialRouteStack`.
|
||||||
*/
|
*/
|
||||||
initialRoute: PropTypes.object,
|
initialRoute: PropTypes.object,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide a set of routes to initially mount the scenes for. Required if no
|
* Provide a set of routes to initially mount. Required if no initialRoute
|
||||||
* initialRoute is provided
|
* is provided. Otherwise, it will default to an array containing only the
|
||||||
|
* `initialRoute`
|
||||||
*/
|
*/
|
||||||
initialRouteStack: PropTypes.arrayOf(PropTypes.object),
|
initialRouteStack: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
|
||||||
|
@ -295,21 +297,18 @@ var Navigator = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
var routeStack = this.props.initialRouteStack || [];
|
var routeStack = this.props.initialRouteStack || [this.props.initialRoute];
|
||||||
var initialRouteIndex = 0;
|
invariant(
|
||||||
if (this.props.initialRoute && routeStack.length) {
|
routeStack.length >= 1,
|
||||||
|
'Navigator requires props.initialRoute or props.initialRouteStack.'
|
||||||
|
);
|
||||||
|
var initialRouteIndex = routeStack.length - 1;
|
||||||
|
if (this.props.initialRoute) {
|
||||||
initialRouteIndex = routeStack.indexOf(this.props.initialRoute);
|
initialRouteIndex = routeStack.indexOf(this.props.initialRoute);
|
||||||
invariant(
|
invariant(
|
||||||
initialRouteIndex !== -1,
|
initialRouteIndex !== -1,
|
||||||
'initialRoute is not in initialRouteStack.'
|
'initialRoute is not in initialRouteStack.'
|
||||||
);
|
);
|
||||||
} else if (this.props.initialRoute) {
|
|
||||||
routeStack = [this.props.initialRoute];
|
|
||||||
} else {
|
|
||||||
invariant(
|
|
||||||
routeStack.length >= 1,
|
|
||||||
'Navigator requires props.initialRoute or props.initialRouteStack.'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
sceneConfigStack: routeStack.map(
|
sceneConfigStack: routeStack.map(
|
||||||
|
@ -689,7 +688,8 @@ var Navigator = React.createClass({
|
||||||
var enabledSceneNativeProps = {
|
var enabledSceneNativeProps = {
|
||||||
left: sceneStyle.left,
|
left: sceneStyle.left,
|
||||||
};
|
};
|
||||||
if (sceneIndex !== this.state.transitionFromIndex) {
|
if (sceneIndex !== this.state.transitionFromIndex &&
|
||||||
|
sceneIndex !== this.state.presentedIndex) {
|
||||||
// If we are not in a transition from this index, make sure opacity is 0
|
// If we are not in a transition from this index, make sure opacity is 0
|
||||||
// to prevent the enabled scene from flashing over the presented scene
|
// to prevent the enabled scene from flashing over the presented scene
|
||||||
enabledSceneNativeProps.opacity = 0;
|
enabledSceneNativeProps.opacity = 0;
|
||||||
|
|
|
@ -14,9 +14,11 @@
|
||||||
var ImageResizeMode = require('ImageResizeMode');
|
var ImageResizeMode = require('ImageResizeMode');
|
||||||
var LayoutPropTypes = require('LayoutPropTypes');
|
var LayoutPropTypes = require('LayoutPropTypes');
|
||||||
var ReactPropTypes = require('ReactPropTypes');
|
var ReactPropTypes = require('ReactPropTypes');
|
||||||
|
var TransformPropTypes = require('TransformPropTypes');
|
||||||
|
|
||||||
var ImageStylePropTypes = {
|
var ImageStylePropTypes = {
|
||||||
...LayoutPropTypes,
|
...LayoutPropTypes,
|
||||||
|
...TransformPropTypes,
|
||||||
resizeMode: ReactPropTypes.oneOf(Object.keys(ImageResizeMode)),
|
resizeMode: ReactPropTypes.oneOf(Object.keys(ImageResizeMode)),
|
||||||
backgroundColor: ReactPropTypes.string,
|
backgroundColor: ReactPropTypes.string,
|
||||||
borderColor: ReactPropTypes.string,
|
borderColor: ReactPropTypes.string,
|
||||||
|
|
|
@ -66,7 +66,7 @@ class XMLHttpRequestBase {
|
||||||
|
|
||||||
getResponseHeader(header: string): ?string {
|
getResponseHeader(header: string): ?string {
|
||||||
if (this.responseHeaders) {
|
if (this.responseHeaders) {
|
||||||
var value = this.responseHeaders[header];
|
var value = this.responseHeaders[header.toLowerCase()];
|
||||||
return value !== undefined ? value : null;
|
return value !== undefined ? value : null;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -132,7 +132,12 @@ class XMLHttpRequestBase {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.status = status;
|
this.status = status;
|
||||||
this.responseHeaders = responseHeaders || {};
|
// Headers should be case-insensitive
|
||||||
|
var lcResponseHeaders = {};
|
||||||
|
for (var header in responseHeaders) {
|
||||||
|
lcResponseHeaders[header.toLowerCase()] = responseHeaders[header];
|
||||||
|
}
|
||||||
|
this.responseHeaders = lcResponseHeaders;
|
||||||
this.responseText = responseText;
|
this.responseText = responseText;
|
||||||
this._setReadyState(this.DONE);
|
this._setReadyState(this.DONE);
|
||||||
this._sendLoad();
|
this._sendLoad();
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#import "RCTBridge.h"
|
#import "RCTBridge.h"
|
||||||
#import "RCTConvert.h"
|
#import "RCTConvert.h"
|
||||||
#import "RCTEventDispatcher.h"
|
#import "RCTEventDispatcher.h"
|
||||||
|
#import "RCTUtils.h"
|
||||||
|
|
||||||
@implementation RCTSettingsManager
|
@implementation RCTSettingsManager
|
||||||
{
|
{
|
||||||
|
@ -53,13 +54,15 @@ RCT_EXPORT_MODULE()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"settingsUpdated" body:[_defaults dictionaryRepresentation]];
|
[_bridge.eventDispatcher
|
||||||
|
sendDeviceEventWithName:@"settingsUpdated"
|
||||||
|
body:RCTJSONClean([_defaults dictionaryRepresentation])];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary *)constantsToExport
|
- (NSDictionary *)constantsToExport
|
||||||
{
|
{
|
||||||
return @{
|
return @{
|
||||||
@"settings": [_defaults dictionaryRepresentation]
|
@"settings": RCTJSONClean([_defaults dictionaryRepresentation])
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* 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 TransformPropTypes
|
||||||
|
* @flow
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var ReactPropTypes = require('ReactPropTypes');
|
||||||
|
|
||||||
|
var TransformPropTypes = {
|
||||||
|
transform: ReactPropTypes.arrayOf(ReactPropTypes.object),
|
||||||
|
transformMatrix: ReactPropTypes.arrayOf(ReactPropTypes.number),
|
||||||
|
|
||||||
|
// DEPRECATED
|
||||||
|
rotation: ReactPropTypes.number,
|
||||||
|
scaleX: ReactPropTypes.number,
|
||||||
|
scaleY: ReactPropTypes.number,
|
||||||
|
translateX: ReactPropTypes.number,
|
||||||
|
translateY: ReactPropTypes.number,
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = TransformPropTypes;
|
|
@ -39,6 +39,7 @@
|
||||||
+ (NSString *)NSString:(id)json;
|
+ (NSString *)NSString:(id)json;
|
||||||
+ (NSNumber *)NSNumber:(id)json;
|
+ (NSNumber *)NSNumber:(id)json;
|
||||||
+ (NSData *)NSData:(id)json;
|
+ (NSData *)NSData:(id)json;
|
||||||
|
+ (NSIndexSet *)NSIndexSet:(id)json;
|
||||||
|
|
||||||
+ (NSURL *)NSURL:(id)json;
|
+ (NSURL *)NSURL:(id)json;
|
||||||
+ (NSURLRequest *)NSURLRequest:(id)json;
|
+ (NSURLRequest *)NSURLRequest:(id)json;
|
||||||
|
@ -76,6 +77,7 @@
|
||||||
+ (UIImage *)UIImage:(id)json;
|
+ (UIImage *)UIImage:(id)json;
|
||||||
+ (CGImageRef)CGImage:(id)json;
|
+ (CGImageRef)CGImage:(id)json;
|
||||||
|
|
||||||
|
+ (UIFont *)UIFont:(id)json;
|
||||||
+ (UIFont *)UIFont:(UIFont *)font withSize:(id)json;
|
+ (UIFont *)UIFont:(UIFont *)font withSize:(id)json;
|
||||||
+ (UIFont *)UIFont:(UIFont *)font withWeight:(id)json;
|
+ (UIFont *)UIFont:(UIFont *)font withWeight:(id)json;
|
||||||
+ (UIFont *)UIFont:(UIFont *)font withStyle:(id)json;
|
+ (UIFont *)UIFont:(UIFont *)font withStyle:(id)json;
|
||||||
|
|
|
@ -64,6 +64,20 @@ RCT_CONVERTER(NSString *, NSString, description)
|
||||||
return [[self NSString:json] dataUsingEncoding:NSUTF8StringEncoding];
|
return [[self NSString:json] dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSIndexSet *)NSIndexSet:(id)json
|
||||||
|
{
|
||||||
|
json = [self NSNumberArray:json];
|
||||||
|
NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] init];
|
||||||
|
for (NSNumber *number in json) {
|
||||||
|
NSInteger index = number.integerValue;
|
||||||
|
if (RCT_DEBUG && index < 0) {
|
||||||
|
RCTLogError(@"Invalid index value %zd. Indices must be positive.", index);
|
||||||
|
}
|
||||||
|
[indexSet addIndex:index];
|
||||||
|
}
|
||||||
|
return indexSet;
|
||||||
|
}
|
||||||
|
|
||||||
+ (NSURL *)NSURL:(id)json
|
+ (NSURL *)NSURL:(id)json
|
||||||
{
|
{
|
||||||
NSString *path = [self NSString:json];
|
NSString *path = [self NSString:json];
|
||||||
|
@ -679,6 +693,16 @@ static BOOL RCTFontIsCondensed(UIFont *font)
|
||||||
return (symbolicTraits & UIFontDescriptorTraitCondensed) != 0;
|
return (symbolicTraits & UIFontDescriptorTraitCondensed) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (UIFont *)UIFont:(id)json
|
||||||
|
{
|
||||||
|
json = [self NSDictionary:json];
|
||||||
|
return [self UIFont:nil
|
||||||
|
withFamily:json[@"fontFamily"]
|
||||||
|
size:json[@"fontSize"]
|
||||||
|
weight:json[@"fontWeight"]
|
||||||
|
style:json[@"fontStyle"]];
|
||||||
|
}
|
||||||
|
|
||||||
+ (UIFont *)UIFont:(UIFont *)font withSize:(id)json
|
+ (UIFont *)UIFont:(UIFont *)font withSize:(id)json
|
||||||
{
|
{
|
||||||
return [self UIFont:font withFamily:nil size:json weight:nil style:nil];
|
return [self UIFont:font withFamily:nil size:json weight:nil style:nil];
|
||||||
|
@ -728,11 +752,6 @@ static BOOL RCTFontIsCondensed(UIFont *font)
|
||||||
// Get font family
|
// Get font family
|
||||||
familyName = [self NSString:family] ?: familyName;
|
familyName = [self NSString:family] ?: familyName;
|
||||||
|
|
||||||
// Get font style
|
|
||||||
if (style) {
|
|
||||||
isItalic = [self RCTFontStyle:style];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gracefully handle being given a font name rather than font family, for
|
// Gracefully handle being given a font name rather than font family, for
|
||||||
// example: "Helvetica Light Oblique" rather than just "Helvetica".
|
// example: "Helvetica Light Oblique" rather than just "Helvetica".
|
||||||
if ([UIFont fontNamesForFamilyName:familyName].count == 0) {
|
if ([UIFont fontNamesForFamilyName:familyName].count == 0) {
|
||||||
|
@ -751,6 +770,11 @@ static BOOL RCTFontIsCondensed(UIFont *font)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get font style
|
||||||
|
if (style) {
|
||||||
|
isItalic = [self RCTFontStyle:style];
|
||||||
|
}
|
||||||
|
|
||||||
// Get font weight
|
// Get font weight
|
||||||
if (weight) {
|
if (weight) {
|
||||||
fontWeight = [self RCTFontWeight:weight];
|
fontWeight = [self RCTFontWeight:weight];
|
||||||
|
@ -758,13 +782,7 @@ static BOOL RCTFontIsCondensed(UIFont *font)
|
||||||
|
|
||||||
// Get the closest font that matches the given weight for the fontFamily
|
// Get the closest font that matches the given weight for the fontFamily
|
||||||
UIFont *bestMatch = [UIFont fontWithName:font.fontName size: fontSize];
|
UIFont *bestMatch = [UIFont fontWithName:font.fontName size: fontSize];
|
||||||
CGFloat closestWeight;
|
CGFloat closestWeight = INFINITY;
|
||||||
|
|
||||||
if (font && [font.familyName isEqualToString: familyName]) {
|
|
||||||
closestWeight = RCTWeightOfFont(font);
|
|
||||||
} else {
|
|
||||||
closestWeight = INFINITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (NSString *name in [UIFont fontNamesForFamilyName:familyName]) {
|
for (NSString *name in [UIFont fontNamesForFamilyName:familyName]) {
|
||||||
UIFont *match = [UIFont fontWithName:name size:fontSize];
|
UIFont *match = [UIFont fontWithName:name size:fontSize];
|
||||||
|
@ -834,7 +852,9 @@ static id RCTConvertPropertyListValue(id json)
|
||||||
{
|
{
|
||||||
if (!json || json == (id)kCFNull) {
|
if (!json || json == (id)kCFNull) {
|
||||||
return nil;
|
return nil;
|
||||||
} else if ([json isKindOfClass:[NSDictionary class]]) {
|
}
|
||||||
|
|
||||||
|
if ([json isKindOfClass:[NSDictionary class]]) {
|
||||||
__block BOOL copy = NO;
|
__block BOOL copy = NO;
|
||||||
NSMutableDictionary *values = [[NSMutableDictionary alloc] initWithCapacity:[json count]];
|
NSMutableDictionary *values = [[NSMutableDictionary alloc] initWithCapacity:[json count]];
|
||||||
[json enumerateKeysAndObjectsUsingBlock:^(NSString *key, id jsonValue, BOOL *stop) {
|
[json enumerateKeysAndObjectsUsingBlock:^(NSString *key, id jsonValue, BOOL *stop) {
|
||||||
|
@ -845,7 +865,9 @@ static id RCTConvertPropertyListValue(id json)
|
||||||
copy |= value != jsonValue;
|
copy |= value != jsonValue;
|
||||||
}];
|
}];
|
||||||
return copy ? values : json;
|
return copy ? values : json;
|
||||||
} else if ([json isKindOfClass:[NSArray class]]) {
|
}
|
||||||
|
|
||||||
|
if ([json isKindOfClass:[NSArray class]]) {
|
||||||
__block BOOL copy = NO;
|
__block BOOL copy = NO;
|
||||||
__block NSArray *values = json;
|
__block NSArray *values = json;
|
||||||
[json enumerateObjectsUsingBlock:^(id jsonValue, NSUInteger idx, BOOL *stop) {
|
[json enumerateObjectsUsingBlock:^(id jsonValue, NSUInteger idx, BOOL *stop) {
|
||||||
|
@ -860,15 +882,17 @@ static id RCTConvertPropertyListValue(id json)
|
||||||
for (NSInteger i = 0; i < idx; i++) {
|
for (NSInteger i = 0; i < idx; i++) {
|
||||||
[(NSMutableArray *)values addObject:json[i]];
|
[(NSMutableArray *)values addObject:json[i]];
|
||||||
}
|
}
|
||||||
[(NSMutableArray *)values addObject:value];
|
if (value) {
|
||||||
|
[(NSMutableArray *)values addObject:value];
|
||||||
|
}
|
||||||
copy = YES;
|
copy = YES;
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
return values;
|
return values;
|
||||||
} else {
|
|
||||||
// All other JSON types are supported by property lists
|
|
||||||
return json;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All other JSON types are supported by property lists
|
||||||
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSPropertyList)NSPropertyList:(id)json
|
+ (NSPropertyList)NSPropertyList:(id)json
|
||||||
|
|
|
@ -66,9 +66,7 @@ RCT_EXPORT_MODULE()
|
||||||
// We're swizzling here because it's poor form to override methods in a category,
|
// We're swizzling here because it's poor form to override methods in a category,
|
||||||
// however UIWindow doesn't actually implement motionEnded:withEvent:, so there's
|
// however UIWindow doesn't actually implement motionEnded:withEvent:, so there's
|
||||||
// no need to call the original implementation.
|
// no need to call the original implementation.
|
||||||
#if RCT_DEV
|
|
||||||
RCTSwapInstanceMethods([UIWindow class], @selector(motionEnded:withEvent:), @selector(RCT_motionEnded:withEvent:));
|
RCTSwapInstanceMethods([UIWindow class], @selector(motionEnded:withEvent:), @selector(RCT_motionEnded:withEvent:));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)init
|
- (instancetype)init
|
||||||
|
@ -121,8 +119,6 @@ RCT_EXPORT_MODULE()
|
||||||
|
|
||||||
- (void)updateSettings
|
- (void)updateSettings
|
||||||
{
|
{
|
||||||
_settings = [NSMutableDictionary dictionaryWithDictionary:[_defaults objectForKey:RCTDevMenuSettingsKey]];
|
|
||||||
|
|
||||||
__weak RCTDevMenu *weakSelf = self;
|
__weak RCTDevMenu *weakSelf = self;
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
RCTDevMenu *strongSelf = weakSelf;
|
RCTDevMenu *strongSelf = weakSelf;
|
||||||
|
@ -130,6 +126,8 @@ RCT_EXPORT_MODULE()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strongSelf->_settings = [NSMutableDictionary dictionaryWithDictionary:[strongSelf->_defaults objectForKey:RCTDevMenuSettingsKey]];
|
||||||
|
|
||||||
strongSelf.shakeToShow = [strongSelf->_settings[@"shakeToShow"] ?: @YES boolValue];
|
strongSelf.shakeToShow = [strongSelf->_settings[@"shakeToShow"] ?: @YES boolValue];
|
||||||
strongSelf.profilingEnabled = [strongSelf->_settings[@"profilingEnabled"] ?: @NO boolValue];
|
strongSelf.profilingEnabled = [strongSelf->_settings[@"profilingEnabled"] ?: @NO boolValue];
|
||||||
strongSelf.liveReloadEnabled = [strongSelf->_settings[@"liveReloadEnabled"] ?: @NO boolValue];
|
strongSelf.liveReloadEnabled = [strongSelf->_settings[@"liveReloadEnabled"] ?: @NO boolValue];
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
RCT_EXTERN NSString *RCTJSONStringify(id jsonObject, NSError **error);
|
RCT_EXTERN NSString *RCTJSONStringify(id jsonObject, NSError **error);
|
||||||
RCT_EXTERN id RCTJSONParse(NSString *jsonString, NSError **error);
|
RCT_EXTERN id RCTJSONParse(NSString *jsonString, NSError **error);
|
||||||
|
|
||||||
|
// Strip non JSON-safe values from an object graph
|
||||||
|
RCT_EXTERN id RCTJSONClean(id object);
|
||||||
|
|
||||||
// Get MD5 hash of a string (TODO: currently unused. Remove?)
|
// Get MD5 hash of a string (TODO: currently unused. Remove?)
|
||||||
RCT_EXTERN NSString *RCTMD5Hash(NSString *string);
|
RCT_EXTERN NSString *RCTMD5Hash(NSString *string);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
NSString *RCTJSONStringify(id jsonObject, NSError **error)
|
NSString *RCTJSONStringify(id jsonObject, NSError **error)
|
||||||
{
|
{
|
||||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonObject options:0 error:error];
|
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonObject options:(NSJSONWritingOptions)NSJSONReadingAllowFragments error:error];
|
||||||
return jsonData ? [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] : nil;
|
return jsonData ? [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] : nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,57 @@ id RCTJSONParse(NSString *jsonString, NSError **error)
|
||||||
return [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:error];
|
return [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:error];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
id RCTJSONClean(id object)
|
||||||
|
{
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
static NSSet *validLeafTypes;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
validLeafTypes = [[NSSet alloc] initWithArray:@[
|
||||||
|
[NSString class],
|
||||||
|
[NSMutableString class],
|
||||||
|
[NSNumber class],
|
||||||
|
[NSNull class],
|
||||||
|
]];
|
||||||
|
});
|
||||||
|
|
||||||
|
if ([validLeafTypes containsObject:[object classForCoder]]) {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([object isKindOfClass:[NSDictionary class]]) {
|
||||||
|
__block BOOL copy = NO;
|
||||||
|
NSMutableDictionary *values = [[NSMutableDictionary alloc] initWithCapacity:[object count]];
|
||||||
|
[object enumerateKeysAndObjectsUsingBlock:^(NSString *key, id item, BOOL *stop) {
|
||||||
|
id value = RCTJSONClean(item);
|
||||||
|
values[key] = value;
|
||||||
|
copy |= value != item;
|
||||||
|
}];
|
||||||
|
return copy ? values : object;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([object isKindOfClass:[NSArray class]]) {
|
||||||
|
__block BOOL copy = NO;
|
||||||
|
__block NSArray *values = object;
|
||||||
|
[object enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
|
||||||
|
id value = RCTJSONClean(item);
|
||||||
|
if (copy) {
|
||||||
|
[(NSMutableArray *)values addObject:value];
|
||||||
|
} else if (value != item) {
|
||||||
|
// Converted value is different, so we'll need to copy the array
|
||||||
|
values = [[NSMutableArray alloc] initWithCapacity:values.count];
|
||||||
|
for (NSInteger i = 0; i < idx; i++) {
|
||||||
|
[(NSMutableArray *)values addObject:object[i]];
|
||||||
|
}
|
||||||
|
[(NSMutableArray *)values addObject:value];
|
||||||
|
copy = YES;
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (id)kCFNull;
|
||||||
|
}
|
||||||
|
|
||||||
NSString *RCTMD5Hash(NSString *string)
|
NSString *RCTMD5Hash(NSString *string)
|
||||||
{
|
{
|
||||||
const char *str = [string UTF8String];
|
const char *str = [string UTF8String];
|
||||||
|
|
|
@ -45,6 +45,6 @@
|
||||||
@property (nonatomic, assign) BOOL automaticallyAdjustContentInsets;
|
@property (nonatomic, assign) BOOL automaticallyAdjustContentInsets;
|
||||||
@property (nonatomic, assign) NSTimeInterval scrollEventThrottle;
|
@property (nonatomic, assign) NSTimeInterval scrollEventThrottle;
|
||||||
@property (nonatomic, assign) BOOL centerContent;
|
@property (nonatomic, assign) BOOL centerContent;
|
||||||
@property (nonatomic, copy) NSArray *stickyHeaderIndices;
|
@property (nonatomic, copy) NSIndexSet *stickyHeaderIndices;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -28,8 +28,8 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
|
||||||
*/
|
*/
|
||||||
@interface RCTCustomScrollView : UIScrollView<UIGestureRecognizerDelegate>
|
@interface RCTCustomScrollView : UIScrollView<UIGestureRecognizerDelegate>
|
||||||
|
|
||||||
@property (nonatomic, copy, readwrite) NSArray *stickyHeaderIndices;
|
@property (nonatomic, copy) NSIndexSet *stickyHeaderIndices;
|
||||||
@property (nonatomic, readwrite, assign) BOOL centerContent;
|
@property (nonatomic, assign) BOOL centerContent;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -155,97 +155,72 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
|
||||||
[super setContentOffset:contentOffset];
|
[super setContentOffset:contentOffset];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setBounds:(CGRect)bounds
|
|
||||||
{
|
|
||||||
[super setBounds:bounds];
|
|
||||||
[self dockClosestSectionHeader];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dockClosestSectionHeader
|
- (void)dockClosestSectionHeader
|
||||||
{
|
{
|
||||||
UIView *contentView = [self contentView];
|
UIView *contentView = [self contentView];
|
||||||
if (_stickyHeaderIndices.count == 0 || !contentView) {
|
CGFloat scrollTop = self.bounds.origin.y + self.contentInset.top;
|
||||||
|
|
||||||
|
// Find the section headers that need to be docked
|
||||||
|
__block UIView *previousHeader = nil;
|
||||||
|
__block UIView *currentHeader = nil;
|
||||||
|
__block UIView *nextHeader = nil;
|
||||||
|
NSInteger subviewCount = contentView.reactSubviews.count;
|
||||||
|
[_stickyHeaderIndices enumerateIndexesWithOptions:0 usingBlock:^(NSUInteger idx, BOOL *stop) {
|
||||||
|
|
||||||
|
if (idx >= subviewCount) {
|
||||||
|
RCTLogError(@"Sticky header index %zd was outside the range {0, %zd}", idx, subviewCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIView *header = contentView.reactSubviews[idx];
|
||||||
|
|
||||||
|
// If nextHeader not yet found, search for docked headers
|
||||||
|
if (!nextHeader) {
|
||||||
|
CGFloat height = header.bounds.size.height;
|
||||||
|
CGFloat top = header.center.y - height * header.layer.anchorPoint.y;
|
||||||
|
if (top > scrollTop) {
|
||||||
|
nextHeader = header;
|
||||||
|
} else {
|
||||||
|
previousHeader = currentHeader;
|
||||||
|
currentHeader = header;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset transforms for header views
|
||||||
|
header.transform = CGAffineTransformIdentity;
|
||||||
|
header.layer.zPosition = ZINDEX_DEFAULT;
|
||||||
|
|
||||||
|
}];
|
||||||
|
|
||||||
|
// If no docked header, bail out
|
||||||
|
if (!currentHeader) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the section header that needs to be docked
|
// Adjust current header to hug the top of the screen
|
||||||
NSInteger firstIndexInView = [[_stickyHeaderIndices firstObject] integerValue] + 1;
|
CGFloat currentFrameHeight = currentHeader.bounds.size.height;
|
||||||
CGRect scrollBounds = self.bounds;
|
CGFloat currentFrameTop = currentHeader.center.y - currentFrameHeight * currentHeader.layer.anchorPoint.y;
|
||||||
scrollBounds.origin.x += self.contentInset.left;
|
CGFloat yOffset = scrollTop - currentFrameTop;
|
||||||
scrollBounds.origin.y += self.contentInset.top;
|
if (nextHeader) {
|
||||||
|
// The next header nudges the current header out of the way when it reaches
|
||||||
NSInteger i = 0;
|
// the top of the screen
|
||||||
for (UIView *subview in contentView.reactSubviews) {
|
CGFloat nextFrameHeight = nextHeader.bounds.size.height;
|
||||||
CGRect rowFrame = [RCTCustomScrollView _calculateUntransformedFrame:subview];
|
CGFloat nextFrameTop = nextHeader.center.y - nextFrameHeight * nextHeader.layer.anchorPoint.y;
|
||||||
if (CGRectIntersectsRect(scrollBounds, rowFrame)) {
|
CGFloat overlap = currentFrameHeight - (nextFrameTop - scrollTop);
|
||||||
firstIndexInView = i;
|
yOffset -= MAX(0, overlap);
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
NSInteger stickyHeaderii = 0;
|
currentHeader.transform = CGAffineTransformMakeTranslation(0, yOffset);
|
||||||
for (NSNumber *stickyHeaderI in _stickyHeaderIndices) {
|
currentHeader.layer.zPosition = ZINDEX_STICKY_HEADER;
|
||||||
if ([stickyHeaderI integerValue] > firstIndexInView) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
stickyHeaderii++;
|
|
||||||
}
|
|
||||||
stickyHeaderii = MAX(0, stickyHeaderii - 1);
|
|
||||||
|
|
||||||
// Set up transforms for the various section headers
|
|
||||||
NSInteger currentlyDockedIndex = [_stickyHeaderIndices[stickyHeaderii] integerValue];
|
|
||||||
NSInteger previouslyDockedIndex = stickyHeaderii > 0 ? [_stickyHeaderIndices[stickyHeaderii-1] integerValue] : -1;
|
|
||||||
NSInteger nextDockedIndex = (stickyHeaderii < _stickyHeaderIndices.count - 1) ?
|
|
||||||
[_stickyHeaderIndices[stickyHeaderii + 1] integerValue] : -1;
|
|
||||||
|
|
||||||
UIView *currentHeader = contentView.reactSubviews[currentlyDockedIndex];
|
|
||||||
UIView *previousHeader = previouslyDockedIndex >= 0 ? contentView.reactSubviews[previouslyDockedIndex] : nil;
|
|
||||||
CGRect curFrame = [RCTCustomScrollView _calculateUntransformedFrame:currentHeader];
|
|
||||||
|
|
||||||
if (previousHeader) {
|
if (previousHeader) {
|
||||||
// the previous header is offset to sit right above the currentlyDockedHeader's initial position
|
// The previous header sits right above the currentHeader's initial position
|
||||||
// (so it scrolls away nicely once the currentHeader locks into position)
|
// so it scrolls away nicely once the currentHeader has locked into place
|
||||||
CGRect previousFrame = [RCTCustomScrollView _calculateUntransformedFrame:previousHeader];
|
CGFloat previousFrameHeight = previousHeader.bounds.size.height;
|
||||||
CGFloat yOffset = curFrame.origin.y - previousFrame.origin.y - previousFrame.size.height;
|
CGFloat targetCenter = currentFrameTop - previousFrameHeight * (1.0 - previousHeader.layer.anchorPoint.y);
|
||||||
|
yOffset = targetCenter - previousHeader.center.y;
|
||||||
previousHeader.transform = CGAffineTransformMakeTranslation(0, yOffset);
|
previousHeader.transform = CGAffineTransformMakeTranslation(0, yOffset);
|
||||||
|
previousHeader.layer.zPosition = ZINDEX_STICKY_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIView *nextHeader = nextDockedIndex >= 0 ? contentView.reactSubviews[nextDockedIndex] : nil;
|
|
||||||
CGRect nextFrame = [RCTCustomScrollView _calculateUntransformedFrame:nextHeader];
|
|
||||||
|
|
||||||
if (curFrame.origin.y < scrollBounds.origin.y) {
|
|
||||||
// scrolled off (or being scrolled off) the top of the screen
|
|
||||||
CGFloat yOffset = 0;
|
|
||||||
if (nextHeader && nextFrame.origin.y < scrollBounds.origin.y + curFrame.size.height) {
|
|
||||||
// next frame is bumping me off if scrolling down (or i'm bumping the next one off if scrolling up)
|
|
||||||
yOffset = nextFrame.origin.y - curFrame.origin.y - curFrame.size.height;
|
|
||||||
} else {
|
|
||||||
// standard sticky header position
|
|
||||||
yOffset = scrollBounds.origin.y - curFrame.origin.y;
|
|
||||||
}
|
|
||||||
currentHeader.transform = CGAffineTransformMakeTranslation(0, yOffset);
|
|
||||||
currentHeader.layer.zPosition = ZINDEX_STICKY_HEADER;
|
|
||||||
} else {
|
|
||||||
// i'm the current header but in the viewport, so just scroll in normal position
|
|
||||||
currentHeader.transform = CGAffineTransformIdentity;
|
|
||||||
currentHeader.layer.zPosition = ZINDEX_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// in our setup, 'next header' will always just scroll with the page
|
|
||||||
if (nextHeader) {
|
|
||||||
nextHeader.transform = CGAffineTransformIdentity;
|
|
||||||
nextHeader.layer.zPosition = ZINDEX_DEFAULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (CGRect)_calculateUntransformedFrame:(UIView *)view
|
|
||||||
{
|
|
||||||
CGRect frame = CGRectNull;
|
|
||||||
if (view) {
|
|
||||||
frame.size = view.bounds.size;
|
|
||||||
frame.origin = CGPointMake(view.layer.position.x - view.bounds.size.width * view.layer.anchorPoint.x, view.layer.position.y - view.bounds.size.height * view.layer.anchorPoint.y);
|
|
||||||
}
|
|
||||||
return frame;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -312,7 +287,7 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
|
||||||
_scrollView.centerContent = centerContent;
|
_scrollView.centerContent = centerContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setStickyHeaderIndices:(NSArray *)headerIndices
|
- (void)setStickyHeaderIndices:(NSIndexSet *)headerIndices
|
||||||
{
|
{
|
||||||
RCTAssert(_scrollView.contentSize.width <= self.frame.size.width,
|
RCTAssert(_scrollView.contentSize.width <= self.frame.size.width,
|
||||||
@"sticky headers are not supported with horizontal scrolled views");
|
@"sticky headers are not supported with horizontal scrolled views");
|
||||||
|
@ -340,14 +315,8 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
|
||||||
|
|
||||||
- (void)setContentInset:(UIEdgeInsets)contentInset
|
- (void)setContentInset:(UIEdgeInsets)contentInset
|
||||||
{
|
{
|
||||||
CGPoint contentOffset = _scrollView.contentOffset;
|
|
||||||
|
|
||||||
_contentInset = contentInset;
|
_contentInset = contentInset;
|
||||||
[RCTView autoAdjustInsetsForView:self
|
[self setNeedsLayout];
|
||||||
withScrollView:_scrollView
|
|
||||||
updateOffset:NO];
|
|
||||||
|
|
||||||
_scrollView.contentOffset = contentOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)scrollToOffset:(CGPoint)offset
|
- (void)scrollToOffset:(CGPoint)offset
|
||||||
|
@ -390,6 +359,7 @@ RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, RCTScrollEventTypeMove)
|
||||||
|
|
||||||
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
||||||
{
|
{
|
||||||
|
[_scrollView dockClosestSectionHeader];
|
||||||
[self updateClippedSubviews];
|
[self updateClippedSubviews];
|
||||||
|
|
||||||
NSTimeInterval now = CACurrentMediaTime();
|
NSTimeInterval now = CACurrentMediaTime();
|
||||||
|
|
|
@ -41,7 +41,7 @@ RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(scrollsToTop, BOOL)
|
RCT_EXPORT_VIEW_PROPERTY(scrollsToTop, BOOL)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(showsHorizontalScrollIndicator, BOOL)
|
RCT_EXPORT_VIEW_PROPERTY(showsHorizontalScrollIndicator, BOOL)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(showsVerticalScrollIndicator, BOOL)
|
RCT_EXPORT_VIEW_PROPERTY(showsVerticalScrollIndicator, BOOL)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(stickyHeaderIndices, NSNumberArray)
|
RCT_EXPORT_VIEW_PROPERTY(stickyHeaderIndices, NSIndexSet)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(scrollEventThrottle, NSTimeInterval)
|
RCT_EXPORT_VIEW_PROPERTY(scrollEventThrottle, NSTimeInterval)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(zoomScale, CGFloat)
|
RCT_EXPORT_VIEW_PROPERTY(zoomScale, CGFloat)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(contentInset, UIEdgeInsets)
|
RCT_EXPORT_VIEW_PROPERTY(contentInset, UIEdgeInsets)
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
"chalk": "^1.0.0",
|
"chalk": "^1.0.0",
|
||||||
"connect": "2.8.3",
|
"connect": "2.8.3",
|
||||||
"debug": "~2.1.0",
|
"debug": "~2.1.0",
|
||||||
|
"graceful-fs": "^3.0.6",
|
||||||
"image-size": "0.3.5",
|
"image-size": "0.3.5",
|
||||||
"joi": "~5.1.0",
|
"joi": "~5.1.0",
|
||||||
"jstransform": "10.1.0",
|
"jstransform": "10.1.0",
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
on run argv
|
on run argv
|
||||||
set theURL to item 1 of argv
|
set theURL to item 1 of argv
|
||||||
|
|
||||||
tell application "Google Chrome"
|
tell application "Chrome"
|
||||||
activate
|
activate
|
||||||
|
|
||||||
if (count every window) = 0 then
|
if (count every window) = 0 then
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
useGracefulFs();
|
||||||
|
|
||||||
var Activity = require('./src/Activity');
|
var Activity = require('./src/Activity');
|
||||||
var Server = require('./src/Server');
|
var Server = require('./src/Server');
|
||||||
|
|
||||||
|
@ -45,3 +47,16 @@ exports.getDependencies = function(options, main) {
|
||||||
return r.dependencies;
|
return r.dependencies;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function useGracefulFs() {
|
||||||
|
var fs = require('fs');
|
||||||
|
var gracefulFs = require('graceful-fs');
|
||||||
|
|
||||||
|
// A bit sneaky but it's not straightforward to update all the
|
||||||
|
// modules we depend on.
|
||||||
|
Object.keys(fs).forEach(function(method) {
|
||||||
|
if (typeof fs[method] === 'function' && gracefulFs[method]) {
|
||||||
|
fs[method] = gracefulFs[method];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue