Updates from Tue 5 May

This commit is contained in:
Alex Kotliarskyi
2015-05-05 14:15:51 -07:00
72 changed files with 2238 additions and 883 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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'
)
};
}

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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,

View File

@@ -582,7 +582,7 @@ var TextInput = React.createClass({
var counter = event.nativeEvent.eventCounter;
if (counter > this.state.mostRecentEventCounter) {
this.setState({mostRecentEventCounter: counter});
}
}
},
});

View File

@@ -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;
}
});

View File

@@ -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,

View File

@@ -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
);
},
/**

View File

@@ -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]),
})}

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;

View File

@@ -11,7 +11,6 @@
*/
'use strict';
var Platform = require('Platform');
var RCTExceptionsManager = require('NativeModules').ExceptionsManager;
var loadSourceMap = require('loadSourceMap');

View File

@@ -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();

View File

@@ -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,

View File

@@ -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;

View File

@@ -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)]) {

View File

@@ -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

View File

@@ -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;
}

View File

@@ -11,8 +11,6 @@
*/
'use strict';
require('ExceptionsManager').installConsoleErrorReporter();
var React = require('React');
var StyleSheet = require('StyleSheet');
var View = require('View');

View 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 */;
}

View 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

View 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

View 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;

View 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;

View File

@@ -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) {

View File

@@ -17,7 +17,7 @@ RCT_EXPORT_MODULE()
- (UIView *)view
{
return nil;
return [[UIView alloc] init]; // TODO(#1102) Remove useless views.
}
- (RCTShadowView *)shadowView

View 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;

View File

@@ -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) {

View File

@@ -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
);
};

View File

@@ -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;