mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-24 04:16:00 +08:00
Updates from Tue 5 May
This commit is contained in:
@@ -17,7 +17,6 @@
|
||||
@interface RCTConvert (ART)
|
||||
|
||||
+ (CGPathRef)CGPath:(id)json;
|
||||
+ (CTFontRef)CTFont:(id)json;
|
||||
+ (CTTextAlignment)CTTextAlignment:(id)json;
|
||||
+ (ARTTextFrame)ARTTextFrame:(id)json;
|
||||
+ (ARTCGFloatArray)ARTCGFloatArray:(id)json;
|
||||
|
||||
@@ -64,18 +64,6 @@
|
||||
return (CGPathRef)CFAutorelease(path);
|
||||
}
|
||||
|
||||
+ (CTFontRef)CTFont:(id)json
|
||||
{
|
||||
NSDictionary *dict = [self NSDictionary:json];
|
||||
if (!dict) {
|
||||
return nil;
|
||||
}
|
||||
CTFontDescriptorRef fontDescriptor = CTFontDescriptorCreateWithAttributes((__bridge CFDictionaryRef)dict);
|
||||
CTFontRef font = CTFontCreateWithFontDescriptor(fontDescriptor, 0.0, NULL);
|
||||
CFRelease(fontDescriptor);
|
||||
return (CTFontRef)CFAutorelease(font);
|
||||
}
|
||||
|
||||
RCT_ENUM_CONVERTER(CTTextAlignment, (@{
|
||||
@"auto": @(kCTTextAlignmentNatural),
|
||||
@"left": @(kCTTextAlignmentLeft),
|
||||
@@ -98,7 +86,8 @@ RCT_ENUM_CONVERTER(CTTextAlignment, (@{
|
||||
return frame;
|
||||
}
|
||||
|
||||
CTFontRef font = [self CTFont:dict[@"font"]];
|
||||
NSDictionary *fontDict = dict[@"font"];
|
||||
CTFontRef font = (__bridge CTFontRef)[self UIFont:nil withFamily:fontDict[@"fontFamily"] size:fontDict[@"fontSize"] weight:fontDict[@"fontWeight"] style:fontDict[@"fontStyle"]];
|
||||
if (!font) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
@@ -50,18 +50,11 @@ function fontAndLinesDiffer(a, b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var aTraits = a.font.NSCTFontTraitsAttribute;
|
||||
var bTraits = b.font.NSCTFontTraitsAttribute;
|
||||
|
||||
if (
|
||||
a.font.fontFamily !== b.font.fontFamily ||
|
||||
a.font.fontSize !== b.font.fontSize ||
|
||||
a.font.fontWeight !== b.font.fontWeight ||
|
||||
a.font.fontStyle !== b.font.fontStyle ||
|
||||
// TODO(6364240): remove iOS-specific attrs
|
||||
a.font.NSFontFamilyAttribute !== b.font.NSFontFamilyAttribute ||
|
||||
a.font.NSFontSizeAttribute !== b.font.NSFontSizeAttribute ||
|
||||
aTraits.NSCTFontSymbolicTrait !== bTraits.NSCTFontSymbolicTrait
|
||||
a.font.fontStyle !== b.font.fontStyle
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@@ -418,14 +411,6 @@ var Shape = React.createClass({
|
||||
|
||||
var cachedFontObjectsFromString = {};
|
||||
|
||||
function extractFontTraits(isBold, isItalic) {
|
||||
var italic = isItalic ? 1 : 0;
|
||||
var bold = isBold ? 2 : 0;
|
||||
return {
|
||||
NSCTFontSymbolicTrait: italic | bold
|
||||
};
|
||||
}
|
||||
|
||||
var fontFamilyPrefix = /^[\s"']*/;
|
||||
var fontFamilySuffix = /[\s"']*$/;
|
||||
|
||||
@@ -456,10 +441,6 @@ function parseFontString(font) {
|
||||
fontSize: fontSize,
|
||||
fontWeight: isBold ? 'bold' : 'normal',
|
||||
fontStyle: isItalic ? 'italic' : 'normal',
|
||||
// TODO(6364240): remove iOS-specific attrs
|
||||
NSFontFamilyAttribute: fontFamily,
|
||||
NSFontSizeAttribute: fontSize,
|
||||
NSCTFontTraitsAttribute: extractFontTraits(isBold, isItalic)
|
||||
};
|
||||
return cachedFontObjectsFromString[font];
|
||||
}
|
||||
@@ -479,13 +460,6 @@ function extractFont(font) {
|
||||
fontSize: fontSize,
|
||||
fontWeight: font.fontWeight,
|
||||
fontStyle: font.fontStyle,
|
||||
// TODO(6364240): remove iOS-specific attrs
|
||||
NSFontFamilyAttribute: fontFamily,
|
||||
NSFontSizeAttribute: fontSize,
|
||||
NSCTFontTraitsAttribute: extractFontTraits(
|
||||
font.fontWeight === 'bold',
|
||||
font.fontStyle === 'italic'
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -231,8 +231,10 @@ module.exports = {
|
||||
|
||||
var tickCount = Math.round(duration * ticksPerSecond / 1000);
|
||||
var samples = [];
|
||||
for (var i = 0; i <= tickCount; i++) {
|
||||
samples.push(easing.call(defaults, i / tickCount));
|
||||
if (tickCount > 0) {
|
||||
for (var i = 0; i <= tickCount; i++) {
|
||||
samples.push(easing.call(defaults, i / tickCount));
|
||||
}
|
||||
}
|
||||
|
||||
return samples;
|
||||
|
||||
@@ -114,7 +114,7 @@ RCT_EXPORT_METHOD(startAnimation:(NSNumber *)reactTag
|
||||
animationTag:(NSNumber *)animationTag
|
||||
duration:(NSTimeInterval)duration
|
||||
delay:(NSTimeInterval)delay
|
||||
easingSample:(NSArray *)easingSample
|
||||
easingSample:(NSNumberArray *)easingSample
|
||||
properties:(NSDictionary *)properties
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
|
||||
@@ -355,7 +355,7 @@ var ScrollResponderMixin = {
|
||||
|
||||
/**
|
||||
* A helper function to zoom to a specific rect in the scrollview.
|
||||
* @param {object} rect Should have shape {x, y, w, h}
|
||||
* @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);
|
||||
|
||||
@@ -211,11 +211,19 @@ var ScrollView = React.createClass({
|
||||
},
|
||||
|
||||
scrollTo: function(destY?: number, destX?: number) {
|
||||
RCTUIManager.scrollTo(
|
||||
this.getNodeHandle(),
|
||||
destX || 0,
|
||||
destY || 0
|
||||
);
|
||||
if (Platform.OS === 'android') {
|
||||
RCTUIManager.dispatchViewManagerCommand(
|
||||
this.getNodeHandle(),
|
||||
RCTUIManager.RCTScrollView.Commands.scrollTo,
|
||||
[destX || 0, destY || 0]
|
||||
);
|
||||
} else {
|
||||
RCTUIManager.scrollTo(
|
||||
this.getNodeHandle(),
|
||||
destX || 0,
|
||||
destY || 0
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
scrollWithoutAnimationTo: function(destY?: number, destX?: number) {
|
||||
@@ -364,7 +372,7 @@ var validAttributes = {
|
||||
if (Platform.OS === 'android') {
|
||||
var AndroidScrollView = createReactIOSNativeComponentClass({
|
||||
validAttributes: validAttributes,
|
||||
uiViewClassName: 'AndroidScrollView',
|
||||
uiViewClassName: 'RCTScrollView',
|
||||
});
|
||||
var AndroidHorizontalScrollView = createReactIOSNativeComponentClass({
|
||||
validAttributes: validAttributes,
|
||||
|
||||
@@ -582,7 +582,7 @@ var TextInput = React.createClass({
|
||||
var counter = event.nativeEvent.eventCounter;
|
||||
if (counter > this.state.mostRecentEventCounter) {
|
||||
this.setState({mostRecentEventCounter: counter});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -11,14 +11,13 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var React = require('React');
|
||||
var POPAnimation = require('POPAnimation');
|
||||
var AnimationExperimental = require('AnimationExperimental');
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var POPAnimation = require('POPAnimation');
|
||||
var React = require('React');
|
||||
var Touchable = require('Touchable');
|
||||
|
||||
var merge = require('merge');
|
||||
var copyProperties = require('copyProperties');
|
||||
var onlyChild = require('onlyChild');
|
||||
|
||||
type State = {
|
||||
@@ -123,9 +122,8 @@ var TouchableBounce = React.createClass({
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// Note(vjeux): use cloneWithProps once React has been upgraded
|
||||
var child = onlyChild(this.props.children);
|
||||
copyProperties(child.props, {
|
||||
return React.cloneElement(child, {
|
||||
accessible: true,
|
||||
testID: this.props.testID,
|
||||
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,
|
||||
@@ -135,7 +133,6 @@ var TouchableBounce = React.createClass({
|
||||
onResponderRelease: this.touchableHandleResponderRelease,
|
||||
onResponderTerminate: this.touchableHandleResponderTerminate
|
||||
});
|
||||
return child;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ var ViewStylePropTypes = {
|
||||
overflow: ReactPropTypes.oneOf(['visible', 'hidden']),
|
||||
shadowColor: ReactPropTypes.string,
|
||||
shadowOffset: ReactPropTypes.shape(
|
||||
{h: ReactPropTypes.number, w: ReactPropTypes.number}
|
||||
{width: ReactPropTypes.number, height: ReactPropTypes.number}
|
||||
),
|
||||
shadowOpacity: ReactPropTypes.number,
|
||||
shadowRadius: ReactPropTypes.number,
|
||||
|
||||
@@ -109,15 +109,27 @@ var WebView = React.createClass({
|
||||
},
|
||||
|
||||
goForward: function() {
|
||||
RCTUIManager.webViewGoForward(this.getWebWiewHandle());
|
||||
RCTUIManager.dispatchViewManagerCommand(
|
||||
this.getWebWiewHandle(),
|
||||
RCTUIManager.RCTWebView.Commands.goForward,
|
||||
null
|
||||
);
|
||||
},
|
||||
|
||||
goBack: function() {
|
||||
RCTUIManager.webViewGoBack(this.getWebWiewHandle());
|
||||
RCTUIManager.dispatchViewManagerCommand(
|
||||
this.getWebWiewHandle(),
|
||||
RCTUIManager.RCTWebView.Commands.goBack,
|
||||
null
|
||||
);
|
||||
},
|
||||
|
||||
reload: function() {
|
||||
RCTUIManager.webViewReload(this.getWebWiewHandle());
|
||||
RCTUIManager.dispatchViewManagerCommand(
|
||||
this.getWebWiewHandle(),
|
||||
RCTUIManager.RCTWebView.Commands.reload,
|
||||
null
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
var AnimationsDebugModule = require('NativeModules').AnimationsDebugModule;
|
||||
var BackAndroid = require('BackAndroid');
|
||||
var Dimensions = require('Dimensions');
|
||||
var InteractionMixin = require('InteractionMixin');
|
||||
var NavigatorBreadcrumbNavigationBar = require('NavigatorBreadcrumbNavigationBar');
|
||||
var NavigatorInterceptor = require('NavigatorInterceptor');
|
||||
@@ -43,8 +44,9 @@ var Subscribable = require('Subscribable');
|
||||
var TimerMixin = require('react-timer-mixin');
|
||||
var View = require('View');
|
||||
|
||||
var getNavigatorContext = require('getNavigatorContext');
|
||||
var clamp = require('clamp');
|
||||
var flattenStyle = require('flattenStyle');
|
||||
var getNavigatorContext = require('getNavigatorContext');
|
||||
var invariant = require('invariant');
|
||||
var keyMirror = require('keyMirror');
|
||||
var merge = require('merge');
|
||||
@@ -52,7 +54,17 @@ var rebound = require('rebound');
|
||||
|
||||
var PropTypes = React.PropTypes;
|
||||
|
||||
var OFF_SCREEN = {style: {opacity: 0}};
|
||||
// TODO: this is not ideal because there is no guarantee that the navigator
|
||||
// is full screen, hwoever we don't have a good way to measure the actual
|
||||
// size of the navigator right now, so this is the next best thing.
|
||||
var SCREEN_WIDTH = Dimensions.get('window').width;
|
||||
var SCREEN_HEIGHT = Dimensions.get('window').height;
|
||||
var SCENE_DISABLED_NATIVE_PROPS = {
|
||||
style: {
|
||||
left: SCREEN_WIDTH,
|
||||
opacity: 0,
|
||||
},
|
||||
};
|
||||
|
||||
var __uid = 0;
|
||||
function getuid() {
|
||||
@@ -72,7 +84,7 @@ var styles = StyleSheet.create({
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
},
|
||||
currentScene: {
|
||||
baseScene: {
|
||||
position: 'absolute',
|
||||
overflow: 'hidden',
|
||||
left: 0,
|
||||
@@ -80,11 +92,8 @@ var styles = StyleSheet.create({
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
},
|
||||
futureScene: {
|
||||
overflow: 'hidden',
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
opacity: 0,
|
||||
disabledScene: {
|
||||
left: SCREEN_WIDTH,
|
||||
},
|
||||
transitioner: {
|
||||
flex: 1,
|
||||
@@ -231,16 +240,13 @@ var Navigator = React.createClass({
|
||||
initialRouteStack: PropTypes.arrayOf(PropTypes.object),
|
||||
|
||||
/**
|
||||
* Will emit the target route upon mounting and before each nav transition,
|
||||
* overriding the handler in this.props.navigator. This overrides the onDidFocus
|
||||
* handler that would be found in this.props.navigator
|
||||
* Will emit the target route upon mounting and before each nav transition
|
||||
*/
|
||||
onWillFocus: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Will be called with the new route of each scene after the transition is
|
||||
* complete or after the initial mounting. This overrides the onDidFocus
|
||||
* handler that would be found in this.props.navigator
|
||||
* complete or after the initial mounting
|
||||
*/
|
||||
onDidFocus: PropTypes.func,
|
||||
|
||||
@@ -390,12 +396,12 @@ var Navigator = React.createClass({
|
||||
return this._handleRequest.apply(null, arguments);
|
||||
},
|
||||
|
||||
requestPop: function() {
|
||||
return this.request('pop');
|
||||
requestPop: function(popToBeforeRoute) {
|
||||
return this.request('pop', popToBeforeRoute);
|
||||
},
|
||||
|
||||
requestPopTo: function(route) {
|
||||
return this.request('pop', route);
|
||||
return this.request('popTo', route);
|
||||
},
|
||||
|
||||
_handleRequest: function(action, arg1, arg2) {
|
||||
@@ -406,6 +412,8 @@ var Navigator = React.createClass({
|
||||
switch (action) {
|
||||
case 'pop':
|
||||
return this._handlePop(arg1);
|
||||
case 'popTo':
|
||||
return this._handlePopTo(arg1);
|
||||
case 'push':
|
||||
return this._handlePush(arg1);
|
||||
default:
|
||||
@@ -414,11 +422,31 @@ var Navigator = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
_handlePop: function(route) {
|
||||
if (route) {
|
||||
var hasRoute = this.state.routeStack.indexOf(route) !== -1;
|
||||
_handlePop: function(popToBeforeRoute) {
|
||||
if (popToBeforeRoute) {
|
||||
var popToBeforeRouteIndex = this.state.routeStack.indexOf(popToBeforeRoute);
|
||||
if (popToBeforeRouteIndex === -1) {
|
||||
return false;
|
||||
}
|
||||
invariant(
|
||||
popToBeforeRouteIndex <= this.state.presentedIndex,
|
||||
'Cannot pop past a route that is forward in the navigator'
|
||||
);
|
||||
this._popN(this.state.presentedIndex - popToBeforeRouteIndex + 1);
|
||||
return true;
|
||||
}
|
||||
if (this.state.presentedIndex === 0) {
|
||||
return false;
|
||||
}
|
||||
this.pop();
|
||||
return true;
|
||||
},
|
||||
|
||||
_handlePopTo: function(destRoute) {
|
||||
if (destRoute) {
|
||||
var hasRoute = this.state.routeStack.indexOf(destRoute) !== -1;
|
||||
if (hasRoute) {
|
||||
this.popToRoute(route);
|
||||
this.popToRoute(destRoute);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -552,10 +580,12 @@ var Navigator = React.createClass({
|
||||
},
|
||||
|
||||
/**
|
||||
* This happens at the end of a transition started by transitionTo
|
||||
* 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) {
|
||||
// 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) {
|
||||
this.state.pendingGestureProgress = null;
|
||||
}
|
||||
@@ -580,11 +610,16 @@ var Navigator = React.createClass({
|
||||
this._interactionHandle = null;
|
||||
}
|
||||
if (this.state.pendingGestureProgress) {
|
||||
// A transition completed, but there is already another gesture happening.
|
||||
// Enable the scene and set the spring to catch up with the new gesture
|
||||
var gestureToIndex = this.state.presentedIndex + this._deltaForGestureAction(this.state.activeGesture);
|
||||
this._enableScene(gestureToIndex);
|
||||
this.spring.setEndValue(this.state.pendingGestureProgress);
|
||||
return;
|
||||
}
|
||||
if (this.state.transitionQueue.length) {
|
||||
var queuedTransition = this.state.transitionQueue.shift();
|
||||
this._enableScene(queuedTransition.destIndex);
|
||||
this._transitionTo(
|
||||
queuedTransition.destIndex,
|
||||
queuedTransition.velocity,
|
||||
@@ -601,7 +636,8 @@ var Navigator = React.createClass({
|
||||
this._lastDidFocus = route;
|
||||
if (this.props.onDidFocus) {
|
||||
this.props.onDidFocus(route);
|
||||
} else if (this.parentNavigator && this.parentNavigator.onDidFocus) {
|
||||
}
|
||||
if (this.parentNavigator && this.parentNavigator.onDidFocus) {
|
||||
this.parentNavigator.onDidFocus(route);
|
||||
}
|
||||
},
|
||||
@@ -617,27 +653,51 @@ var Navigator = React.createClass({
|
||||
}
|
||||
if (this.props.onWillFocus) {
|
||||
this.props.onWillFocus(route);
|
||||
} else if (this.parentNavigator && this.parentNavigator.onWillFocus) {
|
||||
}
|
||||
if (this.parentNavigator && this.parentNavigator.onWillFocus) {
|
||||
this.parentNavigator.onWillFocus(route);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Does not delete the scenes - merely hides them.
|
||||
* Hides scenes that we are not currently on or transitioning from
|
||||
*/
|
||||
_hideScenes: function() {
|
||||
for (var i = 0; i < this.state.routeStack.length; i++) {
|
||||
// This gets called when we detach a gesture, so there will not be a
|
||||
// current gesture, but there might be a transition in progress
|
||||
if (i === this.state.presentedIndex || i === this.state.transitionFromIndex) {
|
||||
continue;
|
||||
}
|
||||
var sceneRef = 'scene_' + i;
|
||||
this.refs[sceneRef] &&
|
||||
this.refs['scene_' + i].setNativeProps(OFF_SCREEN);
|
||||
this._disableScene(i);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Push a scene off the screen, so that opacity:0 scenes will not block touches sent to the presented scenes
|
||||
*/
|
||||
_disableScene: function(sceneIndex) {
|
||||
this.refs['scene_' + sceneIndex] &&
|
||||
this.refs['scene_' + sceneIndex].setNativeProps(SCENE_DISABLED_NATIVE_PROPS);
|
||||
},
|
||||
|
||||
/**
|
||||
* Put the scene back into the state as defined by props.sceneStyle, so transitions can happen normally
|
||||
*/
|
||||
_enableScene: function(sceneIndex) {
|
||||
// First, determine what the defined styles are for scenes in this navigator
|
||||
var sceneStyle = flattenStyle(this.props.sceneStyle);
|
||||
// Then restore the left value for this scene
|
||||
var enabledSceneNativeProps = {
|
||||
left: sceneStyle.left,
|
||||
};
|
||||
if (sceneIndex !== this.state.transitionFromIndex) {
|
||||
// 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
|
||||
enabledSceneNativeProps.opacity = 0;
|
||||
}
|
||||
this.refs['scene_' + sceneIndex] &&
|
||||
this.refs['scene_' + sceneIndex].setNativeProps(enabledSceneNativeProps);
|
||||
},
|
||||
|
||||
_onAnimationStart: function() {
|
||||
var fromIndex = this.state.presentedIndex;
|
||||
var toIndex = this.state.presentedIndex;
|
||||
@@ -648,7 +708,6 @@ var Navigator = React.createClass({
|
||||
}
|
||||
this._setRenderSceneToHarwareTextureAndroid(fromIndex, true);
|
||||
this._setRenderSceneToHarwareTextureAndroid(toIndex, true);
|
||||
|
||||
var navBar = this._navBar;
|
||||
if (navBar && navBar.onAnimationStart) {
|
||||
navBar.onAnimationStart(fromIndex, toIndex);
|
||||
@@ -780,6 +839,8 @@ var Navigator = React.createClass({
|
||||
|
||||
_attachGesture: function(gestureId) {
|
||||
this.state.activeGesture = gestureId;
|
||||
var gesturingToIndex = this.state.presentedIndex + this._deltaForGestureAction(this.state.activeGesture);
|
||||
this._enableScene(gesturingToIndex);
|
||||
},
|
||||
|
||||
_detachGesture: function() {
|
||||
@@ -810,6 +871,7 @@ var Navigator = React.createClass({
|
||||
(gesture.fullDistance - gestureDetectMovement);
|
||||
if (nextProgress < 0 && gesture.isDetachable) {
|
||||
this._detachGesture();
|
||||
this.spring.setCurrentValue(0);
|
||||
}
|
||||
if (this._doesGestureOverswipe(this.state.activeGesture)) {
|
||||
var frictionConstant = gesture.overswipe.frictionConstant;
|
||||
@@ -847,13 +909,17 @@ var Navigator = React.createClass({
|
||||
var travelDist = isTravelVertical ? gestureState.dy : gestureState.dx;
|
||||
var oppositeAxisTravelDist =
|
||||
isTravelVertical ? gestureState.dx : gestureState.dy;
|
||||
var edgeHitWidth = gesture.edgeHitWidth;
|
||||
if (isTravelInverted) {
|
||||
currentLoc = -currentLoc;
|
||||
travelDist = -travelDist;
|
||||
oppositeAxisTravelDist = -oppositeAxisTravelDist;
|
||||
edgeHitWidth = isTravelVertical ?
|
||||
-(SCREEN_HEIGHT - edgeHitWidth) :
|
||||
-(SCREEN_WIDTH - edgeHitWidth);
|
||||
}
|
||||
var moveStartedInRegion = gesture.edgeHitWidth == null ||
|
||||
currentLoc < gesture.edgeHitWidth;
|
||||
currentLoc < edgeHitWidth;
|
||||
var moveTravelledFarEnough =
|
||||
travelDist >= gesture.gestureDetectMovement &&
|
||||
travelDist > oppositeAxisTravelDist * gesture.directionRatio;
|
||||
@@ -924,6 +990,7 @@ var Navigator = React.createClass({
|
||||
_jumpN: function(n) {
|
||||
var destIndex = this._getDestIndexWithinBounds(n);
|
||||
var requestTransitionAndResetUpdatingRange = () => {
|
||||
this._enableScene(destIndex);
|
||||
this._transitionTo(destIndex);
|
||||
this._resetUpdatingRange();
|
||||
};
|
||||
@@ -957,12 +1024,14 @@ var Navigator = React.createClass({
|
||||
var activeIDStack = this.state.idStack.slice(0, activeLength);
|
||||
var activeAnimationConfigStack = this.state.sceneConfigStack.slice(0, activeLength);
|
||||
var nextStack = activeStack.concat([route]);
|
||||
var destIndex = nextStack.length - 1;
|
||||
var nextIDStack = activeIDStack.concat([getuid()]);
|
||||
var nextAnimationConfigStack = activeAnimationConfigStack.concat([
|
||||
this.props.configureScene(route),
|
||||
]);
|
||||
var requestTransitionAndResetUpdatingRange = () => {
|
||||
this._transitionTo(nextStack.length - 1);
|
||||
this._enableScene(destIndex);
|
||||
this._transitionTo(destIndex);
|
||||
this._resetUpdatingRange();
|
||||
};
|
||||
this.setState({
|
||||
@@ -983,6 +1052,7 @@ var Navigator = React.createClass({
|
||||
'Cannot pop below zero'
|
||||
);
|
||||
var popIndex = this.state.presentedIndex - n;
|
||||
this._enableScene(popIndex);
|
||||
this._transitionTo(
|
||||
popIndex,
|
||||
null, // default velocity
|
||||
@@ -1062,7 +1132,7 @@ var Navigator = React.createClass({
|
||||
indexOfRoute !== -1,
|
||||
'Calling pop to route for a route that doesn\'t exist!'
|
||||
);
|
||||
return this.state.routeStack.length - indexOfRoute - 1;
|
||||
return this.state.presentedIndex - indexOfRoute;
|
||||
},
|
||||
|
||||
popToRoute: function(route) {
|
||||
@@ -1190,13 +1260,18 @@ var Navigator = React.createClass({
|
||||
route,
|
||||
sceneNavigatorContext
|
||||
);
|
||||
var initialSceneStyle = i === this.state.presentedIndex ?
|
||||
styles.currentScene : styles.futureScene;
|
||||
var disabledSceneStyle = null;
|
||||
if (i !== this.state.presentedIndex) {
|
||||
disabledSceneStyle = styles.disabledScene;
|
||||
}
|
||||
return (
|
||||
<View
|
||||
key={this.state.idStack[i]}
|
||||
ref={'scene_' + i}
|
||||
style={[initialSceneStyle, this.props.sceneStyle]}>
|
||||
onStartShouldSetResponderCapture={() => {
|
||||
return i !== this.state.presentedIndex;
|
||||
}}
|
||||
style={[styles.baseScene, this.props.sceneStyle, disabledSceneStyle]}>
|
||||
{React.cloneElement(child, {
|
||||
ref: this._handleItemRef.bind(null, this.state.idStack[i]),
|
||||
})}
|
||||
|
||||
@@ -78,9 +78,11 @@ var NavigatorInterceptor = React.createClass({
|
||||
}
|
||||
switch (action) {
|
||||
case 'pop':
|
||||
return this.props.onPopRequest && this.props.onPopRequest(action, arg1, arg2);
|
||||
return this.props.onPopRequest && this.props.onPopRequest(arg1, arg2);
|
||||
case 'popTo':
|
||||
return this.props.onPopToRequest && this.props.onPopToRequest(arg1, arg2);
|
||||
case 'push':
|
||||
return this.props.onPushRequest && this.props.onPushRequest(action, arg1, arg2);
|
||||
return this.props.onPushRequest && this.props.onPushRequest(arg1, arg2);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ typedef NS_ENUM(NSInteger, RCTPositionErrorCode) {
|
||||
#define RCT_DEFAULT_LOCATION_ACCURACY kCLLocationAccuracyHundredMeters
|
||||
|
||||
typedef struct {
|
||||
NSTimeInterval timeout;
|
||||
NSTimeInterval maximumAge;
|
||||
CLLocationAccuracy accuracy;
|
||||
double timeout;
|
||||
double maximumAge;
|
||||
double accuracy;
|
||||
} RCTLocationOptions;
|
||||
|
||||
@implementation RCTConvert (RCTLocationOptions)
|
||||
|
||||
@@ -29,19 +29,4 @@ var ImageStylePropTypes = {
|
||||
opacity: ReactPropTypes.number,
|
||||
};
|
||||
|
||||
// Image doesn't support padding correctly (#4841912)
|
||||
var unsupportedProps = Object.keys({
|
||||
padding: null,
|
||||
paddingTop: null,
|
||||
paddingLeft: null,
|
||||
paddingRight: null,
|
||||
paddingBottom: null,
|
||||
paddingVertical: null,
|
||||
paddingHorizontal: null,
|
||||
});
|
||||
|
||||
for (var i = 0; i < unsupportedProps.length; i++) {
|
||||
delete ImageStylePropTypes[unsupportedProps[i]];
|
||||
}
|
||||
|
||||
module.exports = ImageStylePropTypes;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var Platform = require('Platform');
|
||||
var RCTExceptionsManager = require('NativeModules').ExceptionsManager;
|
||||
|
||||
var loadSourceMap = require('loadSourceMap');
|
||||
|
||||
@@ -79,6 +79,16 @@ function setupRedBoxErrorHandler() {
|
||||
ErrorUtils.setGlobalHandler(handleErrorWithRedBox);
|
||||
}
|
||||
|
||||
function setupRedBoxConsoleErrorHandler() {
|
||||
// ExceptionsManager transitively requires Promise so we install it after
|
||||
var ExceptionsManager = require('ExceptionsManager');
|
||||
var Platform = require('Platform');
|
||||
// TODO (#6925182): Enable console.error redbox on Android
|
||||
if (__DEV__ && Platform.OS === 'ios') {
|
||||
ExceptionsManager.installConsoleErrorReporter();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a set of window environment wrappers that ensure that the
|
||||
* BatchedBridge is flushed after each tick. In both the case of the
|
||||
@@ -139,4 +149,5 @@ setupTimers();
|
||||
setupAlert();
|
||||
setupPromise();
|
||||
setupXHR();
|
||||
setupRedBoxConsoleErrorHandler();
|
||||
setupGeolocation();
|
||||
|
||||
@@ -143,10 +143,7 @@
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
@@ -182,6 +179,7 @@
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "";
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
@@ -199,6 +197,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_STATIC_ANALYZER_MODE = deep;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
|
||||
@interface RCTPushNotificationManager : NSObject <RCTBridgeModule>
|
||||
|
||||
- (instancetype)initWithInitialNotification:(NSDictionary *)initialNotification NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
+ (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings;
|
||||
+ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification;
|
||||
|
||||
|
||||
@@ -24,14 +24,8 @@ RCT_EXPORT_MODULE()
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithInitialNotification:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithInitialNotification:(NSDictionary *)initialNotification
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_initialNotification = [initialNotification copy];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleRemoteNotificationReceived:)
|
||||
name:RCTRemoteNotificationReceived
|
||||
@@ -45,6 +39,12 @@ RCT_EXPORT_MODULE()
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)setBridge:(RCTBridge *)bridge
|
||||
{
|
||||
_bridge = bridge;
|
||||
_initialNotification = [bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy];
|
||||
}
|
||||
|
||||
+ (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
|
||||
{
|
||||
if ([application respondsToSelector:@selector(registerForRemoteNotifications)]) {
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#import "RCTTestRunner.h"
|
||||
|
||||
#import "FBSnapshotTestController.h"
|
||||
#import "RCTDefines.h"
|
||||
#import "RCTRedBox.h"
|
||||
#import "RCTRootView.h"
|
||||
#import "RCTTestModule.h"
|
||||
@@ -18,6 +17,12 @@
|
||||
|
||||
#define TIMEOUT_SECONDS 240
|
||||
|
||||
@interface RCTBridge (RCTTestRunner)
|
||||
|
||||
@property (nonatomic, weak) RCTBridge *batchedBridge;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTTestRunner
|
||||
{
|
||||
FBSnapshotTestController *_testController;
|
||||
@@ -67,7 +72,7 @@
|
||||
rootView.frame = CGRectMake(0, 0, 320, 2000); // Constant size for testing on multiple devices
|
||||
|
||||
NSString *testModuleName = RCTBridgeModuleNameForClass([RCTTestModule class]);
|
||||
RCTTestModule *testModule = rootView.bridge.modules[testModuleName];
|
||||
RCTTestModule *testModule = rootView.bridge.batchedBridge.modules[testModuleName];
|
||||
testModule.controller = _testController;
|
||||
testModule.testSelector = test;
|
||||
testModule.view = rootView;
|
||||
@@ -76,8 +81,6 @@
|
||||
vc.view = [[UIView alloc] init];
|
||||
[vc.view addSubview:rootView]; // Add as subview so it doesn't get resized
|
||||
|
||||
#if RCT_DEBUG // Prevents build errors, as RCTRedBox is underfined if RCT_DEBUG=0
|
||||
|
||||
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
|
||||
NSString *error = [[RCTRedBox sharedInstance] currentErrorMessage];
|
||||
while ([date timeIntervalSinceNow] > 0 && ![testModule isDone] && error == nil) {
|
||||
@@ -86,8 +89,6 @@
|
||||
error = [[RCTRedBox sharedInstance] currentErrorMessage];
|
||||
}
|
||||
[rootView removeFromSuperview];
|
||||
[rootView.bridge invalidate];
|
||||
[rootView invalidate];
|
||||
RCTAssert(vc.view.subviews.count == 0, @"There shouldn't be any other views: %@", vc.view);
|
||||
vc.view = nil;
|
||||
[[RCTRedBox sharedInstance] dismiss];
|
||||
@@ -98,13 +99,6 @@
|
||||
} else {
|
||||
RCTAssert([testModule isDone], @"Test didn't finish within %d seconds", TIMEOUT_SECONDS);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
expectErrorBlock(@"RCTRedBox unavailable. Set RCT_DEBUG=1 for testing.");
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -66,7 +66,8 @@ typedef void (^WSMessageCallback)(NSError *error, NSDictionary *reply);
|
||||
retries--;
|
||||
}
|
||||
if (!runtimeIsReady) {
|
||||
RCTLogError(@"Runtime is not ready. Do you have Chrome open?");
|
||||
RCTLogError(@"Runtime is not ready. Make sure Chrome is running and not "
|
||||
"paused on a breakpoint or exception and try reloading again.");
|
||||
[self invalidate];
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
require('ExceptionsManager').installConsoleErrorReporter();
|
||||
|
||||
var React = require('React');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var View = require('View');
|
||||
|
||||
250
Libraries/Settings/RCTSettings.xcodeproj/project.pbxproj
Normal file
250
Libraries/Settings/RCTSettings.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,250 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
13DBA45E1AEE749000A17CF8 /* RCTSettingsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DBA45D1AEE749000A17CF8 /* RCTSettingsManager.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
58B511D91A9E6C8500147676 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "include/$(PRODUCT_NAME)";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
134814201AA4EA6300B7C361 /* libRCTSettings.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTSettings.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13DBA45C1AEE749000A17CF8 /* RCTSettingsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSettingsManager.h; sourceTree = "<group>"; };
|
||||
13DBA45D1AEE749000A17CF8 /* RCTSettingsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSettingsManager.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
58B511D81A9E6C8500147676 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
134814211AA4EA7D00B7C361 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
134814201AA4EA6300B7C361 /* libRCTSettings.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
58B511D21A9E6C8500147676 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13DBA45C1AEE749000A17CF8 /* RCTSettingsManager.h */,
|
||||
13DBA45D1AEE749000A17CF8 /* RCTSettingsManager.m */,
|
||||
134814211AA4EA7D00B7C361 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
58B511DA1A9E6C8500147676 /* RCTSettings */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTSettings" */;
|
||||
buildPhases = (
|
||||
58B511D71A9E6C8500147676 /* Sources */,
|
||||
58B511D81A9E6C8500147676 /* Frameworks */,
|
||||
58B511D91A9E6C8500147676 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = RCTSettings;
|
||||
productName = RCTDataManager;
|
||||
productReference = 134814201AA4EA6300B7C361 /* libRCTSettings.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
58B511D31A9E6C8500147676 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
58B511DA1A9E6C8500147676 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTSettings" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 58B511D21A9E6C8500147676;
|
||||
productRefGroup = 58B511D21A9E6C8500147676;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
58B511DA1A9E6C8500147676 /* RCTSettings */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
58B511D71A9E6C8500147676 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13DBA45E1AEE749000A17CF8 /* RCTSettingsManager.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
58B511ED1A9E6C8500147676 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
58B511EE1A9E6C8500147676 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
58B511F01A9E6C8500147676 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../React/**",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = RCTSettings;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
58B511F11A9E6C8500147676 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../React/**",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = RCTSettings;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTSettings" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
58B511ED1A9E6C8500147676 /* Debug */,
|
||||
58B511EE1A9E6C8500147676 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTSettings" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
58B511F01A9E6C8500147676 /* Debug */,
|
||||
58B511F11A9E6C8500147676 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 58B511D31A9E6C8500147676 /* Project object */;
|
||||
}
|
||||
18
Libraries/Settings/RCTSettingsManager.h
Normal file
18
Libraries/Settings/RCTSettingsManager.h
Normal file
@@ -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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
|
||||
@interface RCTSettingsManager : NSObject <RCTBridgeModule>
|
||||
|
||||
- (instancetype)initWithUserDefaults:(NSUserDefaults *)defaults NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
100
Libraries/Settings/RCTSettingsManager.m
Normal file
100
Libraries/Settings/RCTSettingsManager.m
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "RCTSettingsManager.h"
|
||||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
|
||||
@implementation RCTSettingsManager
|
||||
{
|
||||
BOOL _ignoringUpdates;
|
||||
NSUserDefaults *_defaults;
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithUserDefaults:[NSUserDefaults standardUserDefaults]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithUserDefaults:(NSUserDefaults *)defaults
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_defaults = defaults;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(userDefaultsDidChange:)
|
||||
name:NSUserDefaultsDidChangeNotification
|
||||
object:_defaults];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)userDefaultsDidChange:(NSNotification *)note
|
||||
{
|
||||
if (_ignoringUpdates) {
|
||||
return;
|
||||
}
|
||||
|
||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"settingsUpdated" body:[_defaults dictionaryRepresentation]];
|
||||
}
|
||||
|
||||
- (NSDictionary *)constantsToExport
|
||||
{
|
||||
return @{
|
||||
@"settings": [_defaults dictionaryRepresentation]
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set one or more values in the settings.
|
||||
* TODO: would it be useful to have a callback for when this has completed?
|
||||
*/
|
||||
RCT_EXPORT_METHOD(setValues:(NSDictionary *)values)
|
||||
{
|
||||
_ignoringUpdates = YES;
|
||||
[values enumerateKeysAndObjectsUsingBlock:^(NSString *key, id json, BOOL *stop) {
|
||||
id plist = [RCTConvert NSPropertyList:json];
|
||||
if (plist) {
|
||||
[_defaults setObject:plist forKey:key];
|
||||
} else {
|
||||
[_defaults removeObjectForKey:key];
|
||||
}
|
||||
}];
|
||||
|
||||
[_defaults synchronize];
|
||||
_ignoringUpdates = NO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove some values from the settings.
|
||||
*/
|
||||
RCT_EXPORT_METHOD(deleteValues:(NSStringArray *)keys)
|
||||
{
|
||||
_ignoringUpdates = YES;
|
||||
for (NSString *key in keys) {
|
||||
[_defaults removeObjectForKey:key];
|
||||
}
|
||||
|
||||
[_defaults synchronize];
|
||||
_ignoringUpdates = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
34
Libraries/Settings/Settings.android.js
Normal file
34
Libraries/Settings/Settings.android.js
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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 Settings
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var Settings = {
|
||||
get(key: string): mixed {
|
||||
console.warn('Settings is not yet supported on Android');
|
||||
return null;
|
||||
},
|
||||
|
||||
set(settings: Object) {
|
||||
console.warn('Settings is not yet supported on Android');
|
||||
},
|
||||
|
||||
watchKeys(keys: string | Array<string>, callback: Function): number {
|
||||
console.warn('Settings is not yet supported on Android');
|
||||
return -1;
|
||||
},
|
||||
|
||||
clearWatch(watchId: number) {
|
||||
console.warn('Settings is not yet supported on Android');
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = Settings;
|
||||
77
Libraries/Settings/Settings.ios.js
Normal file
77
Libraries/Settings/Settings.ios.js
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* 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 Settings
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||
var RCTSettingsManager = require('NativeModules').SettingsManager;
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
||||
var subscriptions: Array<{keys: Array<string>; callback: ?Function}> = [];
|
||||
|
||||
var Settings = {
|
||||
_settings: RCTSettingsManager.settings,
|
||||
|
||||
get(key: string): mixed {
|
||||
return this._settings[key];
|
||||
},
|
||||
|
||||
set(settings: Object) {
|
||||
this._settings = Object.assign(this._settings, settings);
|
||||
RCTSettingsManager.setValues(settings);
|
||||
},
|
||||
|
||||
watchKeys(keys: string | Array<string>, callback: Function): number {
|
||||
if (typeof keys == 'string') {
|
||||
keys = [keys];
|
||||
}
|
||||
|
||||
invariant(
|
||||
Array.isArray(keys),
|
||||
'keys should be a string or array of strings'
|
||||
);
|
||||
|
||||
var sid = subscriptions.length;
|
||||
subscriptions.push({keys: keys, callback: callback})
|
||||
return sid;
|
||||
},
|
||||
|
||||
clearWatch(watchId: number) {
|
||||
if (watchId < subscriptions.length) {
|
||||
subscriptions[watchId] = {keys: [], callback: null};
|
||||
}
|
||||
},
|
||||
|
||||
_sendObservations(body: Object) {
|
||||
var _this = this;
|
||||
Object.keys(body).forEach((key) => {
|
||||
var newValue = body[key];
|
||||
var didChange = _this._settings[key] !== newValue;
|
||||
_this._settings[key] = newValue;
|
||||
|
||||
if (didChange) {
|
||||
subscriptions.forEach((sub) => {
|
||||
if (~sub.keys.indexOf(key) && sub.callback) {
|
||||
sub.callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
RCTDeviceEventEmitter.addListener(
|
||||
'settingsUpdated',
|
||||
Settings._sendObservations.bind(Settings)
|
||||
);
|
||||
|
||||
module.exports = Settings;
|
||||
@@ -37,7 +37,7 @@ var AsyncStorage = {
|
||||
*/
|
||||
getItem: function(
|
||||
key: string,
|
||||
callback: (error: ?Error, result: ?string) => void
|
||||
callback?: ?(error: ?Error, result: ?string) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiGet([key], function(errors, result) {
|
||||
@@ -60,7 +60,7 @@ var AsyncStorage = {
|
||||
setItem: function(
|
||||
key: string,
|
||||
value: string,
|
||||
callback: ?(error: ?Error) => void
|
||||
callback?: ?(error: ?Error) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiSet([[key,value]], function(errors) {
|
||||
@@ -78,7 +78,7 @@ var AsyncStorage = {
|
||||
*/
|
||||
removeItem: function(
|
||||
key: string,
|
||||
callback: ?(error: ?Error) => void
|
||||
callback?: ?(error: ?Error) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiRemove([key], function(errors) {
|
||||
@@ -100,7 +100,7 @@ var AsyncStorage = {
|
||||
mergeItem: function(
|
||||
key: string,
|
||||
value: string,
|
||||
callback: ?(error: ?Error) => void
|
||||
callback?: ?(error: ?Error) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiMerge([[key,value]], function(errors) {
|
||||
@@ -119,7 +119,7 @@ var AsyncStorage = {
|
||||
* don't want to call this - use removeItem or multiRemove to clear only your
|
||||
* own keys instead. Returns a `Promise` object.
|
||||
*/
|
||||
clear: function(callback: ?(error: ?Error) => void): Promise {
|
||||
clear: function(callback?: ?(error: ?Error) => void): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.clear(function(error) {
|
||||
callback && callback(convertError(error));
|
||||
@@ -135,7 +135,7 @@ var AsyncStorage = {
|
||||
/**
|
||||
* Gets *all* keys known to the system, for all callers, libraries, etc. Returns a `Promise` object.
|
||||
*/
|
||||
getAllKeys: function(callback: (error: ?Error) => void): Promise {
|
||||
getAllKeys: function(callback?: ?(error: ?Error, keys: ?Array<string>) => void): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.getAllKeys(function(error, keys) {
|
||||
callback && callback(convertError(error), keys);
|
||||
@@ -166,7 +166,7 @@ var AsyncStorage = {
|
||||
*/
|
||||
multiGet: function(
|
||||
keys: Array<string>,
|
||||
callback: (errors: ?Array<Error>, result: ?Array<Array<string>>) => void
|
||||
callback?: ?(errors: ?Array<Error>, result: ?Array<Array<string>>) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiGet(keys, function(errors, result) {
|
||||
@@ -189,7 +189,7 @@ var AsyncStorage = {
|
||||
*/
|
||||
multiSet: function(
|
||||
keyValuePairs: Array<Array<string>>,
|
||||
callback: ?(errors: ?Array<Error>) => void
|
||||
callback?: ?(errors: ?Array<Error>) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiSet(keyValuePairs, function(errors) {
|
||||
@@ -209,7 +209,7 @@ var AsyncStorage = {
|
||||
*/
|
||||
multiRemove: function(
|
||||
keys: Array<string>,
|
||||
callback: ?(errors: ?Array<Error>) => void
|
||||
callback?: ?(errors: ?Array<Error>) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiRemove(keys, function(errors) {
|
||||
@@ -232,7 +232,7 @@ var AsyncStorage = {
|
||||
*/
|
||||
multiMerge: function(
|
||||
keyValuePairs: Array<Array<string>>,
|
||||
callback: ?(errors: ?Array<Error>) => void
|
||||
callback?: ?(errors: ?Array<Error>) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiMerge(keyValuePairs, function(errors) {
|
||||
|
||||
@@ -17,7 +17,7 @@ RCT_EXPORT_MODULE()
|
||||
|
||||
- (UIView *)view
|
||||
{
|
||||
return nil;
|
||||
return [[UIView alloc] init]; // TODO(#1102) Remove useless views.
|
||||
}
|
||||
|
||||
- (RCTShadowView *)shadowView
|
||||
|
||||
61
Libraries/Text/TextUpdateTest.js
Normal file
61
Libraries/Text/TextUpdateTest.js
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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 TextUpdateTest
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var TimerMixin = require('react-timer-mixin');
|
||||
var {
|
||||
NativeModules,
|
||||
StyleSheet,
|
||||
Text,
|
||||
} = React;
|
||||
|
||||
var TestManager = NativeModules.TestManager || NativeModules.SnapshotTestManager;
|
||||
|
||||
var TextUpdateTest = React.createClass({
|
||||
mixins: [TimerMixin],
|
||||
getInitialState: function() {
|
||||
return {seeMore: true};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.requestAnimationFrame(
|
||||
() => this.setState(
|
||||
{seeMore: false},
|
||||
TestManager.markTestCompleted
|
||||
)
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<Text
|
||||
style={styles.container}
|
||||
onPress={() => this.setState({seeMore: !this.state.seeMore})}>
|
||||
<Text>Tap to see more (bugs)...</Text>
|
||||
{this.state.seeMore && 'raw text'}
|
||||
</Text>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
margin: 10,
|
||||
marginTop: 100,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = TextUpdateTest;
|
||||
@@ -322,23 +322,24 @@ var MessageQueueMixin = {
|
||||
|
||||
processBatch: function(batch) {
|
||||
var self = this;
|
||||
ReactUpdates.batchedUpdates(function() {
|
||||
batch.forEach(function(call) {
|
||||
invariant(
|
||||
call.module === 'BatchedBridge',
|
||||
'All the calls should pass through the BatchedBridge module'
|
||||
);
|
||||
if (call.method === 'callFunctionReturnFlushedQueue') {
|
||||
self.callFunction.apply(self, call.args);
|
||||
} else if (call.method === 'invokeCallbackAndReturnFlushedQueue') {
|
||||
self.invokeCallback.apply(self, call.args);
|
||||
} else {
|
||||
throw new Error(
|
||||
'Unrecognized method called on BatchedBridge: ' + call.method);
|
||||
}
|
||||
return guardReturn(function () {
|
||||
ReactUpdates.batchedUpdates(function() {
|
||||
batch.forEach(function(call) {
|
||||
invariant(
|
||||
call.module === 'BatchedBridge',
|
||||
'All the calls should pass through the BatchedBridge module'
|
||||
);
|
||||
if (call.method === 'callFunctionReturnFlushedQueue') {
|
||||
self._callFunction.apply(self, call.args);
|
||||
} else if (call.method === 'invokeCallbackAndReturnFlushedQueue') {
|
||||
self._invokeCallback.apply(self, call.args);
|
||||
} else {
|
||||
throw new Error(
|
||||
'Unrecognized method called on BatchedBridge: ' + call.method);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
return this.flushedQueue();
|
||||
}, null, this._flushedQueueUnguarded, this);
|
||||
},
|
||||
|
||||
setLoggingEnabled: function(enabled) {
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var dummySize = {w: undefined, h: undefined};
|
||||
var dummySize = {width: undefined, height: undefined};
|
||||
|
||||
var sizesDiffer = function(one, two) {
|
||||
one = one || dummySize;
|
||||
two = two || dummySize;
|
||||
return one !== two && (
|
||||
one.w !== two.w ||
|
||||
one.h !== two.h
|
||||
one.width !== two.width ||
|
||||
one.height !== two.height
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -17,12 +17,19 @@
|
||||
*/
|
||||
function stringifySafe(arg: any): string {
|
||||
var ret;
|
||||
var type = typeof arg;
|
||||
if (arg === undefined) {
|
||||
ret = 'undefined';
|
||||
} else if (arg === null) {
|
||||
ret = 'null';
|
||||
} else if (typeof arg === 'string') {
|
||||
} else if (type === 'string') {
|
||||
ret = '"' + arg + '"';
|
||||
} else if (type === 'function') {
|
||||
try {
|
||||
ret = arg.toString();
|
||||
} catch (e) {
|
||||
ret = '[function unknown]';
|
||||
}
|
||||
} else {
|
||||
// Perform a try catch, just in case the object has a circular
|
||||
// reference or stringify throws for some other reason.
|
||||
@@ -36,7 +43,7 @@ function stringifySafe(arg: any): string {
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret || '["' + typeof arg + '" failed to stringify]';
|
||||
return ret || '["' + type + '" failed to stringify]';
|
||||
}
|
||||
|
||||
module.exports = stringifySafe;
|
||||
|
||||
Reference in New Issue
Block a user