Merge pull request #1353 from a2/Update_Wed_20_May
Updates from Wed 20 May
This commit is contained in:
commit
d20a6e9d2d
|
@ -1,3 +1,5 @@
|
|||
**/node_modules/**/.*js
|
||||
# node_modules ignored by default
|
||||
|
||||
**/staticBundle.js
|
||||
**/main.js
|
||||
Libraries/vendor/**/*
|
||||
|
|
|
@ -168,7 +168,7 @@
|
|||
"no-underscore-dangle": 0, // disallow dangling underscores in identifiers
|
||||
"no-wrap-func": 1, // disallow wrapping of non-IIFE statements in parens
|
||||
"no-mixed-spaces-and-tabs": 1, // disallow mixed spaces and tabs for indentation
|
||||
"quotes": [1, "single"], // specify whether double or single quotes should be used
|
||||
"quotes": [1, "single", "avoid-escape"], // specify whether double or single quotes should be used
|
||||
"quote-props": 0, // require quotes around object literal property names (off by default)
|
||||
"semi": 1, // require or disallow use of semicolons instead of ASI
|
||||
"sort-vars": 0, // sort variables within the same declaration block (off by default)
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule AppEventsTest
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
NativeAppEventEmitter,
|
||||
NativeModules,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
var TestModule = NativeModules.TestModule || NativeModules.SnapshotTestManager;
|
||||
|
||||
var deepDiffer = require('deepDiffer');
|
||||
|
||||
var TEST_PAYLOAD = {foo: 'bar'};
|
||||
|
||||
var AppEventsTest = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {sent: 'none', received: 'none'};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
NativeAppEventEmitter.addListener('testEvent', this.receiveEvent);
|
||||
var event = {data: TEST_PAYLOAD, ts: Date.now()};
|
||||
TestModule.sendAppEvent('testEvent', event);
|
||||
this.setState({sent: event});
|
||||
},
|
||||
receiveEvent: function(event: any) {
|
||||
if (deepDiffer(event.data, TEST_PAYLOAD)) {
|
||||
throw new Error('Received wrong event: ' + JSON.stringify(event));
|
||||
}
|
||||
var elapsed = (Date.now() - event.ts) + 'ms';
|
||||
this.setState({received: event, elapsed}, TestModule.markTestCompleted);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text>
|
||||
{JSON.stringify(this.state, null, ' ')}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
margin: 40,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = AppEventsTest;
|
|
@ -26,6 +26,7 @@ var TESTS = [
|
|||
require('./TimersTest'),
|
||||
require('./AsyncStorageTest'),
|
||||
require('./LayoutEventsTest'),
|
||||
require('./AppEventsTest'),
|
||||
require('./SimpleSnapshotTest'),
|
||||
];
|
||||
|
||||
|
|
|
@ -76,6 +76,11 @@
|
|||
[_runner runTest:_cmd module:@"LayoutEventsTest"];
|
||||
}
|
||||
|
||||
- (void)testAppEvents
|
||||
{
|
||||
[_runner runTest:_cmd module:@"AppEventsTest"];
|
||||
}
|
||||
|
||||
#pragma mark Snapshot Tests
|
||||
|
||||
- (void)testSimpleSnapshot
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
*
|
||||
* @providesModule ARTSerializablePath
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
// TODO: Move this into an ART mode called "serialized" or something
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
*
|
||||
* @providesModule ReactNativeART
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var Color = require('art/core/color');
|
||||
var Path = require('ARTSerializablePath');
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
'use strict';
|
||||
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var NativeModules = require('NativeModules');
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var React = require('React');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
|
|
|
@ -183,7 +183,7 @@ var ScrollResponderMixin = {
|
|||
var currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
||||
if (!this.props.keyboardShouldPersistTaps &&
|
||||
currentlyFocusedTextInput != null &&
|
||||
e.target != currentlyFocusedTextInput) {
|
||||
e.target !== currentlyFocusedTextInput) {
|
||||
return true;
|
||||
}
|
||||
return this.scrollResponderIsAnimating();
|
||||
|
@ -244,7 +244,7 @@ var ScrollResponderMixin = {
|
|||
var currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
||||
if (!this.props.keyboardShouldPersistTaps &&
|
||||
currentlyFocusedTextInput != null &&
|
||||
e.target != currentlyFocusedTextInput &&
|
||||
e.target !== currentlyFocusedTextInput &&
|
||||
!this.state.observedScrollSinceBecomingResponder &&
|
||||
!this.state.becameResponderWhileAnimating) {
|
||||
this.props.onScrollResponderKeyboardDismissed &&
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
'use strict';
|
||||
|
||||
var EventEmitter = require('EventEmitter');
|
||||
import type EventEmitter from 'EventEmitter';
|
||||
|
||||
/**
|
||||
* Subscribable provides a mixin for safely subscribing a component to an
|
||||
|
|
|
@ -179,12 +179,12 @@ var TextInput = React.createClass({
|
|||
'number-pad',
|
||||
'phone-pad',
|
||||
'name-phone-pad',
|
||||
'email-address',
|
||||
'decimal-pad',
|
||||
'twitter',
|
||||
'web-search',
|
||||
// Cross-platform
|
||||
'numeric',
|
||||
'email-address',
|
||||
]),
|
||||
/**
|
||||
* Determines how the return key should look.
|
||||
|
|
|
@ -24,6 +24,26 @@ var createReactNativeComponentClass = require('createReactNativeComponentClass')
|
|||
|
||||
var stylePropType = StyleSheetPropType(ViewStylePropTypes);
|
||||
|
||||
var AccessibilityTraits = [
|
||||
'none',
|
||||
'button',
|
||||
'link',
|
||||
'header',
|
||||
'search',
|
||||
'image',
|
||||
'selected',
|
||||
'plays',
|
||||
'key',
|
||||
'text',
|
||||
'summary',
|
||||
'disabled',
|
||||
'frequentUpdates',
|
||||
'startsMedia',
|
||||
'adjustable',
|
||||
'allowsDirectInteraction',
|
||||
'pageTurn',
|
||||
];
|
||||
|
||||
/**
|
||||
* The most fundamental component for building UI, `View` is a
|
||||
* container that supports layout with flexbox, style, some touch handling, and
|
||||
|
@ -70,6 +90,27 @@ var View = React.createClass({
|
|||
*/
|
||||
accessibilityLabel: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Provides additional traits to screen reader. By default no traits are
|
||||
* provided unless specified otherwise in element
|
||||
*/
|
||||
accessibilityTraits: PropTypes.oneOfType([
|
||||
PropTypes.oneOf(AccessibilityTraits),
|
||||
PropTypes.arrayOf(PropTypes.oneOf(AccessibilityTraits)),
|
||||
]),
|
||||
|
||||
/**
|
||||
* When `accessible` is true, the system will try to invoke this function
|
||||
* when the user performs accessibility tap gesture.
|
||||
*/
|
||||
onAcccessibilityTap: PropTypes.func,
|
||||
|
||||
/**
|
||||
* When `accessible` is true, the system will invoke this function when the
|
||||
* user performs the magic tap gesture.
|
||||
*/
|
||||
onMagicTap: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Used to locate this view in end-to-end tests.
|
||||
*/
|
||||
|
|
|
@ -75,7 +75,7 @@ var WebView = React.createClass({
|
|||
errorEvent.code,
|
||||
errorEvent.description);
|
||||
} else if (this.state.viewState !== WebViewState.IDLE) {
|
||||
console.error("RCTWebView invalid state encountered: " + this.state.loading);
|
||||
console.error('RCTWebView invalid state encountered: ' + this.state.loading);
|
||||
}
|
||||
|
||||
var webViewStyles = [styles.container, this.props.style];
|
||||
|
@ -152,7 +152,7 @@ var WebView = React.createClass({
|
|||
|
||||
onLoadingError: function(event) {
|
||||
event.persist(); // persist this event because we need to store it
|
||||
console.error("encountered an error loading page", event.nativeEvent);
|
||||
console.error('Encountered an error loading page', event.nativeEvent);
|
||||
|
||||
this.setState({
|
||||
lastErrorEvent: event.nativeEvent,
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
var ActivityIndicatorIOS = require('ActivityIndicatorIOS');
|
||||
var EdgeInsetsPropType = require('EdgeInsetsPropType');
|
||||
var React = require('React');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var Text = require('Text');
|
||||
var View = require('View');
|
||||
|
@ -198,7 +197,7 @@ var WebView = React.createClass({
|
|||
|
||||
onLoadingError: function(event: Event) {
|
||||
event.persist(); // persist this event because we need to store it
|
||||
console.error("encountered an error loading page", event.nativeEvent);
|
||||
console.error('Encountered an error loading page', event.nativeEvent);
|
||||
|
||||
this.setState({
|
||||
lastErrorEvent: event.nativeEvent,
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*
|
||||
* @providesModule Navigator
|
||||
*/
|
||||
/* eslint-disable no-extra-boolean-cast*/
|
||||
'use strict';
|
||||
|
||||
var AnimationsDebugModule = require('NativeModules').AnimationsDebugModule;
|
||||
|
@ -48,8 +49,6 @@ var clamp = require('clamp');
|
|||
var flattenStyle = require('flattenStyle');
|
||||
var getNavigatorContext = require('getNavigatorContext');
|
||||
var invariant = require('invariant');
|
||||
var keyMirror = require('keyMirror');
|
||||
var merge = require('merge');
|
||||
var rebound = require('rebound');
|
||||
|
||||
var PropTypes = React.PropTypes;
|
||||
|
@ -689,7 +688,7 @@ var Navigator = React.createClass({
|
|||
*/
|
||||
_enableScene: function(sceneIndex) {
|
||||
// First, determine what the defined styles are for scenes in this navigator
|
||||
var sceneStyle = flattenStyle(this.props.sceneStyle);
|
||||
var sceneStyle = flattenStyle([styles.baseScene, this.props.sceneStyle]);
|
||||
// Then restore the left value for this scene
|
||||
var enabledSceneNativeProps = {
|
||||
left: sceneStyle.left,
|
||||
|
@ -745,7 +744,6 @@ var Navigator = React.createClass({
|
|||
},
|
||||
|
||||
_handleMoveShouldSetPanResponder: function(e, gestureState) {
|
||||
var currentRoute = this.state.routeStack[this.state.presentedIndex];
|
||||
var sceneConfig = this.state.sceneConfigStack[this.state.presentedIndex];
|
||||
this._expectingGestureGrant = this._matchGestureAction(this._eligibleGestures, sceneConfig.gestures, gestureState);
|
||||
return !! this._expectingGestureGrant;
|
||||
|
@ -829,7 +827,16 @@ var Navigator = React.createClass({
|
|||
}
|
||||
} else {
|
||||
// The gesture has enough velocity to complete, so we transition to the gesture's destination
|
||||
this._transitionTo(destIndex, transitionVelocity);
|
||||
this._transitionTo(
|
||||
destIndex,
|
||||
transitionVelocity,
|
||||
null,
|
||||
() => {
|
||||
if (releaseGestureAction === 'pop') {
|
||||
this._cleanScenesPastIndex(destIndex);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
this._detachGesture();
|
||||
},
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
* @providesModule fetch
|
||||
* @nolint
|
||||
*/
|
||||
/* eslint-disable */
|
||||
'use strict';
|
||||
|
||||
var self = {};
|
||||
|
|
|
@ -120,6 +120,6 @@ var Geolocation = {
|
|||
subscriptions = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Geolocation;
|
||||
|
|
|
@ -60,7 +60,7 @@ var Image = React.createClass({
|
|||
/**
|
||||
* `uri` is a string representing the resource identifier for the image, which
|
||||
* could be an http address, a local file path, or the name of a static image
|
||||
* resource (which should be wrapped in the `required('image!name')` function).
|
||||
* resource (which should be wrapped in the `require('image!name')` function).
|
||||
*/
|
||||
source: PropTypes.shape({
|
||||
uri: PropTypes.string,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* and wrapping resulting file into `wrapper` function.
|
||||
*
|
||||
*/
|
||||
/*eslint-disable */
|
||||
|
||||
var scope = {};
|
||||
wrapper.call(scope);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*
|
||||
* @nolint
|
||||
*/
|
||||
/* eslint-disable */
|
||||
|
||||
(function() {
|
||||
var define = null; // Hack to make it work with our packager
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
*/
|
||||
'use strict';
|
||||
|
||||
var NativeModules = require('NativeModules');
|
||||
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||
var RCTPushNotificationManager = require('NativeModules').PushNotificationManager;
|
||||
var invariant = require('invariant');
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#import "FBSnapshotTestController.h"
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTUIManager.h"
|
||||
|
||||
|
@ -63,4 +64,9 @@ RCT_EXPORT_METHOD(markTestCompleted)
|
|||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(sendAppEvent:(NSString *)name body:(id)body)
|
||||
{
|
||||
[_bridge.eventDispatcher sendAppEventWithName:name body:body];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -58,4 +58,3 @@ var queryLayoutByID = function(
|
|||
};
|
||||
|
||||
module.exports = queryLayoutByID;
|
||||
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
* @providesModule IOSNativeBridgeEventPlugin
|
||||
* @flow
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var EventPropagators = require('EventPropagators');
|
||||
var NativeModules = require('NativeModules');
|
||||
|
@ -33,7 +32,7 @@ for (var bubblingTypeName in customBubblingEventTypes) {
|
|||
for (var directTypeName in customDirectEventTypes) {
|
||||
warning(
|
||||
!customBubblingEventTypes[directTypeName],
|
||||
"Event cannot be both direct and bubbling: %s",
|
||||
'Event cannot be both direct and bubbling: %s',
|
||||
directTypeName
|
||||
);
|
||||
allTypesByEventName[directTypeName] = customDirectEventTypes[directTypeName];
|
||||
|
@ -76,4 +75,3 @@ var IOSNativeBridgeEventPlugin = {
|
|||
};
|
||||
|
||||
module.exports = IOSNativeBridgeEventPlugin;
|
||||
|
||||
|
|
|
@ -22,6 +22,13 @@ function verifyPropTypes(
|
|||
if (!viewConfig) {
|
||||
return; // This happens for UnimplementedView.
|
||||
}
|
||||
var componentName = component.name || component.displayName;
|
||||
if (!component.propTypes) {
|
||||
throw new Error(
|
||||
'`' + componentName + '` has no propTypes defined`'
|
||||
);
|
||||
}
|
||||
|
||||
var nativeProps = viewConfig.nativeProps;
|
||||
for (var prop in nativeProps) {
|
||||
if (!component.propTypes[prop] &&
|
||||
|
@ -29,9 +36,9 @@ function verifyPropTypes(
|
|||
!ReactNativeStyleAttributes[prop] &&
|
||||
(!nativePropsToIgnore || !nativePropsToIgnore[prop])) {
|
||||
throw new Error(
|
||||
'`' + component.displayName + '` has no propType for native prop `' +
|
||||
'`' + componentName + '` has no propType for native prop `' +
|
||||
viewConfig.uiViewClassName + '.' + prop + '` of native type `' +
|
||||
nativeProps[prop].type + '`'
|
||||
nativeProps[prop] + '`'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
* @providesModule React
|
||||
* @flow
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
module.exports = require('ReactNative');
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* @providesModule ReactNative
|
||||
* @flow
|
||||
*/
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var ReactChildren = require('ReactChildren');
|
||||
var ReactClass = require('ReactClass');
|
||||
|
|
|
@ -63,7 +63,8 @@ var cachedIndexArray = function(size) {
|
|||
for (var i = 0; i < size; i++) {
|
||||
arr[i] = i;
|
||||
}
|
||||
return cachedIndexArray._cache[size] = arr;
|
||||
cachedIndexArray._cache[size] = arr;
|
||||
return arr;
|
||||
} else {
|
||||
return cachedResult;
|
||||
}
|
||||
|
@ -228,7 +229,7 @@ ReactNativeBaseComponent.Mixin = {
|
|||
*/
|
||||
_reconcileListenersUponUpdate: function(prevProps, nextProps) {
|
||||
for (var key in nextProps) {
|
||||
if (registrationNames[key] && (nextProps[key] != prevProps[key])) {
|
||||
if (registrationNames[key] && (nextProps[key] !== prevProps[key])) {
|
||||
putListener(this._rootNodeID, key, nextProps[key]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
* @providesModule ReactNativeDOMIDOperations
|
||||
* @flow
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var ReactNativeTagHandles = require('ReactNativeTagHandles');
|
||||
var ReactMultiChildUpdateTypes = require('ReactMultiChildUpdateTypes');
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
* @providesModule ReactNativeDefaultInjection
|
||||
* @flow
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Make sure `setTimeout`/`setInterval` are patched correctly.
|
||||
|
@ -21,7 +20,6 @@ var EventPluginUtils = require('EventPluginUtils');
|
|||
var IOSDefaultEventPluginOrder = require('IOSDefaultEventPluginOrder');
|
||||
var IOSNativeBridgeEventPlugin = require('IOSNativeBridgeEventPlugin');
|
||||
var NodeHandle = require('NodeHandle');
|
||||
var ReactClass = require('ReactClass');
|
||||
var ReactComponentEnvironment = require('ReactComponentEnvironment');
|
||||
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
|
||||
var ReactEmptyComponent = require('ReactEmptyComponent');
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
* @providesModule ReactNativeEventEmitter
|
||||
* @flow
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var EventPluginHub = require('EventPluginHub');
|
||||
var ReactEventEmitterMixin = require('ReactEventEmitterMixin');
|
||||
|
|
|
@ -21,7 +21,6 @@ var ReactUpdates = require('ReactUpdates');
|
|||
|
||||
var emptyObject = require('emptyObject');
|
||||
var instantiateReactComponent = require('instantiateReactComponent');
|
||||
var invariant = require('invariant');
|
||||
var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
|
||||
|
||||
function instanceNumberToChildRootID(rootNodeID, instanceNumber) {
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
* @providesModule ReactNativeReconcileTransaction
|
||||
* @flow
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var CallbackQueue = require('CallbackQueue');
|
||||
var PooledClass = require('PooledClass');
|
||||
|
|
|
@ -19,8 +19,11 @@ ReactNativeViewAttributes.UIView = {
|
|||
pointerEvents: true,
|
||||
accessible: true,
|
||||
accessibilityLabel: true,
|
||||
accessibilityTraits: true,
|
||||
testID: true,
|
||||
onLayout: true,
|
||||
onAccessibilityTap: true,
|
||||
onMagicTap: true,
|
||||
};
|
||||
|
||||
ReactNativeViewAttributes.RCTView = merge(
|
||||
|
|
|
@ -10,9 +10,8 @@
|
|||
* @flow
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactNativeBaseComponent = require('ReactNativeBaseComponent');
|
||||
|
||||
// See also ReactNativeBaseComponent
|
||||
|
|
|
@ -31,7 +31,7 @@ var Settings = {
|
|||
},
|
||||
|
||||
watchKeys(keys: string | Array<string>, callback: Function): number {
|
||||
if (typeof keys == 'string') {
|
||||
if (typeof keys === 'string') {
|
||||
keys = [keys];
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ var Settings = {
|
|||
);
|
||||
|
||||
var sid = subscriptions.length;
|
||||
subscriptions.push({keys: keys, callback: callback})
|
||||
subscriptions.push({keys: keys, callback: callback});
|
||||
return sid;
|
||||
},
|
||||
|
||||
|
@ -52,15 +52,14 @@ var Settings = {
|
|||
},
|
||||
|
||||
_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;
|
||||
var didChange = this._settings[key] !== newValue;
|
||||
this._settings[key] = newValue;
|
||||
|
||||
if (didChange) {
|
||||
subscriptions.forEach((sub) => {
|
||||
if (~sub.keys.indexOf(key) && sub.callback) {
|
||||
if (sub.keys.indexOf(key) !== -1 && sub.callback) {
|
||||
sub.callback();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -9,12 +9,11 @@
|
|||
* @providesModule EdgeInsetsPropType
|
||||
* @flow
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
|
||||
var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker');
|
||||
var insetsDiffer = require('insetsDiffer');
|
||||
|
||||
var EdgeInsetsPropType = createStrictShapeTypeChecker({
|
||||
top: PropTypes.number,
|
||||
|
|
|
@ -9,12 +9,11 @@
|
|||
* @providesModule PointPropType
|
||||
* @flow
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
|
||||
var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker');
|
||||
var pointsDiffer = require('pointsDiffer');
|
||||
|
||||
var PointPropType = createStrictShapeTypeChecker({
|
||||
x: PropTypes.number,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*
|
||||
* @providesModule ErrorUtils
|
||||
*/
|
||||
/* eslint-disable consistent-this, global-strict */
|
||||
|
||||
var GLOBAL = this;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* @providesModule MatrixMath
|
||||
*/
|
||||
/* eslint-disable space-infix-ops */
|
||||
'use strict';
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
* @providesModule RCTLog
|
||||
* @flow
|
||||
*/
|
||||
/* globals nativeLoggingHook */
|
||||
'use strict';
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
'use strict';
|
||||
|
||||
var ReactDefaultPerf = require('ReactDefaultPerf');
|
||||
var ReactPerf = require('ReactPerf');
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
function execute(fun, context, args) {
|
||||
return fun.apply(context, args);
|
||||
};
|
||||
}
|
||||
|
||||
function reportError(error) {
|
||||
throw error;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
/**
|
||||
* Cannot "use strict" because we must use eval in this file.
|
||||
*/
|
||||
/* eslint-disable global-strict */
|
||||
|
||||
var keyOf = require('keyOf');
|
||||
|
||||
|
|
|
@ -45,4 +45,3 @@ var truncate = function(
|
|||
};
|
||||
|
||||
module.exports = truncate;
|
||||
|
||||
|
|
|
@ -141,6 +141,7 @@ RCT_EXTERN BOOL RCTCopyProperty(id target, id source, NSString *keyPath);
|
|||
* Underlying implementations of RCT_XXX_CONVERTER macros. Ignore these.
|
||||
*/
|
||||
RCT_EXTERN NSNumber *RCTConvertEnumValue(const char *, NSDictionary *, NSNumber *, id);
|
||||
RCT_EXTERN NSNumber *RCTConvertMultiEnumValue(const char *, NSDictionary *, NSNumber *, id);
|
||||
RCT_EXTERN NSArray *RCTConvertArrayValue(SEL, id);
|
||||
RCT_EXTERN void RCTLogConvertError(id, const char *);
|
||||
|
||||
|
@ -194,6 +195,21 @@ RCT_CUSTOM_CONVERTER(type, type, [[self NSNumber:json] getter])
|
|||
return [RCTConvertEnumValue(#type, mapping, @(default), json) getter]; \
|
||||
}
|
||||
|
||||
/**
|
||||
* This macro is used for creating converters for enum types for
|
||||
* multiple enum values combined with | operator
|
||||
*/
|
||||
#define RCT_MULTI_ENUM_CONVERTER(type, values, default, getter) \
|
||||
+ (type)type:(id)json \
|
||||
{ \
|
||||
static NSDictionary *mapping; \
|
||||
static dispatch_once_t onceToken; \
|
||||
dispatch_once(&onceToken, ^{ \
|
||||
mapping = values; \
|
||||
}); \
|
||||
return [RCTConvertMultiEnumValue(#type, mapping, @(default), json) getter]; \
|
||||
}
|
||||
|
||||
/**
|
||||
* This macro is used for creating converter functions for typed arrays.
|
||||
*/
|
||||
|
|
|
@ -175,6 +175,22 @@ NSNumber *RCTConvertEnumValue(const char *typeName, NSDictionary *mapping, NSNum
|
|||
return value ?: defaultValue;
|
||||
}
|
||||
|
||||
NSNumber *RCTConvertMultiEnumValue(const char *typeName, NSDictionary *mapping, NSNumber *defaultValue, id json)
|
||||
{
|
||||
if ([json isKindOfClass:[NSArray class]]) {
|
||||
if ([json count] == 0) {
|
||||
return defaultValue;
|
||||
}
|
||||
long long result = 0;
|
||||
for (id arrayElement in json) {
|
||||
NSNumber *value = RCTConvertEnumValue(typeName, mapping, defaultValue, arrayElement);
|
||||
result |= [value longLongValue];
|
||||
}
|
||||
return @(result);
|
||||
}
|
||||
return RCTConvertEnumValue(typeName, mapping, defaultValue, json);
|
||||
}
|
||||
|
||||
RCT_ENUM_CONVERTER(NSTextAlignment, (@{
|
||||
@"auto": @(NSTextAlignmentNatural),
|
||||
@"left": @(NSTextAlignmentLeft),
|
||||
|
|
|
@ -1309,6 +1309,12 @@ RCT_EXPORT_METHOD(clearJSResponder)
|
|||
@"topLoadingError": @{
|
||||
@"registrationName": @"onLoadingError"
|
||||
},
|
||||
@"topAccessibilityTap": @{
|
||||
@"registrationName": @"onAccessibilityTap"
|
||||
},
|
||||
@"topMagicTap": @{
|
||||
@"registrationName": @"onMagicTap"
|
||||
},
|
||||
} mutableCopy];
|
||||
|
||||
[_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, RCTViewManager *manager, BOOL *stop) {
|
||||
|
|
|
@ -15,8 +15,14 @@
|
|||
|
||||
@protocol RCTAutoInsetsProtocol;
|
||||
|
||||
@class RCTView;
|
||||
typedef void (^RCTViewEventHandler)(RCTView *view);
|
||||
|
||||
@interface RCTView : UIView
|
||||
|
||||
@property (nonatomic, copy) RCTViewEventHandler accessibilityTapHandler;
|
||||
@property (nonatomic, copy) RCTViewEventHandler magicTapHandler;
|
||||
|
||||
/**
|
||||
* Used to control how touch events are processed.
|
||||
*/
|
||||
|
|
|
@ -167,6 +167,26 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
|||
}
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityActivate
|
||||
{
|
||||
if (self.accessibilityTapHandler) {
|
||||
self.accessibilityTapHandler(self);
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityPerformMagicTap
|
||||
{
|
||||
if (self.magicTapHandler) {
|
||||
self.magicTapHandler(self);
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Statics for dealing with layoutGuides
|
||||
|
||||
+ (void)autoAdjustInsetsForView:(UIView<RCTAutoInsetsProtocol> *)parentView
|
||||
|
|
|
@ -17,6 +17,31 @@
|
|||
#import "RCTUIManager.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "RCTView.h"
|
||||
#import "UIView+React.h"
|
||||
|
||||
@implementation RCTConvert(UIAccessibilityTraits)
|
||||
|
||||
RCT_MULTI_ENUM_CONVERTER(UIAccessibilityTraits, (@{
|
||||
@"none": @(UIAccessibilityTraitNone),
|
||||
@"button": @(UIAccessibilityTraitButton),
|
||||
@"link": @(UIAccessibilityTraitLink),
|
||||
@"header": @(UIAccessibilityTraitHeader),
|
||||
@"search": @(UIAccessibilityTraitSearchField),
|
||||
@"image": @(UIAccessibilityTraitImage),
|
||||
@"selected": @(UIAccessibilityTraitSelected),
|
||||
@"plays": @(UIAccessibilityTraitPlaysSound),
|
||||
@"key": @(UIAccessibilityTraitKeyboardKey),
|
||||
@"text": @(UIAccessibilityTraitStaticText),
|
||||
@"summary": @(UIAccessibilityTraitSummaryElement),
|
||||
@"disabled": @(UIAccessibilityTraitNotEnabled),
|
||||
@"frequentUpdates": @(UIAccessibilityTraitUpdatesFrequently),
|
||||
@"startsMedia": @(UIAccessibilityTraitStartsMediaSession),
|
||||
@"adjustable": @(UIAccessibilityTraitAdjustable),
|
||||
@"allowsDirectInteraction": @(UIAccessibilityTraitAllowsDirectInteraction),
|
||||
@"pageTurn": @(UIAccessibilityTraitCausesPageTurn),
|
||||
}), UIAccessibilityTraitNone, unsignedLongLongValue)
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTViewManager
|
||||
|
||||
|
@ -67,6 +92,7 @@ RCT_EXPORT_MODULE()
|
|||
#pragma mark - View properties
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(accessibilityLabel, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(accessibilityTraits, UIAccessibilityTraits)
|
||||
RCT_EXPORT_VIEW_PROPERTY(backgroundColor, UIColor)
|
||||
RCT_REMAP_VIEW_PROPERTY(accessible, isAccessibilityElement, BOOL)
|
||||
RCT_REMAP_VIEW_PROPERTY(testID, accessibilityIdentifier, NSString)
|
||||
|
@ -146,6 +172,27 @@ RCT_CUSTOM_VIEW_PROPERTY(borderWidth, CGFloat, RCTView)
|
|||
view.layer.borderWidth = json ? [RCTConvert CGFloat:json] : defaultView.layer.borderWidth;
|
||||
}
|
||||
}
|
||||
RCT_CUSTOM_VIEW_PROPERTY(onAccessibilityTap, BOOL, RCTView)
|
||||
{
|
||||
view.accessibilityTapHandler = [self eventHandlerWithName:@"topAccessibilityTap" json:json];
|
||||
}
|
||||
RCT_CUSTOM_VIEW_PROPERTY(onMagicTap, BOOL, RCTView)
|
||||
{
|
||||
view.magicTapHandler = [self eventHandlerWithName:@"topMagicTap" json:json];
|
||||
}
|
||||
|
||||
- (RCTViewEventHandler)eventHandlerWithName:(NSString *)eventName json:(id)json
|
||||
{
|
||||
RCTViewEventHandler handler = nil;
|
||||
if ([RCTConvert BOOL:json]) {
|
||||
__weak RCTViewManager *weakSelf = self;
|
||||
handler = ^(RCTView *tappedView) {
|
||||
NSDictionary *body = @{ @"target": tappedView.reactTag };
|
||||
[weakSelf.bridge.eventDispatcher sendInputEventWithName:eventName body:body];
|
||||
};
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
#define RCT_VIEW_BORDER_PROPERTY(SIDE) \
|
||||
RCT_CUSTOM_VIEW_PROPERTY(border##SIDE##Width, CGFloat, RCTView) \
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
],
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"lint": "node linter.js Examples/",
|
||||
"lint": "node linter.js Examples/ Libraries/",
|
||||
"start": "./packager/packager.sh"
|
||||
},
|
||||
"bin": {
|
||||
|
|
Loading…
Reference in New Issue