diff --git a/.flowconfig b/.flowconfig
index ca1e816a28f1be..3e5608c4e3bfc2 100644
--- a/.flowconfig
+++ b/.flowconfig
@@ -41,12 +41,12 @@ suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe
-suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-0]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)
-suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-0]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)?:? #[0-9]+
+suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-1]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)
+suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-1]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
unsafe.enable_getters_and_setters=true
[version]
-^0.40.0
+^0.41.0
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index ad776d931b493d..c7b878bad1c8c9 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,8 +1,11 @@
-We use GitHub Issues for bugs.
+Please read the following carefully before opening a new issue.
-If you have a non-bug question, ask on Stack Overflow: http://stackoverflow.com/questions/tagged/react-native
+We use GitHub Issues for tracking bugs in React Native.
-If you have a feature request, post it on Product Pains: https://productpains.com/product/react-native/
+- If you have a non-bug question, ask on Stack Overflow: http://stackoverflow.com/questions/tagged/react-native
+- If you have a feature request, post it on Canny: https://react-native.canny.io/feature-requests
+
+Your issue may be closed without explanation if it does not provide the information required by this template.
--- Please use this template, and delete everything above this line before submitting your issue ---
@@ -23,3 +26,4 @@ If you have a feature request, post it on Product Pains: https://productpains.co
* React Native version: [FILL THIS OUT: Does the bug reproduce on the latest RN release?]
* Platform: [FILL THIS OUT: iOS, Android, or both?]
* Operating System: [FILL THIS OUT: MacOS, Linux, or Windows?]
+* Dev tools: [FILL THIS OUT: Xcode or Android Studio version, iOS or Android SDK version, if applicable]
diff --git a/.gitignore b/.gitignore
index 07790dc4745276..1ecdbc1bd3fa7d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,3 +54,5 @@ node_modules
# Test generated files
/ReactAndroid/src/androidTest/assets/AndroidTestBundle.js
*.js.meta
+
+/third-party
diff --git a/.travis.yml b/.travis.yml
index 40f52ea8c85334..5f0caaabc938ee 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
language: objective-c
-osx_image: xcode8
+osx_image: xcode8.2
install:
- mkdir -p /Users/travis/build/facebook/.nvm
@@ -20,19 +20,18 @@ script:
- if [[ "$TEST_TYPE" = objc-ios ]]; then travis_retry travis_wait ./scripts/objc-test-ios.sh; fi
- if [[ "$TEST_TYPE" = objc-tvos ]]; then travis_retry travis_wait ./scripts/objc-test-tvos.sh; fi
- if [[ "$TEST_TYPE" = e2e-objc ]]; then node ./scripts/run-ci-e2e-tests.js --ios --js --retries 3; fi
- - if [[ "$TEST_TYPE" = e2e-objc-tvos ]]; then node ./scripts/run-ci-e2e-tests.js --tvos --retries 3; fi
- - if [[ "$TEST_TYPE" = js ]]; then npm run flow check; fi
- - if [[ "$TEST_TYPE" = js ]]; then npm test -- --maxWorkers=1; fi
- if [[ ( "$TEST_TYPE" = podspecs ) && ( "$TRAVIS_PULL_REQUEST" = "false" ) ]]; then gem install cocoapods && ./scripts/process-podspecs.sh; fi
+
+matrix:
+ - fast_finish: true # Fail the whole build as soon as one test type fails. Should help with Travis capacity issues (very long queues).
+
+# The order of these tests says which are more likely to run first and fail the whole build fast.
env:
- matrix:
- - TEST_TYPE=e2e-objc-tvos
- - TEST_TYPE=e2e-objc
- - TEST_TYPE=objc-ios
- - TEST_TYPE=objc-tvos
- - TEST_TYPE=js
- - TEST_TYPE=podspecs
+ - TEST_TYPE=objc-ios
+ - TEST_TYPE=podspecs
+ - TEST_TYPE=e2e-objc
+ - TEST_TYPE=objc-tvos
branches:
only:
@@ -43,7 +42,8 @@ notifications:
email:
recipients:
- mkonicek@fb.com
- - eloy@artsy.net
+ - douglowder@mac.com # Doug Lowder built and maintains Apple TV specific code and wants to be notified about tvOS failures.
+ - eloy@artsy.net # Eloy Durán maintains the podspecs test and wants to be notified about failures.
on_failure: change
on_success: change
slack:
diff --git a/Examples/Movies/SearchScreen.js b/Examples/Movies/SearchScreen.js
index 316b974e5ae44a..57fa82885f7950 100644
--- a/Examples/Movies/SearchScreen.js
+++ b/Examples/Movies/SearchScreen.js
@@ -123,15 +123,6 @@ var SearchScreen = React.createClass({
fetch(this._urlForQueryAndPage(query, 1))
.then((response) => response.json())
- .catch((error) => {
- LOADING[query] = false;
- resultsCache.dataForQuery[query] = undefined;
-
- this.setState({
- dataSource: this.getDataSource([]),
- isLoading: false,
- });
- })
.then((responseData) => {
LOADING[query] = false;
resultsCache.totalForQuery[query] = responseData.total;
@@ -148,6 +139,15 @@ var SearchScreen = React.createClass({
dataSource: this.getDataSource(responseData.movies),
});
})
+ .catch((error) => {
+ LOADING[query] = false;
+ resultsCache.dataForQuery[query] = undefined;
+
+ this.setState({
+ dataSource: this.getDataSource([]),
+ isLoading: false,
+ });
+ })
.done();
},
diff --git a/Examples/UIExplorer/js/CameraRollView.js b/Examples/UIExplorer/js/CameraRollView.js
index 8bb9fbd2b07765..ca5f1dc5e8e26a 100644
--- a/Examples/UIExplorer/js/CameraRollView.js
+++ b/Examples/UIExplorer/js/CameraRollView.js
@@ -81,6 +81,7 @@ var propTypes = {
};
var CameraRollView = React.createClass({
+ // $FlowFixMe(>=0.41.0)
propTypes: propTypes,
getDefaultProps: function(): Object {
@@ -123,6 +124,7 @@ var CameraRollView = React.createClass({
rendererChanged: function() {
var ds = new ListView.DataSource({rowHasChanged: this._rowHasChanged});
this.state.dataSource = ds.cloneWithRows(
+ // $FlowFixMe(>=0.41.0)
groupByEveryN(this.state.assets, this.props.imagesPerRow)
);
},
@@ -209,6 +211,7 @@ var CameraRollView = React.createClass({
if (image === null) {
return null;
}
+ // $FlowFixMe(>=0.41.0)
return this.props.renderImage(image);
});
@@ -231,6 +234,7 @@ var CameraRollView = React.createClass({
newState.lastCursor = data.page_info.end_cursor;
newState.assets = this.state.assets.concat(assets);
newState.dataSource = this.state.dataSource.cloneWithRows(
+ // $FlowFixMe(>=0.41.0)
groupByEveryN(newState.assets, this.props.imagesPerRow)
);
}
diff --git a/Examples/UIExplorer/js/FlatListExample.js b/Examples/UIExplorer/js/FlatListExample.js
index 0871e7374ae258..6ff92e6dcdf24e 100644
--- a/Examples/UIExplorer/js/FlatListExample.js
+++ b/Examples/UIExplorer/js/FlatListExample.js
@@ -26,11 +26,12 @@
const React = require('react');
const ReactNative = require('react-native');
const {
+ Animated,
+ FlatList,
StyleSheet,
View,
} = ReactNative;
-const FlatList = require('FlatList');
const UIExplorerPage = require('./UIExplorerPage');
const infoLog = require('infoLog');
@@ -47,6 +48,8 @@ const {
renderSmallSwitchOption,
} = require('./ListExampleShared');
+const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
+
const VIEWABILITY_CONFIG = {
minimumViewTime: 3000,
viewAreaCoveragePercentThreshold: 100,
@@ -66,18 +69,34 @@ class FlatListExample extends React.PureComponent {
logViewable: false,
virtualized: true,
};
+
_onChangeFilterText = (filterText) => {
this.setState({filterText});
};
+
_onChangeScrollToIndex = (text) => {
- this._listRef.scrollToIndex({viewPosition: 0.5, index: Number(text)});
+ this._listRef.getNode().scrollToIndex({viewPosition: 0.5, index: Number(text)});
};
+
+ _scrollPos = new Animated.Value(0);
+ _scrollSinkX = Animated.event(
+ [{nativeEvent: { contentOffset: { x: this._scrollPos } }}],
+ {useNativeDriver: true},
+ );
+ _scrollSinkY = Animated.event(
+ [{nativeEvent: { contentOffset: { y: this._scrollPos } }}],
+ {useNativeDriver: true},
+ );
+
componentDidUpdate() {
- this._listRef.recordInteraction(); // e.g. flipping logViewable switch
+ this._listRef.getNode().recordInteraction(); // e.g. flipping logViewable switch
}
+
render() {
const filterRegex = new RegExp(String(this.state.filterText), 'i');
- const filter = (item) => (filterRegex.test(item.text) || filterRegex.test(item.title));
+ const filter = (item) => (
+ filterRegex.test(item.text) || filterRegex.test(item.title)
+ );
const filteredData = this.state.data.filter(filter);
return (
@@ -102,22 +120,37 @@ class FlatListExample extends React.PureComponent {
{renderSmallSwitchOption(this, 'fixedHeight')}
{renderSmallSwitchOption(this, 'logViewable')}
{renderSmallSwitchOption(this, 'debug')}
+
-
}
) => {
// Impressions can be logged here
if (this.state.logViewable) {
- infoLog('onViewableItemsChanged: ', info.changed.map((v) => ({...v, item: '...'})));
+ infoLog(
+ 'onViewableItemsChanged: ',
+ info.changed.map((v) => ({...v, item: '...'})),
+ );
}
};
_pressItem = (key: number) => {
- this._listRef.recordInteraction();
+ this._listRef.getNode().recordInteraction();
pressItem(this, key);
};
_listRef: FlatList<*>;
@@ -180,6 +222,12 @@ const styles = StyleSheet.create({
searchRow: {
paddingHorizontal: 10,
},
+ spindicator: {
+ marginLeft: 'auto',
+ width: 2,
+ height: 16,
+ backgroundColor: 'darkgray',
+ },
});
module.exports = FlatListExample;
diff --git a/Examples/UIExplorer/js/ImageExample.js b/Examples/UIExplorer/js/ImageExample.js
index 04f7437f807739..95ed82f307b990 100644
--- a/Examples/UIExplorer/js/ImageExample.js
+++ b/Examples/UIExplorer/js/ImageExample.js
@@ -677,6 +677,45 @@ exports.examples = [
},
platform: 'ios',
},
+ {
+ title: 'Blur Radius',
+ render: function() {
+ return (
+
+
+
+
+
+
+
+
+ );
+ },
+ },
];
var fullImage = {uri: 'https://facebook.github.io/react/img/logo_og.png'};
diff --git a/Examples/UIExplorer/js/MapViewExample.js b/Examples/UIExplorer/js/MapViewExample.js
deleted file mode 100644
index d2143eec277bb4..00000000000000
--- a/Examples/UIExplorer/js/MapViewExample.js
+++ /dev/null
@@ -1,473 +0,0 @@
-/**
- * Copyright (c) 2013-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.
- *
- * 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.
- *
- * @flow
- * @providesModule MapViewExample
- */
-'use strict';
-
-var React = require('react');
-var ReactNative = require('react-native');
-var { PropTypes } = React;
-var {
- Image,
- MapView,
- StyleSheet,
- Text,
- TextInput,
- TouchableOpacity,
- View,
-} = ReactNative;
-
-var regionText = {
- latitude: '0',
- longitude: '0',
- latitudeDelta: '0',
- longitudeDelta: '0',
-};
-
-var MapRegionInput = React.createClass({
-
- propTypes: {
- region: PropTypes.shape({
- latitude: PropTypes.number.isRequired,
- longitude: PropTypes.number.isRequired,
- latitudeDelta: PropTypes.number,
- longitudeDelta: PropTypes.number,
- }),
- onChange: PropTypes.func.isRequired,
- },
-
- getInitialState() {
- return {
- region: {
- latitude: 0,
- longitude: 0,
- }
- };
- },
-
- componentWillReceiveProps: function(nextProps) {
- this.setState({
- region: nextProps.region || this.getInitialState().region
- });
- },
-
- render: function() {
- var region = this.state.region || this.getInitialState().region;
- return (
-
-
-
- {'Latitude'}
-
-
-
-
-
- {'Longitude'}
-
-
-
-
-
- {'Latitude delta'}
-
-
-
-
-
- {'Longitude delta'}
-
-
-
-
-
- {'Change'}
-
-
-
- );
- },
-
- _onChangeLatitude: function(e) {
- regionText.latitude = e.nativeEvent.text;
- },
-
- _onChangeLongitude: function(e) {
- regionText.longitude = e.nativeEvent.text;
- },
-
- _onChangeLatitudeDelta: function(e) {
- regionText.latitudeDelta = e.nativeEvent.text;
- },
-
- _onChangeLongitudeDelta: function(e) {
- regionText.longitudeDelta = e.nativeEvent.text;
- },
-
- _change: function() {
- this.setState({
- region: {
- latitude: parseFloat(regionText.latitude),
- longitude: parseFloat(regionText.longitude),
- latitudeDelta: parseFloat(regionText.latitudeDelta),
- longitudeDelta: parseFloat(regionText.longitudeDelta),
- },
- });
- this.props.onChange(this.state.region);
- },
-
-});
-
-class MapViewExample extends React.Component {
- state = {
- isFirstLoad: true,
- mapRegion: undefined,
- mapRegionInput: undefined,
- annotations: [],
- };
-
- render() {
- return (
-
-
-
-
- );
- }
-
- _getAnnotations = (region) => {
- return [{
- longitude: region.longitude,
- latitude: region.latitude,
- title: 'You Are Here',
- }];
- };
-
- _onRegionChange = (region) => {
- this.setState({
- mapRegionInput: region,
- });
- };
-
- _onRegionChangeComplete = (region) => {
- if (this.state.isFirstLoad) {
- this.setState({
- mapRegionInput: region,
- annotations: this._getAnnotations(region),
- isFirstLoad: false,
- });
- }
- };
-
- _onRegionInputChanged = (region) => {
- this.setState({
- mapRegion: region,
- mapRegionInput: region,
- annotations: this._getAnnotations(region),
- });
- };
-}
-
-class AnnotationExample extends React.Component {
- state = {
- isFirstLoad: true,
- annotations: [],
- mapRegion: undefined,
- };
-
- render() {
- if (this.state.isFirstLoad) {
- var onRegionChangeComplete = (region) => {
- this.setState({
- isFirstLoad: false,
- annotations: [{
- longitude: region.longitude,
- latitude: region.latitude,
- ...this.props.annotation,
- }],
- });
- };
- }
-
- return (
-
- );
- }
-}
-
-class DraggableAnnotationExample extends React.Component {
- state = {
- isFirstLoad: true,
- annotations: [],
- mapRegion: undefined,
- };
-
- createAnnotation = (longitude, latitude) => {
- return {
- longitude,
- latitude,
- draggable: true,
- onDragStateChange: (event) => {
- if (event.state === 'idle') {
- this.setState({
- annotations: [this.createAnnotation(event.longitude, event.latitude)],
- });
- }
- console.log('Drag state: ' + event.state);
- },
- };
- };
-
- render() {
- if (this.state.isFirstLoad) {
- var onRegionChangeComplete = (region) => {
- //When the MapView loads for the first time, we can create the annotation at the
- //region that was loaded.
- this.setState({
- isFirstLoad: false,
- annotations: [this.createAnnotation(region.longitude, region.latitude)],
- });
- };
- }
-
- return (
-
- );
- }
-}
-
-var styles = StyleSheet.create({
- map: {
- height: 150,
- margin: 10,
- borderWidth: 1,
- borderColor: '#000000',
- },
- row: {
- flexDirection: 'row',
- justifyContent: 'space-between',
- },
- textInput: {
- width: 150,
- height: 20,
- borderWidth: 0.5,
- borderColor: '#aaaaaa',
- fontSize: 13,
- padding: 4,
- },
- changeButton: {
- alignSelf: 'center',
- marginTop: 5,
- padding: 3,
- borderWidth: 0.5,
- borderColor: '#777777',
- },
-});
-
-exports.displayName = (undefined: ?string);
-exports.title = '';
-exports.description = 'Base component to display maps';
-exports.examples = [
- {
- title: 'Map',
- render() {
- return ;
- }
- },
- {
- title: 'showsUserLocation + followUserLocation',
- render() {
- return (
-
- );
- }
- },
- {
- title: 'Callout example',
- render() {
- return {
- alert('You Are Here');
- }}>
-
-
- ),
- }}/>;
- }
- },
- {
- title: 'Show callouts by default example',
- render() {
- return {
- alert('You Are Here');
- }}>
-
-
- ),
- }}
- showsAnnotationCallouts={true}
- />;
- }
- },
- {
- title: 'Annotation focus example',
- render() {
- return {
- alert('Annotation gets focus');
- },
- onBlur: () => {
- alert('Annotation lost focus');
- }
- }}/>;
- }
- },
- {
- title: 'Draggable pin',
- render() {
- return ;
- }
- },
- {
- title: 'Custom pin color',
- render() {
- return ;
- }
- },
- {
- title: 'Custom pin image',
- render() {
- return ;
- }
- },
- {
- title: 'Custom pin view',
- render() {
- return
-
- Thumbs Up!
-
-
- ,
- }}/>;
- }
- },
- {
- title: 'Custom overlay',
- render() {
- return ;
- }
- },
-];
diff --git a/Examples/UIExplorer/js/MultiColumnExample.js b/Examples/UIExplorer/js/MultiColumnExample.js
index d682c2d4196ff3..9b4477240f56ac 100644
--- a/Examples/UIExplorer/js/MultiColumnExample.js
+++ b/Examples/UIExplorer/js/MultiColumnExample.js
@@ -26,12 +26,12 @@
const React = require('react');
const ReactNative = require('react-native');
const {
+ FlatList,
StyleSheet,
Text,
View,
} = ReactNative;
-const FlatList = require('FlatList');
const UIExplorerPage = require('./UIExplorerPage');
const infoLog = require('infoLog');
@@ -97,9 +97,9 @@ class MultiColumnExample extends React.PureComponent {
to build
- * an app with composite navigation system.
- * @providesModule NavigationCardStack-NavigationHeader-Tabs-example
- */
-
-const {
- Component,
- PropTypes,
-} = React;
-
-const {
- NavigationExperimental,
- ScrollView,
- StyleSheet,
- Text,
- TouchableOpacity,
- View,
-} = ReactNative;
-
-const {
- CardStack: NavigationCardStack,
- Header: NavigationHeader,
- PropTypes: NavigationPropTypes,
- StateUtils: NavigationStateUtils,
-} = NavigationExperimental;
-
-// First Step.
-// Define what app navigation state will look like.
-function createAppNavigationState(): Object {
- return {
- // Three tabs.
- tabs: {
- index: 0,
- routes: [
- {key: 'apple'},
- {key: 'banana'},
- {key: 'orange'},
- ],
- },
- // Scenes for the `apple` tab.
- apple: {
- index: 0,
- routes: [{key: 'Apple Home'}],
- },
- // Scenes for the `banana` tab.
- banana: {
- index: 0,
- routes: [{key: 'Banana Home'}],
- },
- // Scenes for the `orange` tab.
- orange: {
- index: 0,
- routes: [{key: 'Orange Home'}],
- },
- };
-}
-
-// Next step.
-// Define what app navigation state shall be updated.
-function updateAppNavigationState(
- state: Object,
- action: Object,
-): Object {
- let {type} = action;
- if (type === 'BackAction') {
- type = 'pop';
- }
-
- switch (type) {
- case 'push': {
- // Push a route into the scenes stack.
- const route: Object = action.route;
- const {tabs} = state;
- const tabKey = tabs.routes[tabs.index].key;
- const scenes = state[tabKey];
- const nextScenes = NavigationStateUtils.push(scenes, route);
- if (scenes !== nextScenes) {
- return {
- ...state,
- [tabKey]: nextScenes,
- };
- }
- break;
- }
-
- case 'pop': {
- // Pops a route from the scenes stack.
- const {tabs} = state;
- const tabKey = tabs.routes[tabs.index].key;
- const scenes = state[tabKey];
- const nextScenes = NavigationStateUtils.pop(scenes);
- if (scenes !== nextScenes) {
- return {
- ...state,
- [tabKey]: nextScenes,
- };
- }
- break;
- }
-
- case 'selectTab': {
- // Switches the tab.
- const tabKey: string = action.tabKey;
- const tabs = NavigationStateUtils.jumpTo(state.tabs, tabKey);
- if (tabs !== state.tabs) {
- return {
- ...state,
- tabs,
- };
- }
- }
- }
- return state;
-}
-
-// Next step.
-// Defines a helper function that creates a HOC (higher-order-component)
-// which provides a function `navigate` through component props. The
-// `navigate` function will be used to invoke navigation changes.
-// This serves a convenient way for a component to navigate.
-function createAppNavigationContainer(ComponentClass) {
- const key = '_yourAppNavigationContainerNavigateCall';
-
- class Container extends Component {
- static contextTypes = {
- [key]: PropTypes.func,
- };
-
- static childContextTypes = {
- [key]: PropTypes.func.isRequired,
- };
-
- static propTypes = {
- navigate: PropTypes.func,
- };
-
- getChildContext(): Object {
- return {
- [key]: this.context[key] || this.props.navigate,
- };
- }
-
- render(): React.Element {
- const navigate = this.context[key] || this.props.navigate;
- return ;
- }
- }
-
- return Container;
-}
-
-// Next step.
-// Define a component for your application that owns the navigation state.
-class YourApplication extends Component {
-
- static propTypes = {
- onExampleExit: PropTypes.func,
- };
-
- // This sets up the initial navigation state.
- constructor(props, context) {
- super(props, context);
- // This sets up the initial navigation state.
- this.state = createAppNavigationState();
- this._navigate = this._navigate.bind(this);
- }
-
- render(): React.Element {
- // User your own navigator (see next step).
- return (
-
- );
- }
-
- // This public method is optional. If exists, the UI explorer will call it
- // the "back button" is pressed. Normally this is the cases for Android only.
- handleBackAction(): boolean {
- return this._navigate({type: 'pop'});
- }
-
- // This handles the navigation state changes. You're free and responsible
- // to define the API that changes that navigation state. In this exmaple,
- // we'd simply use a `updateAppNavigationState` to update the navigation
- // state.
- _navigate(action: Object): void {
- if (action.type === 'exit') {
- // Exits the example. `this.props.onExampleExit` is provided
- // by the UI Explorer.
- this.props.onExampleExit && this.props.onExampleExit();
- return;
- }
-
- const state = updateAppNavigationState(
- this.state,
- action,
- );
-
- // `updateAppNavigationState` (which uses NavigationStateUtils) gives you
- // back the same `state` if nothing has changed. You could use
- // that to avoid redundant re-rendering.
- if (this.state !== state) {
- this.setState(state);
- }
- }
-}
-
-// Next step.
-// Define your own controlled navigator.
-const YourNavigator = createAppNavigationContainer(class extends Component {
- static propTypes = {
- appNavigationState: PropTypes.shape({
- apple: NavigationPropTypes.navigationState.isRequired,
- banana: NavigationPropTypes.navigationState.isRequired,
- orange: NavigationPropTypes.navigationState.isRequired,
- tabs: NavigationPropTypes.navigationState.isRequired,
- }),
- navigate: PropTypes.func.isRequired,
- };
-
- // This sets up the methods (e.g. Pop, Push) for navigation.
- constructor(props: any, context: any) {
- super(props, context);
- this._back = this._back.bind(this);
- this._renderHeader = this._renderHeader.bind(this);
- this._renderScene = this._renderScene.bind(this);
- }
-
- // Now use the `NavigationCardStack` to render the scenes.
- render(): React.Element {
- const {appNavigationState} = this.props;
- const {tabs} = appNavigationState;
- const tabKey = tabs.routes[tabs.index].key;
- const scenes = appNavigationState[tabKey];
-
- return (
-
-
-
-
- );
- }
-
- // Render the header.
- // The detailed spec of `sceneProps` is defined at `NavigationTypeDefinition`
- // as type `NavigationSceneRendererProps`.
- _renderHeader(sceneProps: Object): React.Element {
- return (
-
- );
- }
-
- // Render a scene for route.
- // The detailed spec of `sceneProps` is defined at `NavigationTypeDefinition`
- // as type `NavigationSceneRendererProps`.
- _renderScene(sceneProps: Object): React.Element {
- return (
-
- );
- }
-
- _back() {
- this.props.navigate({type: 'pop'});
- }
-});
-
-// Next step.
-// Define your own header.
-const YourHeader = createAppNavigationContainer(class extends Component {
- static propTypes = {
- ...NavigationPropTypes.SceneRendererProps,
- navigate: PropTypes.func.isRequired,
- };
-
- constructor(props: Object, context: any) {
- super(props, context);
- this._back = this._back.bind(this);
- this._renderTitleComponent = this._renderTitleComponent.bind(this);
- }
-
- render(): React.Element {
- return (
-
- );
- }
-
- _back(): void {
- this.props.navigate({type: 'pop'});
- }
-
- _renderTitleComponent(props: Object): React.Element {
- return (
-
- {props.scene.route.key}
-
- );
- }
-});
-
-// Next step.
-// Define your own scene.
-const YourScene = createAppNavigationContainer(class extends Component {
- static propTypes = {
- ...NavigationPropTypes.SceneRendererProps,
- navigate: PropTypes.func.isRequired,
- };
-
- constructor(props: Object, context: any) {
- super(props, context);
- this._exit = this._exit.bind(this);
- this._popRoute = this._popRoute.bind(this);
- this._pushRoute = this._pushRoute.bind(this);
- }
-
- render(): React.Element {
- return (
-
-
-
-
-
- );
- }
-
- _pushRoute(): void {
- // Just push a route with a new unique key.
- const route = {key: '[' + this.props.scenes.length + ']-' + Date.now()};
- this.props.navigate({type: 'push', route});
- }
-
- _popRoute(): void {
- this.props.navigate({type: 'pop'});
- }
-
- _exit(): void {
- this.props.navigate({type: 'exit'});
- }
-});
-
-// Next step.
-// Define your own tabs.
-const YourTabs = createAppNavigationContainer(class extends Component {
- static propTypes = {
- navigationState: NavigationPropTypes.navigationState.isRequired,
- navigate: PropTypes.func.isRequired,
- };
-
- constructor(props: Object, context: any) {
- super(props, context);
- }
-
- render(): React.Element {
- return (
-
- {this.props.navigationState.routes.map(this._renderTab, this)}
-
- );
- }
-
- _renderTab(route: Object, index: number): React.Element {
- return (
-
- );
- }
-});
-
-// Next step.
-// Define your own Tab
-const YourTab = createAppNavigationContainer(class extends Component {
-
- static propTypes = {
- navigate: PropTypes.func.isRequired,
- route: NavigationPropTypes.navigationRoute.isRequired,
- selected: PropTypes.bool.isRequired,
- };
-
- constructor(props: Object, context: any) {
- super(props, context);
- this._onPress = this._onPress.bind(this);
- }
-
- render(): React.Element {
- const style = [styles.tabText];
- if (this.props.selected) {
- style.push(styles.tabSelected);
- }
- return (
-
-
- {this.props.route.key}
-
-
- );
- }
-
- _onPress() {
- this.props.navigate({type: 'selectTab', tabKey: this.props.route.key});
- }
-});
-
-const styles = StyleSheet.create({
- navigator: {
- flex: 1,
- },
- navigatorCardStack: {
- flex: 20,
- },
- tabs: {
- flex: 1,
- flexDirection: 'row',
- },
- tab: {
- alignItems: 'center',
- backgroundColor: '#fff',
- flex: 1,
- justifyContent: 'center',
- },
- tabText: {
- color: '#222',
- fontWeight: '500',
- },
- tabSelected: {
- color: 'blue',
- },
-});
-
-module.exports = YourApplication;
diff --git a/Examples/UIExplorer/js/NavigationExperimental/NavigationCardStack-NoGesture-example.js b/Examples/UIExplorer/js/NavigationExperimental/NavigationCardStack-NoGesture-example.js
deleted file mode 100644
index 4d62aaa9fbddc6..00000000000000
--- a/Examples/UIExplorer/js/NavigationExperimental/NavigationCardStack-NoGesture-example.js
+++ /dev/null
@@ -1,198 +0,0 @@
-/**
- * Copyright (c) 2013-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.
- *
- * 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 NavigationCardStack-NoGesture-example
- */
-'use strict';
-
-const NavigationExampleRow = require('./NavigationExampleRow');
-const React = require('react');
-const ReactNative = require('react-native');
-
-/**
- * Basic example that shows how to use to build
- * an app with controlled navigation system but without gestures.
- */
-const {
- NavigationExperimental,
- ScrollView,
- StyleSheet,
-} = ReactNative;
-
-const {
- CardStack: NavigationCardStack,
- StateUtils: NavigationStateUtils,
-} = NavigationExperimental;
-
-// Step 1:
-// Define a component for your application.
-class YourApplication extends React.Component {
-
- // This sets up the initial navigation state.
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- // This defines the initial navigation state.
- navigationState: {
- index: 0, // starts with first route focused.
- routes: [{key: 'Welcome'}], // starts with only one route.
- },
- };
-
- this._exit = this._exit.bind(this);
- this._onNavigationChange = this._onNavigationChange.bind(this);
- }
-
- // User your own navigator (see Step 2).
- render(): React.Element {
- return (
-
- );
- }
-
- // This handles the navigation state changes. You're free and responsible
- // to define the API that changes that navigation state. In this exmaple,
- // we'd simply use a `function(type: string)` to update the navigation state.
- _onNavigationChange(type: string): void {
- let {navigationState} = this.state;
- switch (type) {
- case 'push':
- // push a new route.
- const route = {key: 'route-' + Date.now()};
- navigationState = NavigationStateUtils.push(navigationState, route);
- break;
-
- case 'pop':
- navigationState = NavigationStateUtils.pop(navigationState);
- break;
- }
-
- // NavigationStateUtils gives you back the same `navigationState` if nothing
- // has changed. You could use that to avoid redundant re-rendering.
- if (this.state.navigationState !== navigationState) {
- this.setState({navigationState});
- }
- }
-
- // Exits the example. `this.props.onExampleExit` is provided
- // by the UI Explorer.
- _exit(): void {
- this.props.onExampleExit && this.props.onExampleExit();
- }
-
- // This public method is optional. If exists, the UI explorer will call it
- // the "back button" is pressed. Normally this is the cases for Android only.
- handleBackAction(): boolean {
- return this._onNavigationChange('pop');
- }
-}
-
-// Step 2:
-// Define your own controlled navigator.
-//
-// +------------+
-// +-+ |
-// +-+ | |
-// | | | |
-// | | | Active |
-// | | | Scene |
-// | | | |
-// +-+ | |
-// +-+ |
-// +------------+
-//
-class YourNavigator extends React.Component {
-
- // This sets up the methods (e.g. Pop, Push) for navigation.
- constructor(props: any, context: any) {
- super(props, context);
-
- this._onPushRoute = this.props.onNavigationChange.bind(null, 'push');
- this._onPopRoute = this.props.onNavigationChange.bind(null, 'pop');
-
- this._renderScene = this._renderScene.bind(this);
- }
-
- // Now use the `NavigationCardStack` to render the scenes.
- render(): React.Element {
- return (
-
- );
- }
-
- // Render a scene for route.
- // The detailed spec of `sceneProps` is defined at `NavigationTypeDefinition`
- // as type `NavigationSceneRendererProps`.
- _renderScene(sceneProps: Object): React.Element {
- return (
-
- );
- }
-}
-
-// Step 3:
-// Define your own scene.
-class YourScene extends React.Component {
- render() {
- return (
-
-
-
-
-
-
- );
- }
-}
-
-const styles = StyleSheet.create({
- navigator: {
- flex: 1,
- },
-});
-
-module.exports = YourApplication;
diff --git a/Examples/UIExplorer/js/NavigationExperimental/NavigationCardStack-example.js b/Examples/UIExplorer/js/NavigationExperimental/NavigationCardStack-example.js
deleted file mode 100644
index 1029644a02668f..00000000000000
--- a/Examples/UIExplorer/js/NavigationExperimental/NavigationCardStack-example.js
+++ /dev/null
@@ -1,196 +0,0 @@
-/**
- * Copyright (c) 2013-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.
- *
- * 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 NavigationCardStack-example
- */
-'use strict';
-
-const NavigationExampleRow = require('./NavigationExampleRow');
-const React = require('react');
-const ReactNative = require('react-native');
-
-/**
- * Basic example that shows how to use to build
- * an app with controlled navigation system.
- */
-const {
- NavigationExperimental,
- ScrollView,
- StyleSheet,
-} = ReactNative;
-
-const {
- CardStack: NavigationCardStack,
- StateUtils: NavigationStateUtils,
-} = NavigationExperimental;
-
-// Step 1:
-// Define a component for your application.
-class YourApplication extends React.Component {
-
- // This sets up the initial navigation state.
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- // This defines the initial navigation state.
- navigationState: {
- index: 0, // starts with first route focused.
- routes: [{key: 'Welcome'}], // starts with only one route.
- },
- };
-
- this._exit = this._exit.bind(this);
- this._onNavigationChange = this._onNavigationChange.bind(this);
- }
-
- // User your own navigator (see Step 2).
- render(): React.Element {
- return (
-
- );
- }
-
- // This handles the navigation state changes. You're free and responsible
- // to define the API that changes that navigation state. In this exmaple,
- // we'd simply use a `function(type: string)` to update the navigation state.
- _onNavigationChange(type: string): void {
- let {navigationState} = this.state;
- switch (type) {
- case 'push':
- // push a new route.
- const route = {key: 'route-' + Date.now()};
- navigationState = NavigationStateUtils.push(navigationState, route);
- break;
-
- case 'pop':
- navigationState = NavigationStateUtils.pop(navigationState);
- break;
- }
-
- // NavigationStateUtils gives you back the same `navigationState` if nothing
- // has changed. You could use that to avoid redundant re-rendering.
- if (this.state.navigationState !== navigationState) {
- this.setState({navigationState});
- }
- }
-
- // Exits the example. `this.props.onExampleExit` is provided
- // by the UI Explorer.
- _exit(): void {
- this.props.onExampleExit && this.props.onExampleExit();
- }
-
- // This public method is optional. If exists, the UI explorer will call it
- // the "back button" is pressed. Normally this is the cases for Android only.
- handleBackAction(): boolean {
- return this._onNavigationChange('pop');
- }
-}
-
-// Step 2:
-// Define your own controlled navigator.
-//
-// +------------+
-// +-+ |
-// +-+ | |
-// | | | |
-// | | | Active |
-// | | | Scene |
-// | | | |
-// +-+ | |
-// +-+ |
-// +------------+
-//
-class YourNavigator extends React.Component {
-
- // This sets up the methods (e.g. Pop, Push) for navigation.
- constructor(props: any, context: any) {
- super(props, context);
-
- this._onPushRoute = this.props.onNavigationChange.bind(null, 'push');
- this._onPopRoute = this.props.onNavigationChange.bind(null, 'pop');
-
- this._renderScene = this._renderScene.bind(this);
- }
-
- // Now use the `NavigationCardStack` to render the scenes.
- render(): React.Element {
- return (
-
- );
- }
-
- // Render a scene for route.
- // The detailed spec of `sceneProps` is defined at `NavigationTypeDefinition`
- // as type `NavigationSceneRendererProps`.
- _renderScene(sceneProps: Object): React.Element {
- return (
-
- );
- }
-}
-
-// Step 3:
-// Define your own scene.
-class YourScene extends React.Component {
- render() {
- return (
-
-
-
-
-
-
- );
- }
-}
-
-const styles = StyleSheet.create({
- navigator: {
- flex: 1,
- },
-});
-
-module.exports = YourApplication;
diff --git a/Examples/UIExplorer/js/NavigationExperimental/NavigationExampleRow.js b/Examples/UIExplorer/js/NavigationExperimental/NavigationExampleRow.js
deleted file mode 100644
index 5faf80427b672c..00000000000000
--- a/Examples/UIExplorer/js/NavigationExperimental/NavigationExampleRow.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Copyright (c) 2013-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.
- *
- * 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 NavigationExampleRow
- */
-'use strict';
-
-var React = require('react');
-var ReactNative = require('react-native');
-var {
- Text,
- PixelRatio,
- StyleSheet,
- View,
- TouchableHighlight,
-} = ReactNative;
-
-class NavigationExampleRow extends React.Component {
- render() {
- if (this.props.onPress) {
- return (
-
-
- {this.props.text}
-
-
- );
- }
- return (
-
-
- {this.props.text}
-
-
- );
- }
-}
-
-const styles = StyleSheet.create({
- row: {
- padding: 15,
- backgroundColor: 'white',
- borderBottomWidth: 1 / PixelRatio.get(),
- borderBottomColor: '#CDCDCD',
- },
- rowText: {
- fontSize: 17,
- },
- buttonText: {
- fontSize: 17,
- fontWeight: '500',
- },
-});
-
-module.exports = NavigationExampleRow;
diff --git a/Examples/UIExplorer/js/NavigationExperimental/NavigationExperimentalExample.js b/Examples/UIExplorer/js/NavigationExperimental/NavigationExperimentalExample.js
deleted file mode 100644
index 8b6da3af0249f2..00000000000000
--- a/Examples/UIExplorer/js/NavigationExperimental/NavigationExperimentalExample.js
+++ /dev/null
@@ -1,153 +0,0 @@
-/**
- * Copyright (c) 2013-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.
- *
- * 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 NavigationExperimentalExample
- */
-'use strict';
-
-const AsyncStorage = require('AsyncStorage');
-const NavigationExampleRow = require('./NavigationExampleRow');
-const React = require('react');
-const ScrollView = require('ScrollView');
-const StyleSheet = require('StyleSheet');
-const View = require('View');
-
-/*
- * Heads up! This file is not the real navigation example- only a utility to switch between them.
- *
- * To learn how to use the Navigation API, take a look at the following example files:
- */
-const EXAMPLES = {
- 'CardStack + Header + Tabs Example': require('./NavigationCardStack-NavigationHeader-Tabs-example'),
- 'CardStack Example': require('./NavigationCardStack-example'),
- 'CardStack Without Gestures Example': require('./NavigationCardStack-NoGesture-example'),
- 'Transitioner + Animated View Example': require('./NavigationTransitioner-AnimatedView-example'),
- 'Transitioner + Animated View Pager Example': require('./NavigationTransitioner-AnimatedView-pager-example'),
-};
-
-const EXAMPLE_STORAGE_KEY = 'NavigationExperimentalExample';
-
-class NavigationExperimentalExample extends React.Component {
- static title = 'Navigation (Experimental)';
- static description = 'Upcoming navigation APIs and animated navigation views';
- static external = true;
-
- state = {
- example: null,
- };
-
- componentDidMount() {
- AsyncStorage.getItem(EXAMPLE_STORAGE_KEY, (err, example) => {
- if (err || !example || !EXAMPLES[example]) {
- this.setState({
- example: 'menu',
- });
- return;
- }
- this.setState({
- example,
- });
- });
- }
-
- setExample = (example) => {
- this.setState({
- example,
- });
- AsyncStorage.setItem(EXAMPLE_STORAGE_KEY, example);
- };
-
- _renderMenu = () => {
- let exitRow = null;
- if (this.props.onExampleExit) {
- exitRow = (
-
- );
- }
- return (
-
-
- {this._renderExampleList()}
- {exitRow}
-
-
- );
- };
-
- _renderExampleList = () => {
- return Object.keys(EXAMPLES).map(exampleName => (
- {
- this.setExample(exampleName);
- }}
- />
- ));
- };
-
- _exitInnerExample = () => {
- this.setExample('menu');
- };
-
- handleBackAction = () => {
- const wasHandledByExample = (
- this.exampleRef &&
- this.exampleRef.handleBackAction &&
- this.exampleRef.handleBackAction()
- );
- if (wasHandledByExample) {
- return true;
- }
- if (this.state.example && this.state.example !== 'menu') {
- this._exitInnerExample();
- return true;
- }
- return false;
- };
-
- render() {
- if (this.state.example === 'menu') {
- return this._renderMenu();
- }
- if (EXAMPLES[this.state.example]) {
- const Component = EXAMPLES[this.state.example];
- return (
- { this.exampleRef = exampleRef; }}
- />
- );
- }
- return null;
- }
-}
-
-const styles = StyleSheet.create({
- menu: {
- backgroundColor: '#E9E9EF',
- flex: 1,
- marginTop: 20,
- },
-});
-
-module.exports = NavigationExperimentalExample;
diff --git a/Examples/UIExplorer/js/NavigationExperimental/NavigationTransitioner-AnimatedView-example.js b/Examples/UIExplorer/js/NavigationExperimental/NavigationTransitioner-AnimatedView-example.js
deleted file mode 100644
index b408251c0f7948..00000000000000
--- a/Examples/UIExplorer/js/NavigationExperimental/NavigationTransitioner-AnimatedView-example.js
+++ /dev/null
@@ -1,256 +0,0 @@
-/**
- * Copyright (c) 2013-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.
- *
- * 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.
- *
- * @flow
- * @providesModule NavigationTransitioner-AnimatedView-example
- */
-'use strict';
-
-const NavigationExampleRow = require('./NavigationExampleRow');
-const React = require('react');
-const ReactNative = require('react-native');
-
-/**
- * Basic example that shows how to use and
- * to build a stack of animated scenes that render the
- * navigation state.
- */
-
-
-import type {
- NavigationSceneRendererProps,
- NavigationState,
- NavigationTransitionProps,
- NavigationTransitionSpec,
-} from 'NavigationTypeDefinition';
-
-const {
- Component,
- PropTypes,
-} = React;
-
-const {
- Animated,
- Easing,
- NavigationExperimental,
- ScrollView,
- StyleSheet,
-} = ReactNative;
-
-const {
- PropTypes: NavigationPropTypes,
- StateUtils: NavigationStateUtils,
- Transitioner: NavigationTransitioner,
-} = NavigationExperimental;
-
-function reducer(state: ?NavigationState, action: any): NavigationState {
- if (!state) {
- return {
- index: 0,
- routes: [{key: 'route-1'}],
- };
- }
-
- switch (action) {
- case 'push':
- const route = {key: 'route-' + (state.routes.length + 1)};
- return NavigationStateUtils.push(state, route);
- case 'pop':
- return NavigationStateUtils.pop(state);
- }
- return state;
-}
-
-class Example extends Component {
- state: NavigationState;
- constructor(props: any, context: any) {
- super(props, context);
- this.state = reducer();
- }
-
- render(): React.Element {
- return (
- this._navigate(action)}
- />
- );
- }
-
- _navigate(action: any): boolean {
- if (action === 'exit') {
- // Exits the example. `this.props.onExampleExit` is provided
- // by the UI Explorer.
- this.props.onExampleExit && this.props.onExampleExit();
- return false;
- }
-
- const state = reducer(this.state, action);
- if (state === this.state) {
- return false;
- }
-
- this.setState(state);
- return true;
- }
-
- // This public method is optional. If exists, the UI explorer will call it
- // the "back button" is pressed. Normally this is the cases for Android only.
- handleBackAction(): boolean {
- return this._navigate('pop');
- }
-}
-
-class ExampleNavigator extends Component {
- props: {
- navigate: Function,
- navigationState: NavigationState,
- };
-
- static propTypes: {
- navigationState: NavigationPropTypes.navigationState.isRequired,
- navigate: PropTypes.func.isRequired,
- };
-
- render(): React.Element {
- return (
- this._render(transitionProps)}
- configureTransition={this._configureTransition}
- />
- );
- }
-
- _render(
- transitionProps: NavigationTransitionProps,
- ): Array> {
- return transitionProps.scenes.map((scene) => {
- const sceneProps = {
- ...transitionProps,
- scene,
- };
- return this._renderScene(sceneProps);
- });
- }
-
- _renderScene(
- sceneProps: NavigationSceneRendererProps,
- ): React.Element {
- return (
-
- );
- }
-
- _configureTransition(): NavigationTransitionSpec {
- const easing: any = Easing.inOut(Easing.ease);
- return {
- duration: 500,
- easing,
- };
- }
-}
-
-class ExampleScene extends Component {
- props: NavigationSceneRendererProps & {
- navigate: Function,
- };
-
- static propTypes = {
- ...NavigationPropTypes.SceneRendererProps,
- navigate: PropTypes.func.isRequired,
- };
-
- render(): React.Element {
- const {scene, navigate} = this.props;
- return (
-
-
-
- navigate('push')}
- />
- navigate('pop')}
- />
- navigate('exit')}
- />
-
-
- );
- }
-
- _getAnimatedStyle(): Object {
- const {
- layout,
- position,
- scene,
- } = this.props;
-
- const {
- index,
- } = scene;
-
- const inputRange = [index - 1, index, index + 1];
- const width = layout.initWidth;
- const translateX = position.interpolate({
- inputRange,
- outputRange: ([width, 0, -10]: Array),
- });
-
- return {
- transform: [
- { translateX },
- ],
- };
- }
-}
-
-const styles = StyleSheet.create({
- scene: {
- backgroundColor: '#E9E9EF',
- bottom: 0,
- flex: 1,
- left: 0,
- position: 'absolute',
- right: 0,
- shadowColor: 'black',
- shadowOffset: {width: 0, height: 0},
- shadowOpacity: 0.4,
- shadowRadius: 10,
- top: 0,
- },
- scrollView: {
- flex: 1,
- },
-});
-
-module.exports = Example;
diff --git a/Examples/UIExplorer/js/NavigationExperimental/NavigationTransitioner-AnimatedView-pager-example.js b/Examples/UIExplorer/js/NavigationExperimental/NavigationTransitioner-AnimatedView-pager-example.js
deleted file mode 100644
index 755a9b2df0cb94..00000000000000
--- a/Examples/UIExplorer/js/NavigationExperimental/NavigationTransitioner-AnimatedView-pager-example.js
+++ /dev/null
@@ -1,265 +0,0 @@
-/**
- * Copyright (c) 2013-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.
- *
- * 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.
- *
- * @flow
- * @providesModule NavigationTransitioner-AnimatedView-pager-example
- */
-'use strict';
-
-const NavigationExampleRow = require('./NavigationExampleRow');
-const React = require('react');
-const ReactNative = require('react-native');
-
-/**
- * Basic example that shows how to use and
- * to build a list of animated scenes that render the
- * navigation state.
- */
-
-import type {
- NavigationSceneRendererProps,
- NavigationState,
- NavigationTransitionProps,
-} from 'NavigationTypeDefinition';
-
-const {
- Component,
- PropTypes,
-} = React;
-
-const {
- Animated,
- NavigationExperimental,
- StyleSheet,
- Text,
- View,
-} = ReactNative;
-
-const {
- PropTypes: NavigationPropTypes,
- StateUtils: NavigationStateUtils,
- Transitioner: NavigationTransitioner,
- Card: NavigationCard,
-} = NavigationExperimental;
-
-const {
- PagerPanResponder: NavigationPagerPanResponder,
- PagerStyleInterpolator: NavigationPagerStyleInterpolator,
-} = NavigationCard;
-
-function reducer(state: ?NavigationState, action: any): NavigationState {
- if (!state) {
- return {
- index: 0,
- routes: [
- {key: 'Step 1', color: '#ff0000'},
- {key: 'Step 2', color: '#ff7f00'},
- {key: 'Step 3', color: '#ffff00'},
- {key: 'Step 4', color: '#00ff00'},
- {key: 'Step 5', color: '#0000ff'},
- {key: 'Step 6', color: '#4b0082'},
- {key: 'Step 7', color: '#8f00ff'},
- ],
- };
- }
-
- switch (action) {
- case 'back':
- return NavigationStateUtils.back(state);
- case 'forward':
- return NavigationStateUtils.forward(state);
- }
- return state;
-}
-
-class Example extends Component {
- state: NavigationState;
- constructor(props: any, context: any) {
- super(props, context);
- this.state = reducer();
- }
-
- render(): React.Element {
- return (
-
- this._navigate(action)}
- />
- this._navigate('exit')}
- />
-
- );
- }
-
- _navigate(action: string): boolean {
- if (action === 'exit') {
- // Exits the example. `this.props.onExampleExit` is provided
- // by the UI Explorer.
- this.props.onExampleExit && this.props.onExampleExit();
- return false;
- }
-
- const state = reducer(this.state, action);
- if (state === this.state) {
- return false;
- }
-
- this.setState(state);
- return true;
- }
-
- // This public method is optional. If exists, the UI explorer will call it
- // the "back button" is pressed. Normally this is the cases for Android only.
- handleBackAction(): boolean {
- return this._navigate('back');
- }
-}
-
-class ExampleNavigator extends Component {
- _render: Function;
- _renderScene: Function;
-
- props: {
- navigate: Function,
- navigationState: NavigationState,
- };
-
- static propTypes: {
- navigationState: NavigationPropTypes.navigationState.isRequired,
- navigate: PropTypes.func.isRequired,
- };
-
- constructor(props, context) {
- super(props, context);
- this._render = this._render.bind(this);
- this._renderScene = this._renderScene.bind(this);
- }
-
- render(): React.Element {
- return (
-
- );
- }
-
- _render(
- transitionProps: NavigationTransitionProps,
- ): React.Element {
- const scenes = transitionProps.scenes.map((scene) => {
- const sceneProps = {
- ...transitionProps,
- scene,
- };
- return this._renderScene(sceneProps);
- });
- return (
-
- {scenes}
-
- );
- }
-
- _renderScene(
- sceneProps: NavigationSceneRendererProps,
- ): React.Element {
- return (
-
- );
- }
-}
-
-class ExampleScene extends Component {
- props: NavigationSceneRendererProps & {
- navigate: Function,
- };
-
- static propTypes = {
- ...NavigationPropTypes.SceneRendererProps,
- navigate: PropTypes.func.isRequired,
- };
-
- render(): React.Element {
- const {scene, navigate} = this.props;
-
- const panHandlers = NavigationPagerPanResponder.forHorizontal({
- ...this.props,
- onNavigateBack: () => navigate('back'),
- onNavigateForward: () => navigate('forward'),
- });
-
- const route: any = scene.route;
- const style = [
- styles.scene,
- {backgroundColor: route.color},
- NavigationPagerStyleInterpolator.forHorizontal(this.props),
- ];
-
- return (
-
-
-
- {scene.route.key}
-
-
-
- );
- }
-}
-
-const styles = StyleSheet.create({
- example: {
- flex: 1,
- },
- navigator: {
- flex: 1,
- },
- scene: {
- backgroundColor: '#000',
- bottom: 0,
- flex: 1,
- left: 0,
- position: 'absolute',
- right: 0,
- top: 0,
- },
- heading: {
- alignItems : 'center',
- flex: 1,
- justifyContent: 'center',
- },
- headingText: {
- color: '#222',
- fontSize: 24,
- fontWeight: 'bold',
- },
-});
-
-module.exports = Example;
diff --git a/Examples/UIExplorer/js/SectionListExample.js b/Examples/UIExplorer/js/SectionListExample.js
index 41d3279f788ba0..08ed9572d8976e 100644
--- a/Examples/UIExplorer/js/SectionListExample.js
+++ b/Examples/UIExplorer/js/SectionListExample.js
@@ -26,12 +26,12 @@
const React = require('react');
const ReactNative = require('react-native');
const {
+ SectionList,
StyleSheet,
Text,
View,
} = ReactNative;
-const SectionList = require('SectionList');
const UIExplorerPage = require('./UIExplorerPage');
const infoLog = require('infoLog');
@@ -81,7 +81,9 @@ class SectionListExample extends React.PureComponent {
};
render() {
const filterRegex = new RegExp(String(this.state.filterText), 'i');
- const filter = (item) => (filterRegex.test(item.text) || filterRegex.test(item.title));
+ const filter = (item) => (
+ filterRegex.test(item.text) || filterRegex.test(item.title)
+ );
const filteredData = this.state.data.filter(filter);
return (
}
- ItemSeparatorComponent={() => }
+ SectionSeparatorComponent={() =>
+
+ }
+ ItemSeparatorComponent={() =>
+
+ }
enableVirtualization={this.state.virtualized}
onRefresh={() => alert('onRefresh: nothing to refresh :P')}
onViewableItemsChanged={this._onViewableItemsChanged}
@@ -117,8 +123,8 @@ class SectionListExample extends React.PureComponent {
{title: 'Item In Header Section', text: 'Section s1', key: '0'},
]},
{key: 's2', data: [
- {noImage: true, title: 'First item', text: 'Section s2', key: '0'},
- {noImage: true, title: 'Second item', text: 'Section s2', key: '1'},
+ {noImage: true, title: '1st item', text: 'Section s2', key: '0'},
+ {noImage: true, title: '2nd item', text: 'Section s2', key: '1'},
]},
{key: 'Filtered Items', data: filteredData},
]}
@@ -127,11 +133,18 @@ class SectionListExample extends React.PureComponent {
);
}
- _renderItemComponent = ({item}) => ;
- // This is called when items change viewability by scrolling into our out of the viewable area.
+ _renderItemComponent = ({item}) => (
+
+ );
+ // This is called when items change viewability by scrolling into our out of
+ // the viewable area.
_onViewableItemsChanged = (info: {
changed: Array<{
- key: string, isViewable: boolean, item: {columns: Array<*>}, index: ?number, section?: any
+ key: string,
+ isViewable: boolean,
+ item: {columns: Array<*>},
+ index: ?number,
+ section?: any
}>},
) => {
// Impressions can be logged here
diff --git a/Examples/UIExplorer/js/UIExplorerApp.android.js b/Examples/UIExplorer/js/UIExplorerApp.android.js
index 683f53b1342ab1..1e13a212ceb6bd 100644
--- a/Examples/UIExplorer/js/UIExplorerApp.android.js
+++ b/Examples/UIExplorer/js/UIExplorerApp.android.js
@@ -25,7 +25,7 @@
const AppRegistry = require('AppRegistry');
const AsyncStorage = require('AsyncStorage');
-const BackAndroid = require('BackAndroid');
+const BackHandler = require('BackHandler');
const Dimensions = require('Dimensions');
const DrawerLayoutAndroid = require('DrawerLayoutAndroid');
const Linking = require('Linking');
@@ -73,7 +73,7 @@ class UIExplorerApp extends React.Component {
state: UIExplorerNavigationState;
componentWillMount() {
- BackAndroid.addEventListener('hardwareBackPress', this._handleBackButtonPress);
+ BackHandler.addEventListener('hardwareBackPress', this._handleBackButtonPress);
}
componentDidMount() {
diff --git a/Examples/UIExplorer/js/UIExplorerApp.ios.js b/Examples/UIExplorer/js/UIExplorerApp.ios.js
index 802413c0468894..f57e4fbf8c35bb 100644
--- a/Examples/UIExplorer/js/UIExplorerApp.ios.js
+++ b/Examples/UIExplorer/js/UIExplorerApp.ios.js
@@ -24,6 +24,7 @@
'use strict';
const AsyncStorage = require('AsyncStorage');
+const BackHandler = require('BackHandler');
const Linking = require('Linking');
const React = require('react');
const ReactNative = require('react-native');
@@ -68,6 +69,10 @@ class UIExplorerApp extends React.Component {
props: Props;
state: UIExplorerNavigationState;
+ componentWillMount() {
+ BackHandler.addEventListener('hardwareBackPress', this._handleBack);
+ }
+
componentDidMount() {
Linking.getInitialURL().then((url) => {
AsyncStorage.getItem(APP_STATE_KEY, (err, storedString) => {
diff --git a/Examples/UIExplorer/js/UIExplorerExampleList.js b/Examples/UIExplorer/js/UIExplorerExampleList.js
index aea6911313c8c5..b805291832d9fc 100644
--- a/Examples/UIExplorer/js/UIExplorerExampleList.js
+++ b/Examples/UIExplorer/js/UIExplorerExampleList.js
@@ -201,6 +201,7 @@ const styles = StyleSheet.create({
backgroundColor: '#eeeeee',
},
sectionHeader: {
+ backgroundColor: '#eeeeee',
padding: 5,
fontWeight: '500',
fontSize: 11,
diff --git a/Examples/UIExplorer/js/UIExplorerList.android.js b/Examples/UIExplorer/js/UIExplorerList.android.js
index a5ac35b1a33a1f..09d81eb19c42ab 100644
--- a/Examples/UIExplorer/js/UIExplorerList.android.js
+++ b/Examples/UIExplorer/js/UIExplorerList.android.js
@@ -192,10 +192,6 @@ const APIExamples: Array = [
key: 'NativeAnimationsExample',
module: require('./NativeAnimationsExample'),
},
- {
- key: 'NavigationExperimentalExample',
- module: require('./NavigationExperimental/NavigationExperimentalExample'),
- },
{
key: 'NetInfoExample',
module: require('./NetInfoExample'),
diff --git a/Examples/UIExplorer/js/UIExplorerList.ios.js b/Examples/UIExplorer/js/UIExplorerList.ios.js
index 0c130d74fff5f5..9ac8aeeeb3fe2b 100644
--- a/Examples/UIExplorer/js/UIExplorerList.ios.js
+++ b/Examples/UIExplorer/js/UIExplorerList.ios.js
@@ -80,11 +80,6 @@ const ComponentExamples: Array = [
module: require('./ListViewPagingExample'),
supportsTVOS: true,
},
- {
- key: 'MapViewExample',
- module: require('./MapViewExample'),
- supportsTVOS: true,
- },
{
key: 'ModalExample',
module: require('./ModalExample'),
@@ -298,11 +293,6 @@ const APIExamples: Array = [
module: require('./NativeAnimationsExample'),
supportsTVOS: true,
},
- {
- key: 'NavigationExperimentalExample',
- module: require('./NavigationExperimental/NavigationExperimentalExample'),
- supportsTVOS: true,
- },
{
key: 'NetInfoExample',
module: require('./NetInfoExample'),
diff --git a/Libraries/Alert/AlertIOS.js b/Libraries/Alert/AlertIOS.js
index 500d0708d689cd..4a8143024a14ca 100644
--- a/Libraries/Alert/AlertIOS.js
+++ b/Libraries/Alert/AlertIOS.js
@@ -61,7 +61,7 @@ export type AlertButtonStyle = $Enum<{
* @property {Function=} onPress Callback function when button pressed
* @property {AlertButtonStyle=} style Button style
*/
-type ButtonsArray = Array<{
+export type ButtonsArray = Array<{
/**
* Button label
*/
diff --git a/Libraries/Animated/src/Animated.js b/Libraries/Animated/src/Animated.js
index a0c0482aea1589..1eacd03c48c66e 100644
--- a/Libraries/Animated/src/Animated.js
+++ b/Libraries/Animated/src/Animated.js
@@ -16,12 +16,22 @@ var AnimatedImplementation = require('AnimatedImplementation');
var Image = require('Image');
var Text = require('Text');
var View = require('View');
-var ScrollView = require('ScrollView');
-module.exports = {
- ...AnimatedImplementation,
+let AnimatedScrollView;
+
+const Animated = {
View: AnimatedImplementation.createAnimatedComponent(View),
Text: AnimatedImplementation.createAnimatedComponent(Text),
Image: AnimatedImplementation.createAnimatedComponent(Image),
- ScrollView: AnimatedImplementation.createAnimatedComponent(ScrollView),
+ get ScrollView() {
+ // Make this lazy to avoid circular reference.
+ if (!AnimatedScrollView) {
+ AnimatedScrollView = AnimatedImplementation.createAnimatedComponent(require('ScrollView'));
+ }
+ return AnimatedScrollView;
+ },
};
+
+Object.assign((Animated: Object), AnimatedImplementation);
+
+module.exports = ((Animated: any): (typeof AnimatedImplementation) & typeof Animated);
diff --git a/Libraries/Animated/src/AnimatedImplementation.js b/Libraries/Animated/src/AnimatedImplementation.js
index 550c8062db3fc7..e0860eced71cac 100644
--- a/Libraries/Animated/src/AnimatedImplementation.js
+++ b/Libraries/Animated/src/AnimatedImplementation.js
@@ -2151,9 +2151,80 @@ type EventConfig = {
useNativeDriver?: bool,
};
+function attachNativeEvent(viewRef: any, eventName: string, argMapping: Array) {
+ // Find animated values in `argMapping` and create an array representing their
+ // key path inside the `nativeEvent` object. Ex.: ['contentOffset', 'x'].
+ const eventMappings = [];
+
+ const traverse = (value, path) => {
+ if (value instanceof AnimatedValue) {
+ value.__makeNative();
+
+ eventMappings.push({
+ nativeEventPath: path,
+ animatedValueTag: value.__getNativeTag(),
+ });
+ } else if (typeof value === 'object') {
+ for (const key in value) {
+ traverse(value[key], path.concat(key));
+ }
+ }
+ };
+
+ invariant(
+ argMapping[0] && argMapping[0].nativeEvent,
+ 'Native driven events only support animated values contained inside `nativeEvent`.'
+ );
+
+ // Assume that the event containing `nativeEvent` is always the first argument.
+ traverse(argMapping[0].nativeEvent, []);
+
+ const viewTag = ReactNative.findNodeHandle(viewRef);
+
+ eventMappings.forEach((mapping) => {
+ NativeAnimatedAPI.addAnimatedEventToView(viewTag, eventName, mapping);
+ });
+
+ return {
+ detach() {
+ eventMappings.forEach((mapping) => {
+ NativeAnimatedAPI.removeAnimatedEventFromView(
+ viewTag,
+ eventName,
+ mapping.animatedValueTag,
+ );
+ });
+ },
+ };
+}
+
+function forkEvent(event: ?AnimatedEvent | ?Function, listener: Function): AnimatedEvent | Function {
+ if (!event) {
+ return listener;
+ } else if (event instanceof AnimatedEvent) {
+ event.__addListener(listener);
+ return event;
+ } else {
+ return (...args) => {
+ typeof event === 'function' && event(...args);
+ listener(...args);
+ };
+ }
+}
+
+function unforkEvent(event: ?AnimatedEvent | ?Function, listener: Function): void {
+ if (event && event instanceof AnimatedEvent) {
+ event.__removeListener(listener);
+ }
+}
+
class AnimatedEvent {
_argMapping: Array;
- _listener: ?Function;
+ _listeners: Array = [];
+ _callListeners: Function;
+ _attachedEvent: ?{
+ detach: () => void,
+ };
__isNative: bool;
constructor(
@@ -2161,7 +2232,11 @@ class AnimatedEvent {
config?: EventConfig = {}
) {
this._argMapping = argMapping;
- this._listener = config.listener;
+ if (config.listener) {
+ this.__addListener(config.listener);
+ }
+ this._callListeners = this._callListeners.bind(this);
+ this._attachedEvent = null;
this.__isNative = shouldUseNativeDriver(config);
if (__DEV__) {
@@ -2169,52 +2244,29 @@ class AnimatedEvent {
}
}
- __attach(viewRef, eventName) {
- invariant(this.__isNative, 'Only native driven events need to be attached.');
-
- // Find animated values in `argMapping` and create an array representing their
- // key path inside the `nativeEvent` object. Ex.: ['contentOffset', 'x'].
- const eventMappings = [];
-
- const traverse = (value, path) => {
- if (value instanceof AnimatedValue) {
- value.__makeNative();
-
- eventMappings.push({
- nativeEventPath: path,
- animatedValueTag: value.__getNativeTag(),
- });
- } else if (typeof value === 'object') {
- for (const key in value) {
- traverse(value[key], path.concat(key));
- }
- }
- };
-
- invariant(
- this._argMapping[0] && this._argMapping[0].nativeEvent,
- 'Native driven events only support animated values contained inside `nativeEvent`.'
- );
+ __addListener(callback: Function): void {
+ this._listeners.push(callback);
+ }
- // Assume that the event containing `nativeEvent` is always the first argument.
- traverse(this._argMapping[0].nativeEvent, []);
+ __removeListener(callback: Function): void {
+ this._listeners = this._listeners.filter((listener) => listener !== callback);
+ }
- const viewTag = ReactNative.findNodeHandle(viewRef);
+ __attach(viewRef, eventName) {
+ invariant(this.__isNative, 'Only native driven events need to be attached.');
- eventMappings.forEach((mapping) => {
- NativeAnimatedAPI.addAnimatedEventToView(viewTag, eventName, mapping);
- });
+ this._attachedEvent = attachNativeEvent(viewRef, eventName, this._argMapping);
}
__detach(viewTag, eventName) {
invariant(this.__isNative, 'Only native driven events need to be detached.');
- NativeAnimatedAPI.removeAnimatedEventFromView(viewTag, eventName);
+ this._attachedEvent && this._attachedEvent.detach();
}
__getHandler() {
if (this.__isNative) {
- return this._listener;
+ return this._callListeners;
}
return (...args) => {
@@ -2233,13 +2285,14 @@ class AnimatedEvent {
traverse(mapping, args[idx], 'arg' + idx);
});
}
-
- if (this._listener) {
- this._listener.apply(null, args);
- }
+ this._callListeners(...args);
};
}
+ _callListeners(...args) {
+ this._listeners.forEach(listener => listener(...args));
+ }
+
_validateMapping() {
const traverse = (recMapping, recEvt, key) => {
if (typeof recEvt === 'number') {
@@ -2582,5 +2635,18 @@ module.exports = {
*/
createAnimatedComponent,
+ /**
+ * Imperative API to attach an animated value to an event on a view. Prefer using
+ * `Animated.event` with `useNativeDrive: true` if possible.
+ */
+ attachNativeEvent,
+
+ /**
+ * Advanced imperative API for snooping on animated events that are passed in through props. Use
+ * values directly where possible.
+ */
+ forkEvent,
+ unforkEvent,
+
__PropsOnlyForTests: AnimatedProps,
};
diff --git a/Libraries/Animated/src/NativeAnimatedHelper.js b/Libraries/Animated/src/NativeAnimatedHelper.js
index 74c71c7dc54ba4..72c22ef63af1c8 100644
--- a/Libraries/Animated/src/NativeAnimatedHelper.js
+++ b/Libraries/Animated/src/NativeAnimatedHelper.js
@@ -93,9 +93,9 @@ const API = {
assertNativeAnimatedModule();
NativeAnimatedModule.addAnimatedEventToView(viewTag, eventName, eventMapping);
},
- removeAnimatedEventFromView(viewTag: ?number, eventName: string) {
+ removeAnimatedEventFromView(viewTag: ?number, eventName: string, animatedNodeTag: ?number) {
assertNativeAnimatedModule();
- NativeAnimatedModule.removeAnimatedEventFromView(viewTag, eventName);
+ NativeAnimatedModule.removeAnimatedEventFromView(viewTag, eventName, animatedNodeTag);
}
};
diff --git a/Libraries/Animated/src/__tests__/Animated-test.js b/Libraries/Animated/src/__tests__/Animated-test.js
index be7838ecb24167..fc313a8af0582b 100644
--- a/Libraries/Animated/src/__tests__/Animated-test.js
+++ b/Libraries/Animated/src/__tests__/Animated-test.js
@@ -353,6 +353,22 @@ describe('Animated tests', () => {
expect(listener.mock.calls.length).toBe(1);
expect(listener).toBeCalledWith({foo: 42});
});
+ it('should call forked event listeners', () => {
+ var value = new Animated.Value(0);
+ var listener = jest.fn();
+ var handler = Animated.event(
+ [{foo: value}],
+ {listener},
+ );
+ var listener2 = jest.fn();
+ var forkedHandler = Animated.forkEvent(handler, listener2);
+ forkedHandler({foo: 42});
+ expect(value.__getValue()).toBe(42);
+ expect(listener.mock.calls.length).toBe(1);
+ expect(listener).toBeCalledWith({foo: 42});
+ expect(listener2.mock.calls.length).toBe(1);
+ expect(listener2).toBeCalledWith({foo: 42});
+ });
});
describe('Animated Interactions', () => {
diff --git a/Libraries/CameraRoll/CameraRoll.js b/Libraries/CameraRoll/CameraRoll.js
index 581989684c078a..2a4c23f9721314 100644
--- a/Libraries/CameraRoll/CameraRoll.js
+++ b/Libraries/CameraRoll/CameraRoll.js
@@ -81,6 +81,7 @@ var getPhotosParamChecker = createStrictShapeTypeChecker({
* Shape of the return value of the `getPhotos` function.
*/
var getPhotosReturnChecker = createStrictShapeTypeChecker({
+ // $FlowFixMe(>=0.41.0)
edges: ReactPropTypes.arrayOf(createStrictShapeTypeChecker({
node: createStrictShapeTypeChecker({
type: ReactPropTypes.string.isRequired,
diff --git a/Libraries/Components/DatePicker/DatePickerIOS.ios.js b/Libraries/Components/DatePicker/DatePickerIOS.ios.js
index c8024048cd6254..bb001d7e166d12 100644
--- a/Libraries/Components/DatePicker/DatePickerIOS.ios.js
+++ b/Libraries/Components/DatePicker/DatePickerIOS.ios.js
@@ -35,6 +35,7 @@ type Event = Object;
* the user's change will be reverted immediately to reflect `props.date` as the
* source of truth.
*/
+// $FlowFixMe(>=0.41.0)
const DatePickerIOS = React.createClass({
// TOOD: Put a better type for _picker
_picker: (undefined: ?$FlowFixMe),
@@ -102,6 +103,7 @@ const DatePickerIOS = React.createClass({
this.props.onDateChange && this.props.onDateChange(
new Date(nativeTimeStamp)
);
+ // $FlowFixMe(>=0.41.0)
this.props.onChange && this.props.onChange(event);
// We expect the onChange* handlers to be in charge of updating our `date`
diff --git a/Libraries/Components/Keyboard/KeyboardAvoidingView.js b/Libraries/Components/Keyboard/KeyboardAvoidingView.js
index ec7d67187855ea..f20fb0323da9cd 100644
--- a/Libraries/Components/Keyboard/KeyboardAvoidingView.js
+++ b/Libraries/Components/Keyboard/KeyboardAvoidingView.js
@@ -52,6 +52,7 @@ const viewRef = 'VIEW';
* It is a component to solve the common problem of views that need to move out of the way of the virtual keyboard.
* It can automatically adjust either its position or bottom padding based on the position of the keyboard.
*/
+// $FlowFixMe(>=0.41.0)
const KeyboardAvoidingView = React.createClass({
mixins: [TimerMixin],
@@ -153,6 +154,7 @@ const KeyboardAvoidingView = React.createClass({
},
render(): React.Element {
+ // $FlowFixMe(>=0.41.0)
const {behavior, children, style, ...props} = this.props;
switch (behavior) {
diff --git a/Libraries/Components/MapView/MapView.js b/Libraries/Components/MapView/MapView.js
deleted file mode 100644
index 5b5a31282632c2..00000000000000
--- a/Libraries/Components/MapView/MapView.js
+++ /dev/null
@@ -1,563 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @providesModule MapView
- * @flow
- */
-'use strict';
-
-const ColorPropType = require('ColorPropType');
-const EdgeInsetsPropType = require('EdgeInsetsPropType');
-const Image = require('Image');
-const NativeMethodsMixin = require('NativeMethodsMixin');
-const React = require('React');
-const StyleSheet = require('StyleSheet');
-const View = require('View');
-
-const deprecatedPropType = require('deprecatedPropType');
-const processColor = require('processColor');
-const resolveAssetSource = require('resolveAssetSource');
-const requireNativeComponent = require('requireNativeComponent');
-
-type Event = Object;
-
-/**
- * State of an annotation on the map.
- */
-export type AnnotationDragState = $Enum<{
- /**
- * Annotation is not being touched.
- */
- idle: string,
- /**
- * Annotation dragging has began.
- */
- starting: string,
- /**
- * Annotation is being dragged.
- */
- dragging: string,
- /**
- * Annotation dragging is being canceled.
- */
- canceling: string,
- /**
- * Annotation dragging has ended.
- */
- ending: string,
-}>;
-
-/**
- * **IMPORTANT: This component is now DEPRECATED and will be removed
- * in January 2017 (React Native version 0.42). This component only supports
- * iOS.**
- *
- * **Please use
- * [react-native-maps](https://github.com/airbnb/react-native-maps) by Airbnb
- * instead of this component.** Our friends at Airbnb have done an amazing job
- * building a cross-platform `MapView` component that is more feature
- * complete. It is used extensively (over 9k installs / month).
- *
- * `MapView` is used to display embeddable maps and annotations using
- * `MKMapView`.
- *
- * ```
- * import React, { Component } from 'react';
- * import { MapView } from 'react-native';
- *
- * class MapMyRide extends Component {
- * render() {
- * return (
- *
- * );
- * }
- * }
- * ```
- *
- */
-
-const MapView = React.createClass({
-
- mixins: [NativeMethodsMixin],
-
- propTypes: {
- ...View.propTypes,
- /**
- * Used to style and layout the `MapView`.
- */
- style: View.propTypes.style,
-
- /**
- * If `true` the app will ask for the user's location and display it on
- * the map. Default value is `false`.
- *
- * **NOTE**: You'll need to add the `NSLocationWhenInUseUsageDescription`
- * key in Info.plist to enable geolocation, otherwise it will fail silently.
- */
- showsUserLocation: React.PropTypes.bool,
-
- /**
- * If `true` the map will follow the user's location whenever it changes.
- * Note that this has no effect unless `showsUserLocation` is enabled.
- * Default value is `true`.
- */
- followUserLocation: React.PropTypes.bool,
-
- /**
- * If `false` points of interest won't be displayed on the map.
- * Default value is `true`.
- */
- showsPointsOfInterest: React.PropTypes.bool,
-
- /**
- * If `false`, compass won't be displayed on the map.
- * Default value is `true`.
- */
- showsCompass: React.PropTypes.bool,
-
- /**
- * If `true` the map will show the callouts for all annotations without
- * the user having to click on the annotation.
- * Default value is `false`.
- */
- showsAnnotationCallouts: React.PropTypes.bool,
-
- /**
- * If `false` the user won't be able to pinch/zoom the map.
- * Default value is `true`.
- */
- zoomEnabled: React.PropTypes.bool,
-
- /**
- * When this property is set to `true` and a valid camera is associated with
- * the map, the camera's heading angle is used to rotate the plane of the
- * map around its center point.
- *
- * When this property is set to `false`, the
- * camera's heading angle is ignored and the map is always oriented so
- * that true north is situated at the top of the map view
- */
- rotateEnabled: React.PropTypes.bool,
-
- /**
- * When this property is set to `true` and a valid camera is associated
- * with the map, the camera's pitch angle is used to tilt the plane
- * of the map.
- *
- * When this property is set to `false`, the camera's pitch
- * angle is ignored and the map is always displayed as if the user
- * is looking straight down onto it.
- */
- pitchEnabled: React.PropTypes.bool,
-
- /**
- * If `false` the user won't be able to change the map region being displayed.
- * Default value is `true`.
- */
- scrollEnabled: React.PropTypes.bool,
-
- /**
- * The map type to be displayed.
- *
- * - `standard`: Standard road map (default).
- * - `satellite`: Satellite view.
- * - `hybrid`: Satellite view with roads and points of interest overlaid.
- */
- mapType: React.PropTypes.oneOf([
- 'standard',
- 'satellite',
- 'hybrid',
- ]),
-
- /**
- * The region to be displayed by the map.
- *
- * The region is defined by the center coordinates and the span of
- * coordinates to display.
- */
- region: React.PropTypes.shape({
- /**
- * Coordinates for the center of the map.
- */
- latitude: React.PropTypes.number.isRequired,
- longitude: React.PropTypes.number.isRequired,
-
- /**
- * Distance between the minimum and the maximum latitude/longitude
- * to be displayed.
- */
- latitudeDelta: React.PropTypes.number,
- longitudeDelta: React.PropTypes.number,
- }),
-
- /**
- * Map annotations with title and subtitle.
- */
- annotations: React.PropTypes.arrayOf(React.PropTypes.shape({
- /**
- * The location of the annotation.
- */
- latitude: React.PropTypes.number.isRequired,
- longitude: React.PropTypes.number.isRequired,
-
- /**
- * Whether the pin drop should be animated or not
- */
- animateDrop: React.PropTypes.bool,
-
- /**
- * Whether the pin should be draggable or not
- */
- draggable: React.PropTypes.bool,
-
- /**
- * Event that fires when the annotation drag state changes.
- */
- onDragStateChange: React.PropTypes.func,
-
- /**
- * Event that fires when the annotation gets was tapped by the user
- * and the callout view was displayed.
- */
- onFocus: React.PropTypes.func,
-
- /**
- * Event that fires when another annotation or the mapview itself
- * was tapped and a previously shown annotation will be closed.
- */
- onBlur: React.PropTypes.func,
-
- /**
- * Annotation title and subtile.
- */
- title: React.PropTypes.string,
- subtitle: React.PropTypes.string,
-
- /**
- * Callout views.
- */
- leftCalloutView: React.PropTypes.element,
- rightCalloutView: React.PropTypes.element,
- detailCalloutView: React.PropTypes.element,
-
- /**
- * The pin color. This can be any valid color string, or you can use one
- * of the predefined PinColors constants. Applies to both standard pins
- * and custom pin images.
- *
- * Note that on iOS 8 and earlier, only the standard PinColor constants
- * are supported for regular pins. For custom pin images, any tintColor
- * value is supported on all iOS versions.
- */
- tintColor: ColorPropType,
-
- /**
- * Custom pin image. This must be a static image resource inside the app.
- */
- image: Image.propTypes.source,
-
- /**
- * Custom pin view. If set, this replaces the pin or custom pin image.
- */
- view: React.PropTypes.element,
-
- /**
- * annotation id
- */
- id: React.PropTypes.string,
-
- /**
- * Deprecated. Use the left/right/detailsCalloutView props instead.
- */
- hasLeftCallout: deprecatedPropType(
- React.PropTypes.bool,
- 'Use `leftCalloutView` instead.'
- ),
- hasRightCallout: deprecatedPropType(
- React.PropTypes.bool,
- 'Use `rightCalloutView` instead.'
- ),
- onLeftCalloutPress: deprecatedPropType(
- React.PropTypes.func,
- 'Use `leftCalloutView` instead.'
- ),
- onRightCalloutPress: deprecatedPropType(
- React.PropTypes.func,
- 'Use `rightCalloutView` instead.'
- ),
- })),
-
- /**
- * Map overlays
- */
- overlays: React.PropTypes.arrayOf(React.PropTypes.shape({
- /**
- * Polyline coordinates
- */
- coordinates: React.PropTypes.arrayOf(React.PropTypes.shape({
- latitude: React.PropTypes.number.isRequired,
- longitude: React.PropTypes.number.isRequired
- })),
-
- /**
- * Line attributes
- */
- lineWidth: React.PropTypes.number,
- strokeColor: ColorPropType,
- fillColor: ColorPropType,
-
- /**
- * Overlay id
- */
- id: React.PropTypes.string
- })),
-
- /**
- * Maximum size of the area that can be displayed.
- */
- maxDelta: React.PropTypes.number,
-
- /**
- * Minimum size of the area that can be displayed.
- */
- minDelta: React.PropTypes.number,
-
- /**
- * Insets for the map's legal label, originally at bottom left of the map.
- */
- legalLabelInsets: EdgeInsetsPropType,
-
- /**
- * Callback that is called continuously when the user is dragging the map.
- */
- onRegionChange: React.PropTypes.func,
-
- /**
- * Callback that is called once, when the user is done moving the map.
- */
- onRegionChangeComplete: React.PropTypes.func,
-
- /**
- * Deprecated. Use annotation `onFocus` and `onBlur` instead.
- */
- onAnnotationPress: React.PropTypes.func,
-
- /**
- * @platform android
- */
- active: React.PropTypes.bool,
- },
-
- statics: {
- /**
- * Standard iOS MapView pin color constants, to be used with the
- * `annotation.tintColor` property. On iOS 8 and earlier these are the
- * only supported values when using regular pins. On iOS 9 and later
- * you are not obliged to use these, but they are useful for matching
- * the standard iOS look and feel.
- */
- PinColors: {
- RED: '#ff3b30',
- GREEN: '#4cd964',
- PURPLE: '#c969e0',
- },
- },
-
- render: function() {
- let children = [], {annotations, overlays, followUserLocation} = this.props;
- annotations = annotations && annotations.map((annotation: Object) => {
- let {
- id,
- image,
- tintColor,
- view,
- leftCalloutView,
- rightCalloutView,
- detailCalloutView,
- } = annotation;
-
- if (!view && image && tintColor) {
- view = ;
- image = undefined;
- }
- if (view) {
- if (image) {
- console.warn('`image` and `view` both set on annotation. Image will be ignored.');
- }
- var viewIndex = children.length;
- children.push(React.cloneElement(view, {
- // $FlowFixMe - An array of styles should be fine
- style: [styles.annotationView, view.props.style || {}]
- }));
- }
- if (leftCalloutView) {
- var leftCalloutViewIndex = children.length;
- children.push(React.cloneElement(leftCalloutView, {
- style: [styles.calloutView, leftCalloutView.props.style || {}]
- }));
- }
- if (rightCalloutView) {
- var rightCalloutViewIndex = children.length;
- children.push(React.cloneElement(rightCalloutView, {
- style: [styles.calloutView, rightCalloutView.props.style || {}]
- }));
- }
- if (detailCalloutView) {
- var detailCalloutViewIndex = children.length;
- children.push(React.cloneElement(detailCalloutView, {
- style: [styles.calloutView, detailCalloutView.props.style || {}]
- }));
- }
-
- const result = {
- ...annotation,
- tintColor: tintColor && processColor(tintColor),
- image,
- viewIndex,
- leftCalloutViewIndex,
- rightCalloutViewIndex,
- detailCalloutViewIndex,
- view: undefined,
- leftCalloutView: undefined,
- rightCalloutView: undefined,
- detailCalloutView: undefined,
- };
- result.id = id || encodeURIComponent(JSON.stringify(result));
- result.image = image && resolveAssetSource(image);
- return result;
- });
- overlays = overlays && overlays.map((overlay: Object) => {
- const {id, fillColor, strokeColor} = overlay;
- const result = {
- ...overlay,
- strokeColor: strokeColor && processColor(strokeColor),
- fillColor: fillColor && processColor(fillColor),
- };
- result.id = id || encodeURIComponent(JSON.stringify(result));
- return result;
- });
-
- const findByAnnotationId = (annotationId: string) => {
- if (!annotations) {
- return null;
- }
- for (let i = 0, l = annotations.length; i < l; i++) {
- if (annotations[i].id === annotationId) {
- return annotations[i];
- }
- }
- return null;
- };
-
- // TODO: these should be separate events, to reduce bridge traffic
- let onPress, onAnnotationDragStateChange, onAnnotationFocus, onAnnotationBlur;
- if (annotations) {
- onPress = (event: Event) => {
- if (event.nativeEvent.action === 'annotation-click') {
- // TODO: Remove deprecated onAnnotationPress API call later.
- this.props.onAnnotationPress &&
- this.props.onAnnotationPress(event.nativeEvent.annotation);
- } else if (event.nativeEvent.action === 'callout-click') {
- const annotation = findByAnnotationId(event.nativeEvent.annotationId);
- if (annotation) {
- // Pass the right function
- if (event.nativeEvent.side === 'left' && annotation.onLeftCalloutPress) {
- annotation.onLeftCalloutPress(event.nativeEvent);
- } else if (event.nativeEvent.side === 'right' && annotation.onRightCalloutPress) {
- annotation.onRightCalloutPress(event.nativeEvent);
- }
- }
- }
- };
- onAnnotationDragStateChange = (event: Event) => {
- const annotation = findByAnnotationId(event.nativeEvent.annotationId);
- if (annotation) {
- // Call callback
- annotation.onDragStateChange &&
- annotation.onDragStateChange(event.nativeEvent);
- }
- };
- onAnnotationFocus = (event: Event) => {
- const annotation = findByAnnotationId(event.nativeEvent.annotationId);
- if (annotation && annotation.onFocus) {
- annotation.onFocus(event.nativeEvent);
- }
- };
- onAnnotationBlur = (event: Event) => {
- const annotation = findByAnnotationId(event.nativeEvent.annotationId);
- if (annotation && annotation.onBlur) {
- annotation.onBlur(event.nativeEvent);
- }
- };
- }
-
- // TODO: these should be separate events, to reduce bridge traffic
- if (this.props.onRegionChange || this.props.onRegionChangeComplete) {
- var onChange = (event: Event) => {
- if (event.nativeEvent.continuous) {
- this.props.onRegionChange &&
- this.props.onRegionChange(event.nativeEvent.region);
- } else {
- this.props.onRegionChangeComplete &&
- this.props.onRegionChangeComplete(event.nativeEvent.region);
- }
- };
- }
-
- // followUserLocation defaults to true if showUserLocation is set
- if (followUserLocation === undefined) {
- followUserLocation = this.props.showUserLocation;
- }
-
- return (
-
- );
- },
-});
-
-const styles = StyleSheet.create({
- annotationView: {
- position: 'absolute',
- backgroundColor: 'transparent',
- },
- calloutView: {
- position: 'absolute',
- backgroundColor: 'white',
- },
-});
-
-const RCTMap = requireNativeComponent('RCTMap', MapView, {
- nativeOnly: {
- onAnnotationDragStateChange: true,
- onAnnotationFocus: true,
- onAnnotationBlur: true,
- onChange: true,
- onPress: true
- }
-});
-
-module.exports = MapView;
diff --git a/Libraries/Components/Navigation/NavigatorIOS.ios.js b/Libraries/Components/Navigation/NavigatorIOS.ios.js
index e9b43f3e78f9ab..90a6c37e9820c1 100644
--- a/Libraries/Components/Navigation/NavigatorIOS.ios.js
+++ b/Libraries/Components/Navigation/NavigatorIOS.ios.js
@@ -884,6 +884,7 @@ var NavigatorIOS = React.createClass({
=0.41.0)
vertical={this.props.vertical}
requestedTopOfStack={this.state.requestedTopOfStack}
onNavigationComplete={this._handleNavigationComplete}
@@ -914,6 +915,7 @@ var NavigatorIOS = React.createClass({
render: function() {
return (
+ // $FlowFixMe(>=0.41.0)
{this._renderNavigationStackItems()}
diff --git a/Libraries/Components/Picker/Picker.js b/Libraries/Components/Picker/Picker.js
index 7e2ad2a9fa7f85..1f8441814f87ab 100644
--- a/Libraries/Components/Picker/Picker.js
+++ b/Libraries/Components/Picker/Picker.js
@@ -69,6 +69,7 @@ class Picker extends React.Component {
mode: MODE_DIALOG,
};
+ // $FlowFixMe(>=0.41.0)
static propTypes = {
...View.propTypes,
style: pickerStyleType,
@@ -134,7 +135,7 @@ Picker.Item = class extends React.Component {
props: {
label: string,
value?: any,
- color?: $FlowFixMe,
+ color?: ColorPropType,
testID?: string,
};
diff --git a/Libraries/Components/ProgressViewIOS/ProgressViewIOS.ios.js b/Libraries/Components/ProgressViewIOS/ProgressViewIOS.ios.js
index 5d5aebe361b1b6..6ee4db298d08e3 100644
--- a/Libraries/Components/ProgressViewIOS/ProgressViewIOS.ios.js
+++ b/Libraries/Components/ProgressViewIOS/ProgressViewIOS.ios.js
@@ -24,6 +24,7 @@ var PropTypes = React.PropTypes;
/**
* Use `ProgressViewIOS` to render a UIProgressView on iOS.
*/
+// $FlowFixMe(>=0.41.0)
var ProgressViewIOS = React.createClass({
mixins: [NativeMethodsMixin],
diff --git a/Libraries/Components/RefreshControl/RefreshControl.js b/Libraries/Components/RefreshControl/RefreshControl.js
index 6622467709f2fd..a1eff537d8a2ef 100644
--- a/Libraries/Components/RefreshControl/RefreshControl.js
+++ b/Libraries/Components/RefreshControl/RefreshControl.js
@@ -70,6 +70,7 @@ if (Platform.OS === 'android') {
* __Note:__ `refreshing` is a controlled prop, this is why it needs to be set to true
* in the `onRefresh` function otherwise the refresh indicator will stop immediately.
*/
+// $FlowFixMe(>=0.41.0)
const RefreshControl = React.createClass({
statics: {
SIZE: RefreshLayoutConsts.SIZE,
diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js
index 68ac9b987a175a..0f167228b70d73 100644
--- a/Libraries/Components/ScrollView/ScrollView.js
+++ b/Libraries/Components/ScrollView/ScrollView.js
@@ -11,6 +11,7 @@
*/
'use strict';
+const Animated = require('Animated');
const ColorPropType = require('ColorPropType');
const EdgeInsetsPropType = require('EdgeInsetsPropType');
const Platform = require('Platform');
@@ -18,6 +19,7 @@ const PointPropType = require('PointPropType');
const React = require('React');
const ReactNative = require('ReactNative');
const ScrollResponder = require('ScrollResponder');
+const ScrollViewStickyHeader = require('ScrollViewStickyHeader');
const StyleSheet = require('StyleSheet');
const StyleSheetPropType = require('StyleSheetPropType');
const View = require('View');
@@ -46,20 +48,26 @@ const requireNativeComponent = require('requireNativeComponent');
* view from becoming the responder.
*
*
- * `` vs `` - which one to use?
- * ScrollView simply renders all its react child components at once. That
+ * `` vs [``](/react-native/docs/flatlist.html) - which one to use?
+ *
+ * `ScrollView` simply renders all its react child components at once. That
* makes it very easy to understand and use.
+ *
* On the other hand, this has a performance downside. Imagine you have a very
- * long list of items you want to display, worth of couple of your ScrollView’s
- * heights. Creating JS components and native views upfront for all its items,
- * which may not even be shown, will contribute to slow rendering of your
- * screen and increased memory usage.
+ * long list of items you want to display, maybe several screens worth of
+ * content. Creating JS components and native views for everythign all at once,
+ * much of which may not even be shown, will contribute to slow rendering and
+ * increased memory usage.
*
- * This is where ListView comes into play. ListView renders items lazily,
- * just when they are about to appear. This laziness comes at cost of a more
- * complicated API, which is worth it unless you are rendering a small fixed
- * set of items.
+ * This is where `FlatList` comes into play. `FlatList` renders items lazily,
+ * just when they are about to appear, and removes items that scroll way off
+ * screen to save memory and processing time.
+ *
+ * `FlatList` is also handy if you want to render separators between your items,
+ * multiple columns, infinite scroll loading, or any number of other features it
+ * supports out of the box.
*/
+// $FlowFixMe(>=0.41.0)
const ScrollView = React.createClass({
propTypes: {
...View.propTypes,
@@ -157,8 +165,8 @@ const ScrollView = React.createClass({
/**
* The style of the scroll indicators.
* - `default` (the default), same as `black`.
- * - `black`, scroll indicator is black. This style is good against a white content background.
- * - `white`, scroll indicator is white. This style is good against a black content background.
+ * - `black`, scroll indicator is black. This style is good against a light background.
+ * - `white`, scroll indicator is white. This style is good against a dark background.
* @platform ios
*/
indicatorStyle: PropTypes.oneOf([
@@ -227,7 +235,8 @@ const ScrollView = React.createClass({
/**
* Called when scrollable content view of the ScrollView changes.
*
- * Handler function is passed the content width and content height as parameters: `(contentWidth, contentHeight)`
+ * Handler function is passed the content width and content height as parameters:
+ * `(contentWidth, contentHeight)`
*
* It's implemented using onLayout handler attached to the content container
* which this ScrollView renders.
@@ -286,7 +295,6 @@ const ScrollView = React.createClass({
* `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the
* top of the scroll view. This property is not supported in conjunction
* with `horizontal={true}`.
- * @platform ios
*/
stickyHeaderIndices: PropTypes.arrayOf(PropTypes.number),
style: StyleSheetPropType(ViewStylePropTypes),
@@ -372,10 +380,33 @@ const ScrollView = React.createClass({
mixins: [ScrollResponder.Mixin],
+ _scrollAnimatedValue: (new Animated.Value(0): Animated.Value),
+ _scrollAnimatedValueAttachment: (null: ?{detach: () => void}),
+ _stickyHeaderRefs: (new Map(): Map),
+
getInitialState: function() {
return this.scrollResponderMixinGetInitialState();
},
+ componentWillMount: function() {
+ this._scrollAnimatedValue = new Animated.Value(0);
+ this._stickyHeaderRefs = new Map();
+ },
+
+ componentDidMount: function() {
+ this._updateAnimatedNodeAttachment();
+ },
+
+ componentDidUpdate: function() {
+ this._updateAnimatedNodeAttachment();
+ },
+
+ componentWillUnmount: function() {
+ if (this._scrollAnimatedValueAttachment) {
+ this._scrollAnimatedValueAttachment.detach();
+ }
+ },
+
setNativeProps: function(props: Object) {
this._scrollViewRef && this._scrollViewRef.setNativeProps(props);
},
@@ -406,7 +437,7 @@ const ScrollView = React.createClass({
* `scrollTo({x: 0; y: 0; animated: true})`
*
* Note: The weird function signature is due to the fact that, for historical reasons,
- * the function also accepts separate arguments as as alternative to the options object.
+ * the function also accepts separate arguments as an alternative to the options object.
* This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
*/
scrollTo: function(
@@ -415,11 +446,14 @@ const ScrollView = React.createClass({
animated?: boolean
) {
if (typeof y === 'number') {
- console.warn('`scrollTo(y, x, animated)` is deprecated. Use `scrollTo({x: 5, y: 5, animated: true})` instead.');
+ console.warn('`scrollTo(y, x, animated)` is deprecated. Use `scrollTo({x: 5, y: 5, ' +
+ 'animated: true})` instead.');
} else {
({x, y, animated} = y || {});
}
- this.getScrollResponder().scrollResponderScrollTo({x: x || 0, y: y || 0, animated: animated !== false});
+ this.getScrollResponder().scrollResponderScrollTo(
+ {x: x || 0, y: y || 0, animated: animated !== false}
+ );
},
/**
@@ -448,6 +482,40 @@ const ScrollView = React.createClass({
this.scrollTo({x, y, animated: false});
},
+ _updateAnimatedNodeAttachment: function() {
+ if (this.props.stickyHeaderIndices && this.props.stickyHeaderIndices.length > 0) {
+ if (!this._scrollAnimatedValueAttachment) {
+ this._scrollAnimatedValueAttachment = Animated.attachNativeEvent(
+ this._scrollViewRef,
+ 'onScroll',
+ [{nativeEvent: {contentOffset: {y: this._scrollAnimatedValue}}}]
+ );
+ }
+ } else {
+ if (this._scrollAnimatedValueAttachment) {
+ this._scrollAnimatedValueAttachment.detach();
+ }
+ }
+ },
+
+ _setStickyHeaderRef: function(index, ref) {
+ this._stickyHeaderRefs.set(index, ref);
+ },
+
+ _onStickyHeaderLayout: function(index, event) {
+ if (!this.props.stickyHeaderIndices) {
+ return;
+ }
+
+ const previousHeaderIndex = this.props.stickyHeaderIndices[
+ this.props.stickyHeaderIndices.indexOf(index) - 1
+ ];
+ if (previousHeaderIndex != null) {
+ const previousHeader = this._stickyHeaderRefs.get(previousHeaderIndex);
+ previousHeader && previousHeader.setNextHeaderY(event.nativeEvent.layout.y);
+ }
+ },
+
_handleScroll: function(e: Object) {
if (__DEV__) {
if (this.props.onScroll && this.props.scrollEventThrottle == null && Platform.OS === 'ios') {
@@ -531,14 +599,36 @@ const ScrollView = React.createClass({
};
}
- const contentContainer =
+ const {stickyHeaderIndices} = this.props;
+ const hasStickyHeaders = stickyHeaderIndices && stickyHeaderIndices.length > 0;
+ const children = stickyHeaderIndices && hasStickyHeaders ?
+ React.Children.toArray(this.props.children).map((child, index) => {
+ const stickyHeaderIndex = stickyHeaderIndices.indexOf(index);
+ if (child && stickyHeaderIndex >= 0) {
+ return (
+ this._setStickyHeaderRef(index, ref)}
+ onLayout={(event) => this._onStickyHeaderLayout(index, event)}
+ scrollAnimatedValue={this._scrollAnimatedValue}>
+ {child}
+
+ );
+ } else {
+ return child;
+ }
+ }) :
+ this.props.children;
+ const contentContainer =
- {this.props.children}
+ {children}
;
const alwaysBounceHorizontal =
@@ -560,23 +650,25 @@ const ScrollView = React.createClass({
// Override the onContentSizeChange from props, since this event can
// bubble up from TextInputs
onContentSizeChange: null,
- onTouchStart: this.scrollResponderHandleTouchStart,
- onTouchMove: this.scrollResponderHandleTouchMove,
- onTouchEnd: this.scrollResponderHandleTouchEnd,
- onScrollBeginDrag: this.scrollResponderHandleScrollBeginDrag,
- onScrollEndDrag: this.scrollResponderHandleScrollEndDrag,
onMomentumScrollBegin: this.scrollResponderHandleMomentumScrollBegin,
onMomentumScrollEnd: this.scrollResponderHandleMomentumScrollEnd,
- onStartShouldSetResponder: this.scrollResponderHandleStartShouldSetResponder,
- onStartShouldSetResponderCapture: this.scrollResponderHandleStartShouldSetResponderCapture,
- onScrollShouldSetResponder: this.scrollResponderHandleScrollShouldSetResponder,
- onScroll: this._handleScroll,
onResponderGrant: this.scrollResponderHandleResponderGrant,
- onResponderTerminationRequest: this.scrollResponderHandleTerminationRequest,
- onResponderTerminate: this.scrollResponderHandleTerminate,
- onResponderRelease: this.scrollResponderHandleResponderRelease,
onResponderReject: this.scrollResponderHandleResponderReject,
- sendMomentumEvents: (this.props.onMomentumScrollBegin || this.props.onMomentumScrollEnd) ? true : false,
+ onResponderRelease: this.scrollResponderHandleResponderRelease,
+ onResponderTerminate: this.scrollResponderHandleTerminate,
+ onResponderTerminationRequest: this.scrollResponderHandleTerminationRequest,
+ onScroll: this._handleScroll,
+ onScrollBeginDrag: this.scrollResponderHandleScrollBeginDrag,
+ onScrollEndDrag: this.scrollResponderHandleScrollEndDrag,
+ onScrollShouldSetResponder: this.scrollResponderHandleScrollShouldSetResponder,
+ onStartShouldSetResponder: this.scrollResponderHandleStartShouldSetResponder,
+ onStartShouldSetResponderCapture: this.scrollResponderHandleStartShouldSetResponderCapture,
+ onTouchEnd: this.scrollResponderHandleTouchEnd,
+ onTouchMove: this.scrollResponderHandleTouchMove,
+ onTouchStart: this.scrollResponderHandleTouchStart,
+ scrollEventThrottle: hasStickyHeaders ? 1 : this.props.scrollEventThrottle,
+ sendMomentumEvents: (this.props.onMomentumScrollBegin || this.props.onMomentumScrollEnd) ?
+ true : false,
};
const { decelerationRate } = this.props;
@@ -585,12 +677,14 @@ const ScrollView = React.createClass({
}
const refreshControl = this.props.refreshControl;
+
if (refreshControl) {
if (Platform.OS === 'ios') {
// On iOS the RefreshControl is a child of the ScrollView.
+ // tvOS lacks native support for RefreshControl, so don't include it in that case
return (
- {refreshControl}
+ {Platform.isTVOS ? null : refreshControl}
{contentContainer}
);
@@ -636,17 +730,25 @@ const styles = StyleSheet.create({
},
});
-let nativeOnlyProps, AndroidScrollView, AndroidHorizontalScrollView, RCTScrollView, RCTScrollContentView;
+let nativeOnlyProps,
+ AndroidScrollView,
+ AndroidHorizontalScrollView,
+ RCTScrollView,
+ RCTScrollContentView;
if (Platform.OS === 'android') {
nativeOnlyProps = {
nativeOnly: {
sendMomentumEvents: true,
}
};
- AndroidScrollView = requireNativeComponent('RCTScrollView', ScrollView, nativeOnlyProps);
+ AndroidScrollView = requireNativeComponent(
+ 'RCTScrollView',
+ (ScrollView: ReactClass),
+ nativeOnlyProps
+ );
AndroidHorizontalScrollView = requireNativeComponent(
'AndroidHorizontalScrollView',
- ScrollView,
+ (ScrollView: ReactClass),
nativeOnlyProps
);
} else if (Platform.OS === 'ios') {
@@ -658,7 +760,11 @@ if (Platform.OS === 'android') {
onScrollEndDrag: true,
}
};
- RCTScrollView = requireNativeComponent('RCTScrollView', ScrollView, nativeOnlyProps);
+ RCTScrollView = requireNativeComponent(
+ 'RCTScrollView',
+ (ScrollView: ReactClass),
+ nativeOnlyProps,
+ );
RCTScrollContentView = requireNativeComponent('RCTScrollContentView', View);
}
diff --git a/Libraries/Components/ScrollView/ScrollViewStickyHeader.js b/Libraries/Components/ScrollView/ScrollViewStickyHeader.js
new file mode 100644
index 00000000000000..da640b56090adc
--- /dev/null
+++ b/Libraries/Components/ScrollView/ScrollViewStickyHeader.js
@@ -0,0 +1,109 @@
+/**
+ * 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 ScrollViewStickyHeader
+ * @flow
+ */
+'use strict';
+
+const Animated = require('Animated');
+const React = require('React');
+const StyleSheet = require('StyleSheet');
+
+type Props = {
+ children?: React.Element<*>,
+ scrollAnimatedValue: Animated.Value,
+ onLayout: (event: Object) => void,
+};
+
+class ScrollViewStickyHeader extends React.Component {
+ props: Props;
+ state = {
+ measured: false,
+ layoutY: 0,
+ layoutHeight: 0,
+ nextHeaderLayoutY: (null: ?number),
+ };
+
+ setNextHeaderY(y: number) {
+ this.setState({ nextHeaderLayoutY: y });
+ }
+
+ _onLayout = (event) => {
+ this.setState({
+ measured: true,
+ layoutY: event.nativeEvent.layout.y,
+ layoutHeight: event.nativeEvent.layout.height,
+ });
+
+ this.props.onLayout(event);
+ const child = React.Children.only(this.props.children);
+ if (child.props.onLayout) {
+ child.props.onLayout(event);
+ }
+ };
+
+ render() {
+ const {measured, layoutHeight, layoutY, nextHeaderLayoutY} = this.state;
+
+ let translateY;
+ if (measured) {
+ // The interpolation looks like:
+ // - Negative scroll: no translation
+ // - From 0 to the y of the header: no translation. This will cause the header
+ // to scroll normally until it reaches the top of the scroll view.
+ // - From header y to when the next header y hits the bottom edge of the header: translate
+ // equally to scroll. This will cause the header to stay at the top of the scroll view.
+ // - Past the collision with the next header y: no more translation. This will cause the
+ // header to continue scrolling up and make room for the next sticky header.
+ // In the case that there is no next header just translate equally to
+ // scroll indefinetly.
+ const inputRange = [-1, 0, layoutY];
+ const outputRange: Array = [0, 0, 0];
+ if (nextHeaderLayoutY != null) {
+ const collisionPoint = nextHeaderLayoutY - layoutHeight;
+ inputRange.push(collisionPoint, collisionPoint + 1);
+ outputRange.push(collisionPoint - layoutY, collisionPoint - layoutY);
+ } else {
+ inputRange.push(layoutY + 1);
+ outputRange.push(1);
+ }
+ translateY = this.props.scrollAnimatedValue.interpolate({
+ inputRange,
+ outputRange,
+ });
+ } else {
+ translateY = 0;
+ }
+
+ const child = React.Children.only(this.props.children);
+
+ return (
+
+ {React.cloneElement(child, {
+ style: styles.fill, // We transfer the child style to the wrapper.
+ onLayout: undefined, // we call this manually through our this._onLayout
+ })}
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ header: {
+ zIndex: 10,
+ },
+ fill: {
+ flex: 1,
+ },
+});
+
+module.exports = ScrollViewStickyHeader;
diff --git a/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js b/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js
index 01f4c42ddc7142..200e198e1c025c 100644
--- a/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js
+++ b/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js
@@ -49,6 +49,7 @@ type Event = Object;
* />
* ````
*/
+// $FlowFixMe(>=0.41.0)
var SegmentedControlIOS = React.createClass({
mixins: [NativeMethodsMixin],
diff --git a/Libraries/Components/Slider/Slider.js b/Libraries/Components/Slider/Slider.js
index 23ea68bd278093..3fbe92fc5f38af 100644
--- a/Libraries/Components/Slider/Slider.js
+++ b/Libraries/Components/Slider/Slider.js
@@ -29,6 +29,7 @@ type Event = Object;
/**
* A component used to select a single value from a range of values.
*/
+// $FlowFixMe(>=0.41.0)
var Slider = React.createClass({
mixins: [NativeMethodsMixin],
diff --git a/Libraries/Components/StatusBar/StatusBar.js b/Libraries/Components/StatusBar/StatusBar.js
index f1712b4a52d481..1a4eb6a9722129 100644
--- a/Libraries/Components/StatusBar/StatusBar.js
+++ b/Libraries/Components/StatusBar/StatusBar.js
@@ -274,8 +274,6 @@ class StatusBar extends React.Component {
translucent: React.PropTypes.bool,
/**
* Sets the color of the status bar text.
- *
- * @platform ios
*/
barStyle: React.PropTypes.oneOf([
'default',
diff --git a/Libraries/Components/Switch/Switch.js b/Libraries/Components/Switch/Switch.js
index ca1e1295cadced..f614164cab8577 100644
--- a/Libraries/Components/Switch/Switch.js
+++ b/Libraries/Components/Switch/Switch.js
@@ -38,6 +38,7 @@ type DefaultProps = {
* @keyword checkbox
* @keyword toggle
*/
+// $FlowFixMe(>=0.41.0)
var Switch = React.createClass({
propTypes: {
...View.propTypes,
diff --git a/Libraries/Components/TabBarIOS/TabBarIOS.android.js b/Libraries/Components/TabBarIOS/TabBarIOS.android.js
index c582903a760478..d9efee3ff322b1 100644
--- a/Libraries/Components/TabBarIOS/TabBarIOS.android.js
+++ b/Libraries/Components/TabBarIOS/TabBarIOS.android.js
@@ -7,15 +7,19 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule TabBarIOS
+ * @flow
*/
'use strict';
-var React = require('React');
-var View = require('View');
-var StyleSheet = require('StyleSheet');
+const React = require('React');
+const StyleSheet = require('StyleSheet');
+const TabBarItemIOS = require('TabBarItemIOS');
+const View = require('View');
class DummyTabBarIOS extends React.Component {
+ static Item = TabBarItemIOS;
+
render() {
return (
@@ -25,7 +29,7 @@ class DummyTabBarIOS extends React.Component {
}
}
-var styles = StyleSheet.create({
+const styles = StyleSheet.create({
tabGroup: {
flex: 1,
}
diff --git a/Libraries/Components/TabBarIOS/TabBarIOS.ios.js b/Libraries/Components/TabBarIOS/TabBarIOS.ios.js
index 283e9928f50b54..5ccab62e11fe7d 100644
--- a/Libraries/Components/TabBarIOS/TabBarIOS.ios.js
+++ b/Libraries/Components/TabBarIOS/TabBarIOS.ios.js
@@ -32,6 +32,7 @@ class TabBarIOS extends React.Component {
static Item = TabBarItemIOS;
+ // $FlowFixMe(>=0.41.0)
static propTypes = {
...View.propTypes,
style: View.propTypes.style,
diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js
index 1c70e412ae4110..e9b2de7d5474e3 100644
--- a/Libraries/Components/TextInput/TextInput.js
+++ b/Libraries/Components/TextInput/TextInput.js
@@ -168,6 +168,7 @@ const DataDetectorTypes = [
* or control this param programmatically with native code.
*
*/
+// $FlowFixMe(>=0.41.0)
const TextInput = React.createClass({
statics: {
/* TODO(brentvatne) docs are needed for this */
diff --git a/Libraries/Components/Touchable/TouchableBounce.js b/Libraries/Components/Touchable/TouchableBounce.js
index 1abedf4e284e20..333cf6cbf79a9b 100644
--- a/Libraries/Components/Touchable/TouchableBounce.js
+++ b/Libraries/Components/Touchable/TouchableBounce.js
@@ -33,6 +33,7 @@ var PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
* `TouchableMixin` expects us to implement some abstract methods to handle
* interesting interactions such as `handleTouchablePress`.
*/
+// $FlowFixMe(>=0.41.0)
var TouchableBounce = React.createClass({
mixins: [Touchable.Mixin, NativeMethodsMixin],
@@ -148,7 +149,9 @@ var TouchableBounce = React.createClass({
onResponderMove={this.touchableHandleResponderMove}
onResponderRelease={this.touchableHandleResponderRelease}
onResponderTerminate={this.touchableHandleResponderTerminate}>
- {this.props.children}
+ {
+ // $FlowFixMe(>=0.41.0)
+ this.props.children}
{Touchable.renderDebugView({color: 'orange', hitSlop: this.props.hitSlop})}
);
diff --git a/Libraries/Components/Touchable/TouchableNativeFeedback.android.js b/Libraries/Components/Touchable/TouchableNativeFeedback.android.js
index 037a3b85ca8cfd..5707b61e378aaf 100644
--- a/Libraries/Components/Touchable/TouchableNativeFeedback.android.js
+++ b/Libraries/Components/Touchable/TouchableNativeFeedback.android.js
@@ -255,7 +255,7 @@ var TouchableNativeFeedback = React.createClass({
// We need to clone the actual element so that the ripple background drawable
// can be applied directly to the background of this element rather than to
- // a wrapper view as done in outher Touchable*
+ // a wrapper view as done in other Touchable*
return React.cloneElement(
child,
childProps
diff --git a/Libraries/Components/Touchable/TouchableOpacity.js b/Libraries/Components/Touchable/TouchableOpacity.js
index 8d3e53312ae0f6..40079f44538f00 100644
--- a/Libraries/Components/Touchable/TouchableOpacity.js
+++ b/Libraries/Components/Touchable/TouchableOpacity.js
@@ -77,7 +77,7 @@ var TouchableOpacity = React.createClass({
getInitialState: function() {
return {
...this.touchableGetInitialState(),
- anim: new Animated.Value(1),
+ anim: new Animated.Value(this._getChildStyleOpacityWithDefault()),
};
},
@@ -156,9 +156,8 @@ var TouchableOpacity = React.createClass({
},
_opacityInactive: function(duration: number) {
- var childStyle = flattenStyle(this.props.style) || {};
this.setOpacityTo(
- childStyle.opacity === undefined ? 1 : childStyle.opacity,
+ this._getChildStyleOpacityWithDefault(),
duration
);
},
@@ -166,6 +165,11 @@ var TouchableOpacity = React.createClass({
_opacityFocused: function() {
this.setOpacityTo(this.props.focusedOpacity);
},
+
+ _getChildStyleOpacityWithDefault: function() {
+ var childStyle = flattenStyle(this.props.style) || {};
+ return childStyle.opacity == undefined ? 1 : childStyle.opacity;
+ },
render: function() {
return (
diff --git a/Libraries/Components/Touchable/TouchableWithoutFeedback.js b/Libraries/Components/Touchable/TouchableWithoutFeedback.js
index ed0d92d5c98de9..582832b2a6292b 100755
--- a/Libraries/Components/Touchable/TouchableWithoutFeedback.js
+++ b/Libraries/Components/Touchable/TouchableWithoutFeedback.js
@@ -31,6 +31,7 @@ const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
* TouchableWithoutFeedback supports only one child.
* If you wish to have several child components, wrap them in a View.
*/
+// $FlowFixMe(>=0.41.0)
const TouchableWithoutFeedback = React.createClass({
mixins: [TimerMixin, Touchable.Mixin],
@@ -147,6 +148,7 @@ const TouchableWithoutFeedback = React.createClass({
render: function(): React.Element {
// Note(avik): remove dynamic typecast once Flow has been upgraded
+ // $FlowFixMe(>=0.41.0)
const child = React.Children.only(this.props.children);
let children = child.props.children;
warning(
@@ -163,9 +165,11 @@ const TouchableWithoutFeedback = React.createClass({
child.props.style;
return (React: any).cloneElement(child, {
accessible: this.props.accessible !== false,
+ // $FlowFixMe(>=0.41.0)
accessibilityLabel: this.props.accessibilityLabel,
accessibilityComponentType: this.props.accessibilityComponentType,
accessibilityTraits: this.props.accessibilityTraits,
+ // $FlowFixMe(>=0.41.0)
testID: this.props.testID,
onLayout: this.props.onLayout,
hitSlop: this.props.hitSlop,
diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js
index 43ef58152729e1..a519dfbb6b1edc 100644
--- a/Libraries/Components/View/View.js
+++ b/Libraries/Components/View/View.js
@@ -98,6 +98,7 @@ const statics = {
* - `timestamp` - A time identifier for the touch, useful for velocity calculation.
* - `touches` - Array of all current touches on the screen.
*/
+// $FlowFixMe(>=0.41.0)
const View = React.createClass({
// TODO: We should probably expose the mixins, viewConfig, and statics publicly. For example,
// one of the props is of type AccessibilityComponentType. That is defined as a const[] above,
diff --git a/Libraries/Components/WebView/WebView.android.js b/Libraries/Components/WebView/WebView.android.js
index 294095035d36a0..4de8be62dbb289 100644
--- a/Libraries/Components/WebView/WebView.android.js
+++ b/Libraries/Components/WebView/WebView.android.js
@@ -160,6 +160,28 @@ class WebView extends React.Component {
* @platform android
*/
allowUniversalAccessFromFileURLs: PropTypes.bool,
+
+ /**
+ * Function that accepts a string that will be passed to the WebView and
+ * executed immediately as JavaScript.
+ */
+ injectJavaScript: PropTypes.func,
+
+ /**
+ * Specifies the mixed content mode. i.e WebView will allow a secure origin to load content from any other origin.
+ *
+ * Possible values for `mixedContentMode` are:
+ *
+ * - `'never'` (default) - WebView will not allow a secure origin to load content from an insecure origin.
+ * - `'always'` - WebView will allow a secure origin to load content from any other origin, even if that origin is insecure.
+ * - `'compatibility'` - WebView will attempt to be compatible with the approach of a modern web browser with regard to mixed content.
+ * @platform android
+ */
+ mixedContentMode: PropTypes.oneOf([
+ 'never',
+ 'always',
+ 'compatibility'
+ ]),
};
static defaultProps = {
@@ -236,6 +258,7 @@ class WebView extends React.Component {
testID={this.props.testID}
mediaPlaybackRequiresUserAction={this.props.mediaPlaybackRequiresUserAction}
allowUniversalAccessFromFileURLs={this.props.allowUniversalAccessFromFileURLs}
+ mixedContentMode={this.props.mixedContentMode}
/>;
return (
diff --git a/Libraries/Components/WebView/WebView.ios.js b/Libraries/Components/WebView/WebView.ios.js
index 15409e2cc2b22d..96488b2c3ccd92 100644
--- a/Libraries/Components/WebView/WebView.ios.js
+++ b/Libraries/Components/WebView/WebView.ios.js
@@ -334,6 +334,28 @@ class WebView extends React.Component {
* to tap them before they start playing. The default value is `true`.
*/
mediaPlaybackRequiresUserAction: PropTypes.bool,
+
+ /**
+ * Function that accepts a string that will be passed to the WebView and
+ * executed immediately as JavaScript.
+ */
+ injectJavaScript: PropTypes.func,
+
+ /**
+ * Specifies the mixed content mode. i.e WebView will allow a secure origin to load content from any other origin.
+ *
+ * Possible values for `mixedContentMode` are:
+ *
+ * - `'never'` (default) - WebView will not allow a secure origin to load content from an insecure origin.
+ * - `'always'` - WebView will allow a secure origin to load content from any other origin, even if that origin is insecure.
+ * - `'compatibility'` - WebView will attempt to be compatible with the approach of a modern web browser with regard to mixed content.
+ * @platform android
+ */
+ mixedContentMode: PropTypes.oneOf([
+ 'never',
+ 'always',
+ 'compatibility'
+ ]),
};
state = {
diff --git a/Libraries/CustomComponents/ListView/ListView.js b/Libraries/CustomComponents/ListView/ListView.js
index 42dfa4d0916768..066691f54bbc73 100644
--- a/Libraries/CustomComponents/ListView/ListView.js
+++ b/Libraries/CustomComponents/ListView/ListView.js
@@ -33,6 +33,7 @@
'use strict';
var ListViewDataSource = require('ListViewDataSource');
+var Platform = require('Platform');
var React = require('React');
var ReactNative = require('ReactNative');
var RCTScrollViewManager = require('NativeModules').ScrollViewManager;
@@ -227,8 +228,9 @@ var ListView = React.createClass({
* Makes the sections headers sticky. The sticky behavior means that it
* will scroll with the content at the top of the section until it reaches
* the top of the screen, at which point it will stick to the top until it
- * is pushed off the screen by the next section header.
- * @platform ios
+ * is pushed off the screen by the next section header. This property is
+ * not supported in conjunction with `horizontal={true}`. Only enabled by
+ * default on iOS because of typical platform standards.
*/
stickySectionHeadersEnabled: React.PropTypes.bool,
/**
@@ -237,7 +239,6 @@ var ListView = React.createClass({
* `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the
* top of the scroll view. This property is not supported in conjunction
* with `horizontal={true}`.
- * @platform ios
*/
stickyHeaderIndices: PropTypes.arrayOf(PropTypes.number).isRequired,
/**
@@ -330,7 +331,7 @@ var ListView = React.createClass({
renderScrollComponent: props => ,
scrollRenderAheadDistance: DEFAULT_SCROLL_RENDER_AHEAD,
onEndReachedThreshold: DEFAULT_END_REACHED_THRESHOLD,
- stickySectionHeadersEnabled: true,
+ stickySectionHeadersEnabled: Platform.OS === 'ios',
stickyHeaderIndices: [],
};
},
@@ -403,6 +404,8 @@ var ListView = React.createClass({
var rowCount = 0;
var stickySectionHeaderIndices = [];
+ const {renderSectionHeader} = this.props;
+
var header = this.props.renderHeader && this.props.renderHeader();
var footer = this.props.renderFooter && this.props.renderFooter();
var totalIndex = header ? 1 : 0;
@@ -426,22 +429,17 @@ var ListView = React.createClass({
}
}
- if (this.props.renderSectionHeader) {
- var shouldUpdateHeader = rowCount >= this._prevRenderedRowsCount &&
- dataSource.sectionHeaderShouldUpdate(sectionIdx);
- bodyComponents.push(
-
+ if (renderSectionHeader) {
+ const element = renderSectionHeader(
+ dataSource.getSectionHeaderData(sectionIdx),
+ sectionID
);
- if (this.props.stickySectionHeadersEnabled) {
- stickySectionHeaderIndices.push(totalIndex++);
+ if (element) {
+ bodyComponents.push(React.cloneElement(element, {key: 's_' + sectionID}));
+ if (this.props.stickySectionHeadersEnabled) {
+ stickySectionHeaderIndices.push(totalIndex);
+ }
+ totalIndex++;
}
}
diff --git a/Libraries/Experimental/FlatList.js b/Libraries/CustomComponents/Lists/FlatList.js
similarity index 70%
rename from Libraries/Experimental/FlatList.js
rename to Libraries/CustomComponents/Lists/FlatList.js
index 240f0c73b47e60..10a47cc46974c5 100644
--- a/Libraries/Experimental/FlatList.js
+++ b/Libraries/CustomComponents/Lists/FlatList.js
@@ -34,10 +34,11 @@
const MetroListView = require('MetroListView'); // Used as a fallback legacy option
const React = require('React');
+const ReactNative = require('ReactNative');
const View = require('View');
const VirtualizedList = require('VirtualizedList');
-const invariant = require('invariant');
+const invariant = require('fbjs/lib/invariant');
import type {StyleObj} from 'StyleSheetTypes';
import type {ViewabilityConfig, ViewToken} from 'ViewabilityHelper';
@@ -45,19 +46,19 @@ import type {Props as VirtualizedListProps} from 'VirtualizedList';
type RequiredProps = {
/**
- * Takes an item from `data` and renders it into the list. Typicaly usage:
+ * Takes an item from `data` and renders it into the list. Typical usage:
*
- * _renderItem = ({item}) => (
- * this._onPress(item)}>
- * {item.title}}
- *
- * );
- * ...
- *
+ * _renderItem = ({item}) => (
+ * this._onPress(item)}>
+ * {item.title}}
+ *
+ * );
+ * ...
+ *
*
* Provides additional metadata like `index` if you need it.
*/
- renderItem: ({item: ItemT, index: number}) => ?React.Element<*>,
+ renderItem: (info: {item: ItemT, index: number}) => ?React.Element,
/**
* For simplicity, data is just a plain array. If you want to use something else, like an
* immutable list, use the underlying `VirtualizedList` directly.
@@ -66,26 +67,28 @@ type RequiredProps = {
};
type OptionalProps = {
/**
- * Rendered at the bottom of all the items.
+ * Rendered in between each item, but not at the top or bottom.
*/
- FooterComponent?: ?ReactClass<*>,
+ ItemSeparatorComponent?: ?ReactClass,
/**
- * Rendered at the top of all the items.
+ * Rendered at the bottom of all the items.
*/
- HeaderComponent?: ?ReactClass<*>,
+ ListFooterComponent?: ?ReactClass,
/**
- * Rendered in between each item, but not at the top or bottom.
+ * Rendered at the top of all the items.
*/
- SeparatorComponent?: ?ReactClass<*>,
+ ListHeaderComponent?: ?ReactClass,
/**
- * getItemLayout is an optional optimizations that let us skip measurement of dynamic content if
- * you know the height of items a priori. getItemLayout is the most efficient, and is easy to use
- * if you have fixed height items, for example:
+ * `getItemLayout` is an optional optimizations that let us skip measurement of dynamic content if
+ * you know the height of items a priori. `getItemLayout` is the most efficient, and is easy to
+ * use if you have fixed height items, for example:
*
- * getItemLayout={(data, index) => ({length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index})}
+ * getItemLayout={(data, index) => (
+ * {length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
+ * )}
*
* Remember to include separator length (height or width) in your offset calculation if you
- * specify `SeparatorComponent`.
+ * specify `ItemSeparatorComponent`.
*/
getItemLayout?: (data: ?Array, index: number) =>
{length: number, offset: number, index: number},
@@ -95,30 +98,31 @@ type OptionalProps = {
horizontal?: ?boolean,
/**
* Used to extract a unique key for a given item at the specified index. Key is used for caching
- * and as the react key to track item re-ordering. The default extractor checks item.key, then
- * falls back to using the index, like react does.
+ * and as the react key to track item re-ordering. The default extractor checks `item.key`, then
+ * falls back to using the index, like React does.
*/
keyExtractor: (item: ItemT, index: number) => string,
/**
- * Multiple columns can only be rendered with horizontal={false} and will zig-zag like a flexWrap
- * layout. Items should all be the same height - masonry layouts are not supported.
+ * Multiple columns can only be rendered with `horizontal={false}`` and will zig-zag like a
+ * `flexWrap` layout. Items should all be the same height - masonry layouts are not supported.
*/
numColumns: number,
/**
- * Called once when the scroll position gets within onEndReachedThreshold of the rendered content.
+ * Called once when the scroll position gets within `onEndReachedThreshold` of the rendered
+ * content.
*/
- onEndReached?: ?({distanceFromEnd: number}) => void,
+ onEndReached?: ?(info: {distanceFromEnd: number}) => void,
onEndReachedThreshold?: ?number,
/**
* If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make
* sure to also set the `refreshing` prop correctly.
*/
- onRefresh?: ?Function,
+ onRefresh?: ?() => void,
/**
* Called when the viewability of rows changes, as defined by the
* `viewablePercentThreshold` prop.
*/
- onViewableItemsChanged?: ?({viewableItems: Array, changed: Array}) => void,
+ onViewableItemsChanged?: ?(info: {viewableItems: Array, changed: Array}) => void,
legacyImplementation?: ?boolean,
/**
* Set this true while waiting for new data from a refresh.
@@ -129,14 +133,7 @@ type OptionalProps = {
*/
columnWrapperStyle?: StyleObj,
/**
- * Optional optimization to minimize re-rendering items.
- */
- shouldItemUpdate: (
- prevInfo: {item: ItemT, index: number},
- nextInfo: {item: ItemT, index: number}
- ) => boolean,
- /**
- * See ViewabilityHelper for flow type and comments.
+ * See `ViewabilityHelper` for flow type and further documentation.
*/
viewabilityConfig?: ViewabilityConfig,
};
@@ -155,25 +152,43 @@ type DefaultProps = typeof defaultProps;
*
* - Fully cross-platform.
* - Optional horizontal mode.
- * - Viewability callbacks.
+ * - Configurable viewability callbacks.
+ * - Header support.
* - Footer support.
* - Separator support.
- * - Pull to Refresh
+ * - Pull to Refresh.
+ * - Scroll loading.
*
- * If you need sticky section header support, use ListView.
+ * If you need section support, use [``](/react-native/docs/sectionlist.html).
*
* Minimal Example:
*
- * {item.key}}
- * />
+ * {item.key}}
+ * />
+ *
+ * This is a convenience wrapper around [``](/react-native/docs/virtualizedlist.html),
+ * and thus inherits the following caveats:
+ *
+ * - Internal state is not preserved when content scrolls out of the render window. Make sure all
+ * your data is captured in the item data or external stores like Flux, Redux, or Relay.
+ * - This is a `PureComponent` which means that it will not re-render if `props` remain shallow-
+ * equal. Make sure that everything your `renderItem` function depends on is passed as a prop that
+ * is not `===` after updates, otherwise your UI may not update on changes. This includes the
+ * `data` prop and parent component state.
+ * - In order to constrain memory and enable smooth scrolling, content is rendered asynchronously
+ * offscreen. This means it's possible to scroll faster than the fill rate ands momentarily see
+ * blank content. This is a tradeoff that can be adjusted to suit the needs of each application,
+ * and we are working on improving it behind the scenes.
+ * - By default, the list looks for a `key` prop on each item and uses that for the React key.
+ * Alternatively, you can provide a custom `keyExtractor` prop.
*/
class FlatList extends React.PureComponent, void> {
static defaultProps: DefaultProps = defaultProps;
props: Props;
/**
- * Scrolls to the end of the content. May be janky without getItemLayout prop.
+ * Scrolls to the end of the content. May be janky without `getItemLayout` prop.
*/
scrollToEnd(params?: ?{animated?: ?boolean}) {
this._listRef.scrollToEnd(params);
@@ -181,24 +196,25 @@ class FlatList extends React.PureComponent, vo
/**
* Scrolls to the item at a the specified index such that it is positioned in the viewable area
- * such that viewPosition 0 places it at the top, 1 at the bottom, and 0.5 centered in the middle.
+ * such that `viewPosition` 0 places it at the top, 1 at the bottom, and 0.5 centered in the
+ * middle.
*
- * May be janky without getItemLayout prop.
+ * May be janky without `getItemLayout` prop.
*/
scrollToIndex(params: {animated?: ?boolean, index: number, viewPosition?: number}) {
this._listRef.scrollToIndex(params);
}
/**
- * Requires linear scan through data - use scrollToIndex instead if possible. May be janky without
- * `getItemLayout` prop.
- */
+ * Requires linear scan through data - use `scrollToIndex` instead if possible. May be janky
+ * without `getItemLayout` prop.
+ */
scrollToItem(params: {animated?: ?boolean, item: ItemT, viewPosition?: number}) {
this._listRef.scrollToItem(params);
}
/**
- * Scroll to a specific content pixel offset, like a normal ScrollView.
+ * Scroll to a specific content pixel offset, like a normal `ScrollView`.
*/
scrollToOffset(params: {animated?: ?boolean, offset: number}) {
this._listRef.scrollToOffset(params);
@@ -206,13 +222,21 @@ class FlatList extends React.PureComponent, vo
/**
* Tells the list an interaction has occured, which should trigger viewability calculations, e.g.
- * if waitForInteractions is true and the user has not scrolled. This is typically called by taps
- * on items or by navigation actions.
+ * if `waitForInteractions` is true and the user has not scrolled. This is typically called by
+ * taps on items or by navigation actions.
*/
recordInteraction() {
this._listRef.recordInteraction();
}
+ getScrollableNode() {
+ if (this._listRef && this._listRef.getScrollableNode) {
+ return this._listRef.getScrollableNode();
+ } else {
+ return ReactNative.findNodeHandle(this._listRef);
+ }
+ }
+
componentWillMount() {
this._checkProps(this.props);
}
@@ -255,7 +279,7 @@ class FlatList extends React.PureComponent, vo
}
}
- _getItem = (data: Array, index: number): ItemT | Array => {
+ _getItem = (data: Array, index: number) => {
const {numColumns} = this.props;
if (numColumns > 1) {
const ret = [];
@@ -269,11 +293,11 @@ class FlatList extends React.PureComponent, vo
}
};
- _getItemCount = (data?: ?Array): number => {
+ _getItemCount = (data: ?Array): number => {
return data ? Math.ceil(data.length / this.props.numColumns) : 0;
};
- _keyExtractor = (items: ItemT | Array, index: number): string => {
+ _keyExtractor = (items: ItemT | Array, index: number) => {
const {keyExtractor, numColumns} = this.props;
if (numColumns > 1) {
invariant(
diff --git a/Libraries/Experimental/MetroListView.js b/Libraries/CustomComponents/Lists/MetroListView.js
similarity index 100%
rename from Libraries/Experimental/MetroListView.js
rename to Libraries/CustomComponents/Lists/MetroListView.js
diff --git a/Libraries/Experimental/SectionList.js b/Libraries/CustomComponents/Lists/SectionList.js
similarity index 55%
rename from Libraries/Experimental/SectionList.js
rename to Libraries/CustomComponents/Lists/SectionList.js
index 65bb78ac9441bf..2bc66a65affe54 100644
--- a/Libraries/Experimental/SectionList.js
+++ b/Libraries/CustomComponents/Lists/SectionList.js
@@ -47,8 +47,8 @@ type SectionBase = {
key: string,
// Optional props will override list-wide props just for this section.
- renderItem?: ?({item: SectionItemT, index: number}) => ?React.Element<*>,
- SeparatorComponent?: ?ReactClass<*>,
+ renderItem?: ?(info: {item: SectionItemT, index: number}) => ?React.Element,
+ SeparatorComponent?: ?ReactClass,
keyExtractor?: (item: SectionItemT) => string,
// TODO: support more optional/override props
@@ -57,53 +57,52 @@ type SectionBase = {
// onViewableItemsChanged?: ({viewableItems: Array, changed: Array}) => void,
};
-type RequiredProps> = {
+type RequiredProps> = {
sections: Array,
};
-type OptionalProps> = {
+type OptionalProps> = {
/**
* Default renderer for every item in every section. Can be over-ridden on a per-section basis.
*/
- renderItem: ({item: Item, index: number}) => ?React.Element<*>,
+ renderItem: (info: {item: Item, index: number}) => ?React.Element,
/**
* Rendered in between adjacent Items within each section.
*/
- ItemSeparatorComponent?: ?ReactClass<*>,
+ ItemSeparatorComponent?: ?ReactClass,
/**
* Rendered at the very beginning of the list.
*/
- ListHeaderComponent?: ?ReactClass<*>,
+ ListHeaderComponent?: ?ReactClass,
/**
* Rendered at the very end of the list.
*/
- ListFooterComponent?: ?ReactClass<*>,
+ ListFooterComponent?: ?ReactClass,
/**
* Rendered at the top of each section. Sticky headers are not yet supported.
*/
- renderSectionHeader?: ?({section: SectionT}) => ?React.Element<*>,
+ renderSectionHeader?: ?(info: {section: SectionT}) => ?React.Element,
/**
* Rendered in between each section.
*/
- SectionSeparatorComponent?: ?ReactClass<*>,
+ SectionSeparatorComponent?: ?ReactClass,
/**
- * Warning: Virtualization can drastically improve memory consumption for long lists, but trashes
- * the state of items when they scroll out of the render window, so make sure all relavent data is
- * stored outside of the recursive `renderItem` instance tree.
+ * Used to extract a unique key for a given item at the specified index. Key is used for caching
+ * and as the react key to track item re-ordering. The default extractor checks item.key, then
+ * falls back to using the index, like react does.
*/
- enableVirtualization?: ?boolean,
keyExtractor: (item: Item, index: number) => string,
- onEndReached?: ?({distanceFromEnd: number}) => void,
+ onEndReached?: ?(info: {distanceFromEnd: number}) => void,
/**
* If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make
* sure to also set the `refreshing` prop correctly.
*/
- onRefresh?: ?Function,
+ onRefresh?: ?() => void,
/**
* Called when the viewability of rows changes, as defined by the
* `viewabilityConfig` prop.
*/
- onViewableItemsChanged?: ?({viewableItems: Array, changed: Array}) => void,
+ onViewableItemsChanged?: ?(info: {viewableItems: Array, changed: Array}) => void,
/**
* Set this true while waiting for new data from a refresh.
*/
@@ -127,31 +126,65 @@ type DefaultProps = typeof VirtualizedSectionList.defaultProps;
* A performant interface for rendering sectioned lists, supporting the most handy features:
*
* - Fully cross-platform.
- * - Viewability callbacks.
- * - Footer support.
- * - Separator support.
- * - Heterogeneous data and item support.
+ * - Configurable viewability callbacks.
+ * - List header support.
+ * - List footer support.
+ * - Item separator support.
+ * - Section header support.
+ * - Section separator support.
+ * - Heterogeneous data and item rendering support.
* - Pull to Refresh.
+ * - Scroll loading.
*
- * If you don't need section support and want a simpler interface, use FlatList.
+ * If you don't need section support and want a simpler interface, use [``](/react-native/docs/flatlist.html).
+ *
+ * If you need _sticky_ section header support, use `ListView` for now.
+ *
+ * Simple Examples:
+ *
+ * }
+ * sections={[ // homogenous rendering between sections
+ * {data: [...], key: ...},
+ * {data: [...], key: ...},
+ * {data: [...], key: ...},
+ * ]}
+ * />
+ *
+ *
+ *
+ * This is a convenience wrapper around [``](/react-native/docs/virtualizedlist.html),
+ * and thus inherits the following caveats:
+ *
+ * - Internal state is not preserved when content scrolls out of the render window. Make sure all
+ * your data is captured in the item data or external stores like Flux, Redux, or Relay.
+ * - This is a `PureComponent` which means that it will not re-render if `props` remain shallow-
+ * equal. Make sure that everything your `renderItem` function depends on is passed as a prop that
+ * is not `===` after updates, otherwise your UI may not update on changes. This includes the
+ * `data` prop and parent component state.
+ * - In order to constrain memory and enable smooth scrolling, content is rendered asynchronously
+ * offscreen. This means it's possible to scroll faster than the fill rate ands momentarily see
+ * blank content. This is a tradeoff that can be adjusted to suit the needs of each application,
+ * and we are working on improving it behind the scenes.
+ * - By default, the list looks for a `key` prop on each item and uses that for the React key.
+ * Alternatively, you can provide a custom `keyExtractor` prop.
*/
-class SectionList>
- extends React.PureComponent, *>
+class SectionList>
+ extends React.PureComponent, void>
{
props: Props;
static defaultProps: DefaultProps = VirtualizedSectionList.defaultProps;
render() {
- const {ListFooterComponent, ListHeaderComponent, ItemSeparatorComponent} = this.props;
const List = this.props.legacyImplementation ? MetroListView : VirtualizedSectionList;
- return (
-
- );
+ return
;
}
}
diff --git a/Libraries/Experimental/ViewabilityHelper.js b/Libraries/CustomComponents/Lists/ViewabilityHelper.js
similarity index 88%
rename from Libraries/Experimental/ViewabilityHelper.js
rename to Libraries/CustomComponents/Lists/ViewabilityHelper.js
index a8a185165c1697..f3cc0e584b34d4 100644
--- a/Libraries/Experimental/ViewabilityHelper.js
+++ b/Libraries/CustomComponents/Lists/ViewabilityHelper.js
@@ -11,7 +11,7 @@
*/
'use strict';
-const invariant = require('invariant');
+const invariant = require('fbjs/lib/invariant');
export type ViewToken = {item: any, key: string, index: ?number, isViewable: boolean, section?: any};
@@ -42,18 +42,12 @@ export type ViewabilityConfig = {|
* render.
*/
waitForInteraction?: boolean,
-
- /**
- * Criteria to filter out certain scroll events so they don't count as interactions. By default,
- * any non-zero scroll offset will be considered an interaction.
- */
- scrollInteractionFilter?: {|
- minimumOffset?: number, // scrolls with an offset less than this are ignored.
- minimumElapsed?: number, // scrolls that happen before this are ignored.
- |},
|};
/**
+* A Utility class for calculating viewable items based on current metrics like scroll position and
+* layout.
+*
* An item is said to be in a "viewable" state when any of the following
* is true for longer than `minViewTime` milliseconds (after an interaction if `waitForInteraction`
* is true):
@@ -71,17 +65,19 @@ class ViewabilityHelper {
_viewableItems: Map = new Map();
constructor(config: ViewabilityConfig = {viewAreaCoveragePercentThreshold: 0}) {
- invariant(
- config.scrollInteractionFilter == null || config.waitForInteraction,
- 'scrollInteractionFilter only works in conjunction with waitForInteraction',
- );
this._config = config;
}
+ /**
+ * Cleanup, e.g. on unmount. Clears any pending timers.
+ */
dispose() {
this._timers.forEach(clearTimeout);
}
+ /**
+ * Determines which items are viewable based on the current metrics and config.
+ */
computeViewableItems(
itemCount: number,
scrollOffset: number,
@@ -135,6 +131,10 @@ class ViewabilityHelper {
return viewableIndices;
}
+ /**
+ * Figures out which items are viewable and how that has changed from before and calls
+ * `onViewableItemsChanged` as appropriate.
+ */
onUpdate(
itemCount: number,
scrollOffset: number,
@@ -150,17 +150,6 @@ class ViewabilityHelper {
this._lastUpdateTime = updateTime;
}
const updateElapsed = this._lastUpdateTime ? updateTime - this._lastUpdateTime : 0;
- if (this._config.waitForInteraction && !this._hasInteracted && scrollOffset !== 0) {
- const filter = this._config.scrollInteractionFilter;
- if (filter) {
- if ((filter.minimumOffset == null || scrollOffset >= filter.minimumOffset) &&
- (filter.minimumElapsed == null || updateElapsed >= filter.minimumElapsed)) {
- this._hasInteracted = true;
- }
- } else {
- this._hasInteracted = true;
- }
- }
if (this._config.waitForInteraction && !this._hasInteracted) {
return;
}
@@ -196,6 +185,9 @@ class ViewabilityHelper {
}
}
+ /**
+ * Records that an interaction has happened even if there has been no scroll.
+ */
recordInteraction() {
this._hasInteracted = true;
}
diff --git a/Libraries/Experimental/VirtualizeUtils.js b/Libraries/CustomComponents/Lists/VirtualizeUtils.js
similarity index 99%
rename from Libraries/Experimental/VirtualizeUtils.js
rename to Libraries/CustomComponents/Lists/VirtualizeUtils.js
index c366cc80a2047a..e03fa4dd725662 100644
--- a/Libraries/Experimental/VirtualizeUtils.js
+++ b/Libraries/CustomComponents/Lists/VirtualizeUtils.js
@@ -11,7 +11,7 @@
*/
'use strict';
-const invariant = require('invariant');
+const invariant = require('fbjs/lib/invariant');
/**
* Used to find the indices of the frames that overlap the given offsets. Useful for finding the
diff --git a/Libraries/Experimental/VirtualizedList.js b/Libraries/CustomComponents/Lists/VirtualizedList.js
similarity index 79%
rename from Libraries/Experimental/VirtualizedList.js
rename to Libraries/CustomComponents/Lists/VirtualizedList.js
index bf10add143d824..9040fcf1b81763 100644
--- a/Libraries/Experimental/VirtualizedList.js
+++ b/Libraries/CustomComponents/Lists/VirtualizedList.js
@@ -34,6 +34,7 @@
const Batchinator = require('Batchinator');
const React = require('React');
+const ReactNative = require('ReactNative');
const RefreshControl = require('RefreshControl');
const ScrollView = require('ScrollView');
const View = require('View');
@@ -47,21 +48,8 @@ const {computeWindowedRenderLimits} = require('VirtualizeUtils');
import type {ViewabilityConfig, ViewToken} from 'ViewabilityHelper';
type Item = any;
-type renderItemType = ({item: Item, index: number}) => ?React.Element<*>;
+type renderItemType = (info: {item: Item, index: number}) => ?React.Element;
-/**
- * Renders a virtual list of items given a data blob and accessor functions. Items that are outside
- * the render window (except for the initial items at the top) are 'virtualized' e.g. unmounted or
- * never rendered in the first place. This improves performance and saves memory for large data
- * sets, but will reset state on items that scroll too far out of the render window.
- *
- * TODO: Note that LayoutAnimation and sticky section headers both have bugs when used with this and
- * are therefor not supported, but new Animated impl might work?
- * https://github.com/facebook/react-native/pull/11315
- *
- * TODO: removeClippedSubviews might not be necessary and may cause bugs?
- *
- */
type RequiredProps = {
renderItem: renderItemType,
/**
@@ -71,12 +59,9 @@ type RequiredProps = {
data?: any,
};
type OptionalProps = {
- FooterComponent?: ?ReactClass<*>,
- HeaderComponent?: ?ReactClass<*>,
- SeparatorComponent?: ?ReactClass<*>,
/**
* `debug` will turn on extra logging and visual overlays to aid with debugging both usage and
- * implementation.
+ * implementation, but with a significant perf hit.
*/
debug?: ?boolean,
/**
@@ -85,15 +70,30 @@ type OptionalProps = {
* this for debugging purposes.
*/
disableVirtualization: boolean,
- getItem: (items: any, index: number) => ?Item,
- getItemCount: (items: any) => number,
- getItemLayout?: (items: any, index: number) =>
+ /**
+ * A generic accessor for extracting an item from any sort of data blob.
+ */
+ getItem: (data: any, index: number) => ?Item,
+ /**
+ * Determines how many items are in the data blob.
+ */
+ getItemCount: (data: any) => number,
+ getItemLayout?: (data: any, index: number) =>
{length: number, offset: number, index: number}, // e.g. height, y
horizontal?: ?boolean,
+ /**
+ * How many items to render in the initial batch. This should be enough to fill the screen but not
+ * much more.
+ */
initialNumToRender: number,
keyExtractor: (item: Item, index: number) => string,
+ /**
+ * The maximum number of items to render in each incremental render batch. The more rendered at
+ * once, the better the fill rate, but responsiveness my suffer because rendering content may
+ * interfere with responding to button taps or other interactions.
+ */
maxToRenderPerBatch: number,
- onEndReached?: ?({distanceFromEnd: number}) => void,
+ onEndReached?: ?(info: {distanceFromEnd: number}) => void,
onEndReachedThreshold?: ?number, // units of visible length
onLayout?: ?Function,
/**
@@ -105,26 +105,80 @@ type OptionalProps = {
* Called when the viewability of rows changes, as defined by the
* `viewabilityConfig` prop.
*/
- onViewableItemsChanged?: ?({viewableItems: Array, changed: Array}) => void,
+ onViewableItemsChanged?: ?(info: {viewableItems: Array, changed: Array}) => void,
/**
* Set this true while waiting for new data from a refresh.
*/
refreshing?: ?boolean,
+ /**
+ * A native optimization that removes clipped subviews (those outside the parent) from the view
+ * hierarchy to offload work from the native rendering system. They are still kept around so no
+ * memory is saved and state is preserved.
+ */
removeClippedSubviews?: boolean,
- renderScrollComponent: (props: Object) => React.Element<*>,
+ /**
+ * Render a custom scroll component, e.g. with a differently styled `RefreshControl`.
+ */
+ renderScrollComponent: (props: Object) => React.Element,
shouldItemUpdate: (
props: {item: Item, index: number},
nextProps: {item: Item, index: number}
) => boolean,
+ /**
+ * Amount of time between low-pri item render batches, e.g. for rendering items quite a ways off
+ * screen. Similar fill rate/responsiveness tradeoff as `maxToRenderPerBatch`.
+ */
updateCellsBatchingPeriod: number,
viewabilityConfig?: ViewabilityConfig,
- windowSize: number, // units of visible length
+ /**
+ * Determines the maximum number of items rendered outside of the visible area, in units of
+ * visible lengths. So if your list fills the screen, then `windowSize={21}` (the default) will
+ * render the visible screen area plus up to 10 screens above and 10 below the viewport. Reducing
+ * this number will reduce memory consumption and may improve performance, but will increase the
+ * chance that fast scrolling may reveal momentary blank areas of unrendered content.
+ */
+ windowSize: number,
};
export type Props = RequiredProps & OptionalProps;
let _usedIndexForKey = false;
-class VirtualizedList extends React.PureComponent {
+type State = {first: number, last: number};
+
+/**
+ * Base implementation for the more convenient [``](/react-native/docs/flatlist.html)
+ * and [``](/react-native/docs/sectionlist.html) components, which are also better
+ * documented. In general, this should only really be used if you need more flexibility than
+ * `FlatList` provides, e.g. for use with immutable data instead of plain arrays.
+ *
+ * Virtualization massively improves memory consumption and performance of large lists by
+ * maintaining a finite render window of active items and replacing all items outside of the render
+ * window with appropriately sized blank space. The window adapts to scrolling behavior, and items
+ * are rendered incrementally with low-pri (after any running interactions) if they are far from the
+ * visible area, or with hi-pri otherwise to minimize the potential of seeing blank space.
+ *
+ * Some caveats:
+ *
+ * - Internal state is not preserved when content scrolls out of the render window. Make sure all
+ * your data is captured in the item data or external stores like Flux, Redux, or Relay.
+ * - This is a `PureComponent` which means that it will not re-render if `props` remain shallow-
+ * equal. Make sure that everything your `renderItem` function depends on is passed as a prop that
+ * is not `===` after updates, otherwise your UI may not update on changes. This includes the
+ * `data` prop and parent component state.
+ * - In order to constrain memory and enable smooth scrolling, content is rendered asynchronously
+ * offscreen. This means it's possible to scroll faster than the fill rate ands momentarily see
+ * blank content. This is a tradeoff that can be adjusted to suit the needs of each application,
+ * and we are working on improving it behind the scenes.
+ * - By default, the list looks for a `key` prop on each item and uses that for the React key.
+ * Alternatively, you can provide a custom `keyExtractor` prop.
+ *
+ * NOTE: `LayoutAnimation` and sticky section headers both have bugs when used with this and are
+ * therefore not officially supported yet.
+ *
+ * NOTE: `removeClippedSubviews` might not be necessary and may cause bugs. If you see issues with
+ * content not rendering, try disabling it, and we may change the default there.
+ */
+class VirtualizedList extends React.PureComponent {
props: Props;
// scrollToEnd may be janky without getItemLayout prop
@@ -181,6 +235,14 @@ class VirtualizedList extends React.PureComponent {
this._updateViewableItems(this.props.data);
}
+ getScrollableNode() {
+ if (this._scrollRef && this._scrollRef.getScrollableNode) {
+ return this._scrollRef.getScrollableNode();
+ } else {
+ return ReactNative.findNodeHandle(this._scrollRef);
+ }
+ }
+
static defaultProps = {
disableVirtualization: false,
getItem: (data: any, index: number) => data[index],
@@ -228,7 +290,7 @@ class VirtualizedList extends React.PureComponent {
windowSize: 21, // multiples of length
};
- state = {
+ state: State = {
first: 0,
last: this.props.initialNumToRender,
};
@@ -237,8 +299,10 @@ class VirtualizedList extends React.PureComponent {
super(props);
invariant(
!props.onScroll || !props.onScroll.__isNative,
- 'VirtualizedList does not support AnimatedEvent with onScroll and useNativeDriver',
+ 'Components based on VirtualizedList must be wrapped with Animated.createAnimatedComponent ' +
+ 'to support native onScroll events with useNativeDriver',
);
+
this._updateCellsToRenderBatcher = new Batchinator(
this._updateCellsToRender,
this.props.updateCellsBatchingPeriod,
@@ -268,7 +332,7 @@ class VirtualizedList extends React.PureComponent {
}
_pushCells(cells, first, last) {
- const {SeparatorComponent, data, getItem, getItemCount, keyExtractor} = this.props;
+ const {ItemSeparatorComponent, data, getItem, getItemCount, keyExtractor} = this.props;
const end = getItemCount(data) - 1;
last = Math.min(end, last);
for (let ii = first; ii <= last; ii++) {
@@ -281,24 +345,24 @@ class VirtualizedList extends React.PureComponent {
index={ii}
item={item}
key={key}
- onLayout={this._onCellLayout}
+ onCellLayout={this._onCellLayout}
onUnmount={this._onCellUnmount}
parentProps={this.props}
/>
);
- if (SeparatorComponent && ii < end) {
- cells.push();
+ if (ItemSeparatorComponent && ii < end) {
+ cells.push();
}
}
}
render() {
- const {FooterComponent, HeaderComponent} = this.props;
+ const {ListFooterComponent, ListHeaderComponent} = this.props;
const {data, disableVirtualization, horizontal} = this.props;
const cells = [];
- if (HeaderComponent) {
+ if (ListHeaderComponent) {
cells.push(
-
+
);
}
@@ -338,10 +402,10 @@ class VirtualizedList extends React.PureComponent {
);
}
}
- if (FooterComponent) {
+ if (ListFooterComponent) {
cells.push(
-
+
);
}
@@ -351,6 +415,7 @@ class VirtualizedList extends React.PureComponent {
onContentSizeChange: this._onContentSizeChange,
onLayout: this._onLayout,
onScroll: this._onScroll,
+ onScrollBeginDrag: this._onScrollBeginDrag,
ref: this._captureScrollRef,
scrollEventThrottle: 50, // TODO: Android support
},
@@ -487,6 +552,9 @@ class VirtualizedList extends React.PureComponent {
}
_onContentSizeChange = (width: number, height: number) => {
+ if (this.props.onContentSizeChange) {
+ this.props.onContentSizeChange(width, height);
+ }
this._scrollMetrics.contentLength = this._selectLength({height, width});
this._updateCellsToRenderBatcher.schedule();
};
@@ -545,6 +613,10 @@ class VirtualizedList extends React.PureComponent {
this._updateCellsToRenderBatcher.schedule();
};
+ _onScrollBeginDrag = (e): void => {
+ this._viewabilityHelper.recordInteraction();
+ this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e);
+ };
_updateCellsToRender = () => {
const {data, disableVirtualization, getItemCount, onEndReachedThreshold} = this.props;
this._updateViewableItems(data);
@@ -571,7 +643,7 @@ class VirtualizedList extends React.PureComponent {
});
};
- _createViewToken = (index: number, isViewable: boolean): ViewToken => {
+ _createViewToken = (index: number, isViewable: boolean) => {
const {data, getItem, keyExtractor} = this.props;
const item = getItem(data, index);
invariant(item, 'Missing item for index ' + index);
@@ -630,7 +702,7 @@ class CellRenderer extends React.Component {
cellKey: string,
index: number,
item: Item,
- onLayout: (event: Object, cellKey: string, index: number) => void,
+ onCellLayout: (event: Object, cellKey: string, index: number) => void,
onUnmount: (cellKey: string) => void,
parentProps: {
renderItem: renderItemType,
@@ -642,7 +714,7 @@ class CellRenderer extends React.Component {
},
};
_onLayout = (e) => {
- this.props.onLayout(e, this.props.cellKey, this.props.index);
+ this.props.onCellLayout(e, this.props.cellKey, this.props.index);
}
componentWillUnmount() {
this.props.onUnmount(this.props.cellKey);
diff --git a/Libraries/Experimental/VirtualizedSectionList.js b/Libraries/CustomComponents/Lists/VirtualizedSectionList.js
similarity index 98%
rename from Libraries/Experimental/VirtualizedSectionList.js
rename to Libraries/CustomComponents/Lists/VirtualizedSectionList.js
index c0bacd3c8ba4fc..317891c4d3ebc2 100644
--- a/Libraries/Experimental/VirtualizedSectionList.js
+++ b/Libraries/CustomComponents/Lists/VirtualizedSectionList.js
@@ -36,8 +36,8 @@ const React = require('React');
const View = require('View');
const VirtualizedList = require('VirtualizedList');
-const invariant = require('invariant');
-const warning = require('warning');
+const invariant = require('fbjs/lib/invariant');
+const warning = require('fbjs/lib/warning');
import type {ViewToken} from 'ViewabilityHelper';
import type {Props as VirtualizedListProps} from 'VirtualizedList';
@@ -84,7 +84,7 @@ type OptionalProps = {
renderSectionHeader?: ?({section: SectionT}) => ?React.Element<*>,
/**
* Rendered at the bottom of every Section, except the very last one, in place of the normal
- * SeparatorComponent.
+ * ItemSeparatorComponent.
*/
SectionSeparatorComponent?: ?ReactClass<*>,
/**
diff --git a/Libraries/Experimental/__flowtests__/FlatList-flowtest.js b/Libraries/CustomComponents/Lists/__flowtests__/FlatList-flowtest.js
similarity index 100%
rename from Libraries/Experimental/__flowtests__/FlatList-flowtest.js
rename to Libraries/CustomComponents/Lists/__flowtests__/FlatList-flowtest.js
diff --git a/Libraries/Experimental/__flowtests__/SectionList-flowtest.js b/Libraries/CustomComponents/Lists/__flowtests__/SectionList-flowtest.js
similarity index 100%
rename from Libraries/Experimental/__flowtests__/SectionList-flowtest.js
rename to Libraries/CustomComponents/Lists/__flowtests__/SectionList-flowtest.js
diff --git a/Libraries/Experimental/__tests__/ViewabilityHelper-test.js b/Libraries/CustomComponents/Lists/__tests__/ViewabilityHelper-test.js
similarity index 96%
rename from Libraries/Experimental/__tests__/ViewabilityHelper-test.js
rename to Libraries/CustomComponents/Lists/__tests__/ViewabilityHelper-test.js
index 9d7876f49db92a..199132ae8156bd 100644
--- a/Libraries/Experimental/__tests__/ViewabilityHelper-test.js
+++ b/Libraries/CustomComponents/Lists/__tests__/ViewabilityHelper-test.js
@@ -10,6 +10,7 @@
'use strict';
jest.unmock('ViewabilityHelper');
+
const ViewabilityHelper = require('ViewabilityHelper');
let rowFrames;
@@ -315,14 +316,11 @@ describe('onUpdate', function() {
);
it(
- 'waitForInteraction blocks callback until scroll',
+ 'waitForInteraction blocks callback until interaction',
function() {
const helper = new ViewabilityHelper({
waitForInteraction: true,
viewAreaCoveragePercentThreshold: 0,
- scrollInteractionFilter: {
- minimumOffset: 20,
- },
});
rowFrames = {
a: {y: 0, height: 200},
@@ -339,15 +337,9 @@ describe('onUpdate', function() {
onViewableItemsChanged,
);
expect(onViewableItemsChanged).not.toBeCalled();
- helper.onUpdate(
- data.length,
- 10, // not far enough to meet minimumOffset
- 100,
- getFrameMetrics,
- createViewToken,
- onViewableItemsChanged,
- );
- expect(onViewableItemsChanged).not.toBeCalled();
+
+ helper.recordInteraction();
+
helper.onUpdate(
data.length,
20,
diff --git a/Libraries/Experimental/__tests__/VirtualizeUtils-test.js b/Libraries/CustomComponents/Lists/__tests__/VirtualizeUtils-test.js
similarity index 100%
rename from Libraries/Experimental/__tests__/VirtualizeUtils-test.js
rename to Libraries/CustomComponents/Lists/__tests__/VirtualizeUtils-test.js
diff --git a/Libraries/CustomComponents/Navigator/Navigation/NavigationRouteStack.js b/Libraries/CustomComponents/Navigator/Navigation/NavigationRouteStack.js
index 3290ba462d2e2e..fe40a609110e46 100644
--- a/Libraries/CustomComponents/Navigator/Navigation/NavigationRouteStack.js
+++ b/Libraries/CustomComponents/Navigator/Navigation/NavigationRouteStack.js
@@ -1,5 +1,26 @@
/**
- * Copyright 2004-present Facebook. All Rights Reserved.
+ * Copyright (c) 2015, Facebook, Inc. All rights reserved.
+ *
+ * Facebook, Inc. ("Facebook") owns all right, title and interest, including
+ * all intellectual property and other proprietary rights, in and to the React
+ * Native CustomComponents software (the "Software"). Subject to your
+ * compliance with these terms, you are hereby granted a non-exclusive,
+ * worldwide, royalty-free copyright license to (1) use and copy the Software;
+ * and (2) reproduce and distribute the Software as part of your own software
+ * ("Your Software"). Facebook reserves all rights not expressly granted to
+ * you in this license agreement.
+ *
+ * THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED.
+ * IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR
+ * EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @providesModule NavigationRouteStack
* @flow
@@ -135,7 +156,7 @@ class RouteStack {
invariant(this._routeNodes.indexOf(route) === -1, 'route must be unique');
// When pushing, removes the rest of the routes past the current index.
- var routeNodes = this._routeNodes.withMutations((list: List) => {
+ var routeNodes = this._routeNodes.withMutations((list: List) => {
list.slice(0, this._index + 1).push(new RouteNode(route));
});
@@ -232,7 +253,7 @@ class RouteStack {
return new Set(items);
}
- _update(index: number, routeNodes: List): RouteStack {
+ _update(index: number, routeNodes: List): RouteStack {
if (this._index === index && this._routeNodes === routeNodes) {
return this;
}
diff --git a/Libraries/CustomComponents/Navigator/Navigation/NavigationTreeNode.js b/Libraries/CustomComponents/Navigator/Navigation/NavigationTreeNode.js
index 02b0e3dbb83f58..d188c366f74596 100644
--- a/Libraries/CustomComponents/Navigator/Navigation/NavigationTreeNode.js
+++ b/Libraries/CustomComponents/Navigator/Navigation/NavigationTreeNode.js
@@ -1,10 +1,30 @@
/**
* Copyright (c) 2015, Facebook, Inc. All rights reserved.
*
+ * Facebook, Inc. ("Facebook") owns all right, title and interest, including
+ * all intellectual property and other proprietary rights, in and to the React
+ * Native CustomComponents software (the "Software"). Subject to your
+ * compliance with these terms, you are hereby granted a non-exclusive,
+ * worldwide, royalty-free copyright license to (1) use and copy the Software;
+ * and (2) reproduce and distribute the Software as part of your own software
+ * ("Your Software"). Facebook reserves all rights not expressly granted to
+ * you in this license agreement.
+ *
+ * THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED.
+ * IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR
+ * EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
* @providesModule NavigationTreeNode
* @flow
*/
-
'use strict';
var invariant = require('fbjs/lib/invariant');
diff --git a/Libraries/Image/AssetRegistry.js b/Libraries/Image/AssetRegistry.js
index 440f16587b6643..fd03c69b57a384 100644
--- a/Libraries/Image/AssetRegistry.js
+++ b/Libraries/Image/AssetRegistry.js
@@ -1,11 +1,17 @@
/**
- * Copyright 2004-present Facebook. All Rights Reserved.
+ * 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 AssetRegistry
* @flow
*/
'use strict';
+
export type PackagerAsset = {
__packager_asset: boolean,
fileSystemLocation: string,
diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js
index b0e813b3fd8b6e..7d4a7752d3b56f 100644
--- a/Libraries/Image/Image.android.js
+++ b/Libraries/Image/Image.android.js
@@ -11,23 +11,24 @@
*/
'use strict';
-var NativeMethodsMixin = require('NativeMethodsMixin');
-var NativeModules = require('NativeModules');
var ImageResizeMode = require('ImageResizeMode');
var ImageStylePropTypes = require('ImageStylePropTypes');
-var ViewStylePropTypes = require('ViewStylePropTypes');
+var NativeMethodsMixin = require('NativeMethodsMixin');
+var NativeModules = require('NativeModules');
+var PropTypes = require('react/lib/ReactPropTypes');
var React = require('React');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
+var Set = require('Set');
var StyleSheet = require('StyleSheet');
var StyleSheetPropType = require('StyleSheetPropType');
var View = require('View');
+var ViewStylePropTypes = require('ViewStylePropTypes');
+var filterObject = require('fbjs/lib/filterObject');
var flattenStyle = require('flattenStyle');
var merge = require('merge');
var requireNativeComponent = require('requireNativeComponent');
var resolveAssetSource = require('resolveAssetSource');
-var Set = require('Set');
-var filterObject = require('fbjs/lib/filterObject');
var PropTypes = React.PropTypes;
var {
@@ -106,6 +107,10 @@ var Image = React.createClass({
height: PropTypes.number,
}))
]),
+ /**
+ * blurRadius: the blur radius of the blur filter added to the image
+ */
+ blurRadius: PropTypes.number,
/**
* similarly to `source`, this property represents the resource used to render
* the loading indicator for the image, displayed until image is ready to be
diff --git a/Libraries/Image/Image.ios.js b/Libraries/Image/Image.ios.js
index 5b029d1128460b..3177b1f5e2fcb4 100644
--- a/Libraries/Image/Image.ios.js
+++ b/Libraries/Image/Image.ios.js
@@ -126,6 +126,7 @@ const ImageViewManager = NativeModules.ImageViewManager;
* ```
*
*/
+// $FlowFixMe(>=0.41.0)
const Image = React.createClass({
propTypes: {
/**
@@ -288,6 +289,8 @@ const Image = React.createClass({
* does not fully load/download the image data. A proper, supported way to
* preload images will be provided as a separate API.
*
+ * Does not work for static image resources.
+ *
* @param uri The location of the image.
* @param success The function that will be called if the image was successfully found and width
* and height retrieved.
diff --git a/Libraries/Interaction/InteractionMixin.js b/Libraries/Interaction/InteractionMixin.js
index b92120f90fe4bf..b0e3104407ea36 100644
--- a/Libraries/Interaction/InteractionMixin.js
+++ b/Libraries/Interaction/InteractionMixin.js
@@ -1,5 +1,10 @@
/**
- * Copyright 2004-present Facebook. All Rights Reserved.
+ * 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 InteractionMixin
* @flow
diff --git a/Libraries/Linking/Linking.js b/Libraries/Linking/Linking.js
index 8fe85bfd045224..1902bfb2a793ef 100644
--- a/Libraries/Linking/Linking.js
+++ b/Libraries/Linking/Linking.js
@@ -61,7 +61,7 @@ const LinkingManager = Platform.OS === 'android' ?
* execution you'll need to add the following lines to you `*AppDelegate.m`:
*
* ```
- * #import "RCTLinkingManager.h"
+ * #import
*
* - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
* sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedModule.m b/Libraries/NativeAnimation/RCTNativeAnimatedModule.m
index 55763bfe57dc28..4b30c47d7c419c 100644
--- a/Libraries/NativeAnimation/RCTNativeAnimatedModule.m
+++ b/Libraries/NativeAnimation/RCTNativeAnimatedModule.m
@@ -168,10 +168,11 @@ - (void)setBridge:(RCTBridge *)bridge
}
RCT_EXPORT_METHOD(removeAnimatedEventFromView:(nonnull NSNumber *)viewTag
- eventName:(nonnull NSString *)eventName)
+ eventName:(nonnull NSString *)eventName
+ animatedNodeTag:(nonnull NSNumber *)animatedNodeTag)
{
[_operations addObject:^(RCTNativeAnimatedNodesManager *nodesManager) {
- [nodesManager removeAnimatedEventFromView:viewTag eventName:eventName];
+ [nodesManager removeAnimatedEventFromView:viewTag eventName:eventName animatedNodeTag:animatedNodeTag];
}];
}
diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h
index e911f1b37c2dd5..c4ffc652a693ad 100644
--- a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h
+++ b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h
@@ -9,8 +9,8 @@
#import
-#import
#import
+#import
#import "RCTValueAnimatedNode.h"
@@ -70,7 +70,8 @@
eventMapping:(NSDictionary *__nonnull)eventMapping;
- (void)removeAnimatedEventFromView:(nonnull NSNumber *)viewTag
- eventName:(nonnull NSString *)eventName;
+ eventName:(nonnull NSString *)eventName
+ animatedNodeTag:(nonnull NSNumber *)animatedNodeTag;
- (void)handleAnimatedEvent:(nonnull id)event;
diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m
index ac15ad705ddd3c..caeabba7232a62 100644
--- a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m
+++ b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m
@@ -11,29 +11,29 @@
#import
+#import "RCTAdditionAnimatedNode.h"
#import "RCTAnimatedNode.h"
#import "RCTAnimationDriver.h"
-#import "RCTEventAnimation.h"
-
-#import "RCTAdditionAnimatedNode.h"
-#import "RCTInterpolationAnimatedNode.h"
#import "RCTDiffClampAnimatedNode.h"
#import "RCTDivisionAnimatedNode.h"
+#import "RCTEventAnimation.h"
+#import "RCTFrameAnimation.h"
+#import "RCTInterpolationAnimatedNode.h"
#import "RCTModuloAnimatedNode.h"
#import "RCTMultiplicationAnimatedNode.h"
-#import "RCTModuloAnimatedNode.h"
#import "RCTPropsAnimatedNode.h"
+#import "RCTSpringAnimation.h"
#import "RCTStyleAnimatedNode.h"
#import "RCTTransformAnimatedNode.h"
#import "RCTValueAnimatedNode.h"
-#import "RCTFrameAnimation.h"
-#import "RCTSpringAnimation.h"
@implementation RCTNativeAnimatedNodesManager
{
RCTUIManager *_uiManager;
NSMutableDictionary *_animationNodes;
- NSMutableDictionary *_eventDrivers;
+ // Mapping of a view tag and an event name to a list of event animation drivers. 99% of the time
+ // there will be only one driver per mapping so all code code should be optimized around that.
+ NSMutableDictionary *> *_eventDrivers;
NSMutableSet> *_activeAnimations;
CADisplayLink *_displayLink;
}
@@ -207,7 +207,7 @@ - (void)startAnimatingNode:(nonnull NSNumber *)animationId
RCTValueAnimatedNode *valueNode = (RCTValueAnimatedNode *)_animationNodes[nodeTag];
NSString *type = config[@"type"];
- idanimationDriver;
+ id animationDriver;
if ([type isEqual:@"frames"]) {
animationDriver = [[RCTFrameAnimation alloc] initWithId:animationId
@@ -233,7 +233,7 @@ - (void)startAnimatingNode:(nonnull NSNumber *)animationId
- (void)stopAnimation:(nonnull NSNumber *)animationId
{
- for (iddriver in _activeAnimations) {
+ for (id driver in _activeAnimations) {
if ([driver.animationId isEqual:animationId]) {
[driver removeAnimation];
[_activeAnimations removeObject:driver];
@@ -264,15 +264,36 @@ - (void)addAnimatedEventToView:(nonnull NSNumber *)viewTag
NSArray *eventPath = [RCTConvert NSStringArray:eventMapping[@"nativeEventPath"]];
RCTEventAnimation *driver =
- [[RCTEventAnimation alloc] initWithEventPath:eventPath valueNode:(RCTValueAnimatedNode *)node];
+ [[RCTEventAnimation alloc] initWithEventPath:eventPath valueNode:(RCTValueAnimatedNode *)node];
- _eventDrivers[[NSString stringWithFormat:@"%@%@", viewTag, eventName]] = driver;
+ NSString *key = [NSString stringWithFormat:@"%@%@", viewTag, eventName];
+ if (_eventDrivers[key] != nil) {
+ [_eventDrivers[key] addObject:driver];
+ } else {
+ NSMutableArray *drivers = [NSMutableArray new];
+ [drivers addObject:driver];
+ _eventDrivers[key] = drivers;
+ }
}
- (void)removeAnimatedEventFromView:(nonnull NSNumber *)viewTag
eventName:(nonnull NSString *)eventName
+ animatedNodeTag:(nonnull NSNumber *)animatedNodeTag
{
- [_eventDrivers removeObjectForKey:[NSString stringWithFormat:@"%@%@", viewTag, eventName]];
+ NSString *key = [NSString stringWithFormat:@"%@%@", viewTag, eventName];
+ if (_eventDrivers[key] != nil) {
+ if (_eventDrivers[key].count == 1) {
+ [_eventDrivers removeObjectForKey:key];
+ } else {
+ NSMutableArray *driversForKey = _eventDrivers[key];
+ for (NSUInteger i = 0; i < driversForKey.count; i++) {
+ if (driversForKey[i].valueNode.nodeTag == animatedNodeTag) {
+ [driversForKey removeObjectAtIndex:i];
+ break;
+ }
+ }
+ }
+ }
}
- (void)handleAnimatedEvent:(id)event
@@ -282,9 +303,12 @@ - (void)handleAnimatedEvent:(id)event
}
NSString *key = [NSString stringWithFormat:@"%@%@", event.viewTag, event.eventName];
- RCTEventAnimation *driver = _eventDrivers[key];
- if (driver) {
- [driver updateWithEvent:event];
+ NSMutableArray *driversForKey = _eventDrivers[key];
+ if (driversForKey) {
+ for (RCTEventAnimation *driver in driversForKey) {
+ [driver updateWithEvent:event];
+ }
+
[self updateAnimations];
}
}
@@ -337,13 +361,13 @@ - (void)stopAnimationLoop
- (void)stepAnimations
{
- for (idanimationDriver in _activeAnimations) {
+ for (id animationDriver in _activeAnimations) {
[animationDriver stepAnimation];
}
[self updateAnimations];
- for (idanimationDriver in [_activeAnimations copy]) {
+ for (id animationDriver in [_activeAnimations copy]) {
if (animationDriver.animationHasFinished) {
[animationDriver removeAnimation];
[_activeAnimations removeObject:animationDriver];
diff --git a/Libraries/NavigationExperimental/NavigationExperimental.js b/Libraries/NavigationExperimental/NavigationExperimental.js
index 4f1bb068ce14a8..c4fd955c8fd34c 100644
--- a/Libraries/NavigationExperimental/NavigationExperimental.js
+++ b/Libraries/NavigationExperimental/NavigationExperimental.js
@@ -18,6 +18,18 @@ const NavigationPropTypes = require('NavigationPropTypes');
const NavigationStateUtils = require('NavigationStateUtils');
const NavigationTransitioner = require('NavigationTransitioner');
+const warning = require('fbjs/lib/warning');
+
+// This warning will only be reached if the user has required the module
+warning(
+ false,
+ 'NavigationExperimental is deprecated and will be removed in a future ' +
+ 'version of React Native. The NavigationExperimental views live on in ' +
+ 'the React-Navigation project, which also makes it easy to declare ' +
+ 'navigation logic for your app. Learn more at https://reactnavigation.org/'
+);
+
+
const NavigationExperimental = {
// Core
StateUtils: NavigationStateUtils,
diff --git a/Libraries/Network/RCTNetworking.ios.js b/Libraries/Network/RCTNetworking.ios.js
index b67049036d5628..dd569a07d36aca 100644
--- a/Libraries/Network/RCTNetworking.ios.js
+++ b/Libraries/Network/RCTNetworking.ios.js
@@ -33,7 +33,8 @@ class RCTNetworking extends NativeEventEmitter {
responseType: 'text' | 'base64',
incrementalUpdates: boolean,
timeout: number,
- callback: (requestId: number) => any
+ callback: (requestId: number) => any,
+ withCredentials: boolean
) {
const body = convertRequestBody(data);
RCTNetworkingNative.sendRequest({
@@ -43,7 +44,8 @@ class RCTNetworking extends NativeEventEmitter {
headers,
responseType,
incrementalUpdates,
- timeout
+ timeout,
+ withCredentials
}, callback);
}
diff --git a/Libraries/Network/RCTNetworking.mm b/Libraries/Network/RCTNetworking.mm
index 67379f96b59865..4a7f7ccd668743 100644
--- a/Libraries/Network/RCTNetworking.mm
+++ b/Libraries/Network/RCTNetworking.mm
@@ -230,6 +230,7 @@ - (RCTURLRequestCancellationBlock)buildRequest:(NSDictionary *)q
request.HTTPMethod = [RCTConvert NSString:RCTNilIfNull(query[@"method"])].uppercaseString ?: @"GET";
request.allHTTPHeaderFields = [self stripNullsInRequestHeaders:[RCTConvert NSDictionary:query[@"headers"]]];
request.timeoutInterval = [RCTConvert NSTimeInterval:query[@"timeout"]];
+ request.HTTPShouldHandleCookies = [RCTConvert BOOL:query[@"withCredentials"]];
NSDictionary *data = [RCTConvert NSDictionary:RCTNilIfNull(query[@"data"])];
NSString *trackingName = data[@"trackingName"];
if (trackingName) {
diff --git a/Libraries/Network/XMLHttpRequest.js b/Libraries/Network/XMLHttpRequest.js
index bf6d30191a2e33..92669b8b2d81b9 100644
--- a/Libraries/Network/XMLHttpRequest.js
+++ b/Libraries/Network/XMLHttpRequest.js
@@ -81,6 +81,7 @@ class XMLHttpRequestEventTarget extends EventTarget(...REQUEST_EVENTS) {
onprogress: ?Function;
ontimeout: ?Function;
onerror: ?Function;
+ onabort: ?Function;
onloadend: ?Function;
}
@@ -109,6 +110,7 @@ class XMLHttpRequest extends EventTarget(...XHR_EVENTS) {
onprogress: ?Function;
ontimeout: ?Function;
onerror: ?Function;
+ onabort: ?Function;
onloadend: ?Function;
onreadystatechange: ?Function;
@@ -117,6 +119,7 @@ class XMLHttpRequest extends EventTarget(...XHR_EVENTS) {
status: number = 0;
timeout: number = 0;
responseURL: ?string;
+ withCredentials: boolean = false
upload: XMLHttpRequestEventTarget = new XMLHttpRequestEventTarget();
@@ -499,6 +502,7 @@ class XMLHttpRequest extends EventTarget(...XHR_EVENTS) {
incrementalEvents,
this.timeout,
this.__didCreateRequest.bind(this),
+ this.withCredentials
);
}
diff --git a/Libraries/Promise.js b/Libraries/Promise.js
index 7b52e135cc33f9..615b990b1b17a0 100644
--- a/Libraries/Promise.js
+++ b/Libraries/Promise.js
@@ -13,14 +13,26 @@
const Promise = require('fbjs/lib/Promise.native');
+const prettyFormat = require('pretty-format');
+
if (__DEV__) {
require('promise/setimmediate/rejection-tracking').enable({
allRejections: true,
onUnhandled: (id, error = {}) => {
- const {message = null, stack = null} = error;
+ let message: string;
+ let stack: ?string;
+
+ const stringValue = Object.prototype.toString.call(error);
+ if (stringValue === '[object Error]') {
+ message = Error.prototype.toString.call(error);
+ stack = error.stack;
+ } else {
+ message = prettyFormat(error);
+ }
+
const warning =
`Possible Unhandled Promise Rejection (id: ${id}):\n` +
- (message == null ? '' : `${message}\n`) +
+ `${message}\n` +
(stack == null ? '' : stack);
console.warn(warning);
},
diff --git a/Libraries/RCTTest/SnapshotViewIOS.ios.js b/Libraries/RCTTest/SnapshotViewIOS.ios.js
index 869a2914a2e22e..f14ef0a7d547e1 100644
--- a/Libraries/RCTTest/SnapshotViewIOS.ios.js
+++ b/Libraries/RCTTest/SnapshotViewIOS.ios.js
@@ -25,6 +25,7 @@ class SnapshotViewIOS extends React.Component {
testIdentifier?: string,
};
+ // $FlowFixMe(>=0.41.0)
static propTypes = {
...View.propTypes,
// A callback when the Snapshot view is ready to be compared
diff --git a/Libraries/ReactNative/YellowBox.js b/Libraries/ReactNative/YellowBox.js
index e8be755b0faed2..2042431c3f4824 100644
--- a/Libraries/ReactNative/YellowBox.js
+++ b/Libraries/ReactNative/YellowBox.js
@@ -394,16 +394,22 @@ const textColor = 'white';
const rowGutter = 1;
const rowHeight = 46;
+// For unknown reasons, setting elevation: Number.MAX_VALUE causes remote debugging to
+// hang on iOS (some sort of overflow maybe). Setting it to Number.MAX_SAFE_INTEGER fixes the iOS issue, but since
+// elevation is an android-only style property we might as well remove it altogether for iOS.
+// See: https://github.com/facebook/react-native/issues/12223
+const elevation = Platform.OS === 'android' ? Number.MAX_SAFE_INTEGER : undefined;
+
var styles = StyleSheet.create({
fullScreen: {
height: '100%',
- elevation: Number.MAX_VALUE
+ elevation: elevation
},
inspector: {
backgroundColor: backgroundColor(0.95),
height: '100%',
paddingTop: 5,
- elevation: Number.MAX_VALUE
+ elevation:elevation
},
inspectorButtons: {
flexDirection: 'row',
@@ -451,7 +457,7 @@ var styles = StyleSheet.create({
left: 0,
right: 0,
bottom: 0,
- elevation: Number.MAX_VALUE
+ elevation: elevation
},
listRow: {
backgroundColor: backgroundColor(0.95),
diff --git a/Libraries/ReactNative/renderApplication.js b/Libraries/ReactNative/renderApplication.js
index 26cf1bed7f143a..0175b5c6f58e6e 100644
--- a/Libraries/ReactNative/renderApplication.js
+++ b/Libraries/ReactNative/renderApplication.js
@@ -18,8 +18,8 @@ var ReactNative = require('ReactNative');
var invariant = require('fbjs/lib/invariant');
-// require BackAndroid so it sets the default handler that exits the app if no listeners respond
-require('BackAndroid');
+// require BackHandler so it sets the default handler that exits the app if no listeners respond
+require('BackHandler');
function renderApplication(
RootComponent: ReactClass,
diff --git a/Libraries/StyleSheet/LayoutPropTypes.js b/Libraries/StyleSheet/LayoutPropTypes.js
index d8790f2af8f900..a8ab32c0772d72 100644
--- a/Libraries/StyleSheet/LayoutPropTypes.js
+++ b/Libraries/StyleSheet/LayoutPropTypes.js
@@ -27,6 +27,13 @@ var ReactPropTypes = require('React').PropTypes;
* algorithm and affect the positioning and sizing of views.
*/
var LayoutPropTypes = {
+ /** `display` sets the display type of this component.
+ *
+ * It works similarly to `display` in CSS, but only support 'flex' and 'none'.
+ * 'flex' is the default.
+ */
+ display: ReactPropTypes.string,
+
/** `width` sets the width of this component.
*
* It works similarly to `width` in CSS, but in React Native you
@@ -402,6 +409,20 @@ var LayoutPropTypes = {
'baseline'
]),
+ /** `alignContent` controls how a rows align in the cross direction,
+ * overriding the `alignContent` of the parent.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/align-content
+ * for more details.
+ */
+ alignContent: ReactPropTypes.oneOf([
+ 'flex-start',
+ 'flex-end',
+ 'center',
+ 'stretch',
+ 'space-between',
+ 'space-around'
+ ]),
+
/** `overflow` controls how a children are measured and displayed.
* `overflow: hidden` causes views to be clipped while `overflow: scroll`
* causes views to be measured independently of their parents main axis.`
diff --git a/React/Views/RCTMapAnnotation.m b/Libraries/Text/RCTShadowTextField.h
similarity index 80%
rename from React/Views/RCTMapAnnotation.m
rename to Libraries/Text/RCTShadowTextField.h
index 0b90fe8ab1e8b1..543f7fb349a0ef 100644
--- a/React/Views/RCTMapAnnotation.m
+++ b/Libraries/Text/RCTShadowTextField.h
@@ -7,8 +7,8 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-#import "RCTMapAnnotation.h"
+#import
-@implementation RCTMapAnnotation
+@interface RCTShadowTextField : RCTShadowView
@end
diff --git a/React/Views/RCTMapOverlay.h b/Libraries/Text/RCTShadowTextField.m
similarity index 58%
rename from React/Views/RCTMapOverlay.h
rename to Libraries/Text/RCTShadowTextField.m
index a6fcdad5e4525e..3bc5929dc49c37 100644
--- a/React/Views/RCTMapOverlay.h
+++ b/Libraries/Text/RCTShadowTextField.m
@@ -7,12 +7,13 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-#import
+#import "RCTShadowTextField.h"
-@interface RCTMapOverlay : MKPolyline
+@implementation RCTShadowTextField
-@property (nonatomic, copy) NSString *identifier;
-@property (nonatomic, strong) UIColor *strokeColor;
-@property (nonatomic, assign) CGFloat lineWidth;
+- (BOOL)isYogaLeafNode
+{
+ return YES;
+}
@end
diff --git a/React/Views/RCTMapOverlay.m b/Libraries/Text/RCTShadowTextView.h
similarity index 80%
rename from React/Views/RCTMapOverlay.m
rename to Libraries/Text/RCTShadowTextView.h
index 2a52dd5b28fba4..e2c6f1e7ed45db 100644
--- a/React/Views/RCTMapOverlay.m
+++ b/Libraries/Text/RCTShadowTextView.h
@@ -7,8 +7,8 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-#import "RCTMapOverlay.h"
+#import
-@implementation RCTMapOverlay
+@interface RCTShadowTextView : RCTShadowView
@end
diff --git a/React/Views/RCTMapManager.h b/Libraries/Text/RCTShadowTextView.m
similarity index 74%
rename from React/Views/RCTMapManager.h
rename to Libraries/Text/RCTShadowTextView.m
index fdf678efd3ae9c..d3e3602edc4073 100644
--- a/React/Views/RCTMapManager.h
+++ b/Libraries/Text/RCTShadowTextView.m
@@ -7,8 +7,13 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-#import
+#import "RCTShadowTextView.h"
-@interface RCTMapManager : RCTViewManager
+@implementation RCTShadowTextView
+
+- (BOOL)isYogaLeafNode
+{
+ return YES;
+}
@end
diff --git a/Libraries/Text/RCTText.xcodeproj/project.pbxproj b/Libraries/Text/RCTText.xcodeproj/project.pbxproj
index 8e7ee1f1a20598..e2cfafd68291b7 100644
--- a/Libraries/Text/RCTText.xcodeproj/project.pbxproj
+++ b/Libraries/Text/RCTText.xcodeproj/project.pbxproj
@@ -27,6 +27,10 @@
58B511D01A9E6C5C00147676 /* RCTShadowText.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511CB1A9E6C5C00147676 /* RCTShadowText.m */; };
58B511D11A9E6C5C00147676 /* RCTTextManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511CD1A9E6C5C00147676 /* RCTTextManager.m */; };
58B512161A9E6EFF00147676 /* RCTText.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B512141A9E6EFF00147676 /* RCTText.m */; };
+ 59F60E911E661BDD0081153B /* RCTShadowTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 59F60E8E1E661BDD0081153B /* RCTShadowTextField.m */; };
+ 59F60E921E661BDD0081153B /* RCTShadowTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 59F60E8E1E661BDD0081153B /* RCTShadowTextField.m */; };
+ 59F60E931E661BDD0081153B /* RCTShadowTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 59F60E901E661BDD0081153B /* RCTShadowTextView.m */; };
+ 59F60E941E661BDD0081153B /* RCTShadowTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 59F60E901E661BDD0081153B /* RCTShadowTextView.m */; };
AF3225F91DE5574F00D3E7E7 /* RCTConvert+Text.m in Sources */ = {isa = PBXBuildFile; fileRef = AF3225F81DE5574F00D3E7E7 /* RCTConvert+Text.m */; };
AF3225FA1DE5574F00D3E7E7 /* RCTConvert+Text.m in Sources */ = {isa = PBXBuildFile; fileRef = AF3225F81DE5574F00D3E7E7 /* RCTConvert+Text.m */; };
/* End PBXBuildFile section */
@@ -54,6 +58,10 @@
58B511CD1A9E6C5C00147676 /* RCTTextManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTextManager.m; sourceTree = ""; };
58B512141A9E6EFF00147676 /* RCTText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTText.m; sourceTree = ""; };
58B512151A9E6EFF00147676 /* RCTText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTText.h; sourceTree = ""; };
+ 59F60E8D1E661BDD0081153B /* RCTShadowTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTShadowTextField.h; sourceTree = ""; };
+ 59F60E8E1E661BDD0081153B /* RCTShadowTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTShadowTextField.m; sourceTree = ""; };
+ 59F60E8F1E661BDD0081153B /* RCTShadowTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTShadowTextView.h; sourceTree = ""; };
+ 59F60E901E661BDD0081153B /* RCTShadowTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTShadowTextView.m; sourceTree = ""; };
AF3225F71DE5574F00D3E7E7 /* RCTConvert+Text.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+Text.h"; sourceTree = ""; };
AF3225F81DE5574F00D3E7E7 /* RCTConvert+Text.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+Text.m"; sourceTree = ""; };
/* End PBXFileReference section */
@@ -62,29 +70,33 @@
58B511921A9E6C1200147676 = {
isa = PBXGroup;
children = (
+ 58B5119C1A9E6C1200147676 /* Products */,
AF3225F71DE5574F00D3E7E7 /* RCTConvert+Text.h */,
AF3225F81DE5574F00D3E7E7 /* RCTConvert+Text.m */,
- 19FC5C861D41A4220090108F /* RCTTextSelection.h */,
- 19FC5C841D41A4120090108F /* RCTTextSelection.m */,
58B511C61A9E6C5C00147676 /* RCTRawTextManager.h */,
58B511C71A9E6C5C00147676 /* RCTRawTextManager.m */,
58B511C81A9E6C5C00147676 /* RCTShadowRawText.h */,
58B511C91A9E6C5C00147676 /* RCTShadowRawText.m */,
58B511CA1A9E6C5C00147676 /* RCTShadowText.h */,
58B511CB1A9E6C5C00147676 /* RCTShadowText.m */,
+ 59F60E8D1E661BDD0081153B /* RCTShadowTextField.h */,
+ 59F60E8E1E661BDD0081153B /* RCTShadowTextField.m */,
+ 59F60E8F1E661BDD0081153B /* RCTShadowTextView.h */,
+ 59F60E901E661BDD0081153B /* RCTShadowTextView.m */,
58B512151A9E6EFF00147676 /* RCTText.h */,
58B512141A9E6EFF00147676 /* RCTText.m */,
- 58B511CC1A9E6C5C00147676 /* RCTTextManager.h */,
- 58B511CD1A9E6C5C00147676 /* RCTTextManager.m */,
1362F0FC1B4D51F400E06D8C /* RCTTextField.h */,
1362F0FD1B4D51F400E06D8C /* RCTTextField.m */,
1362F0FE1B4D51F400E06D8C /* RCTTextFieldManager.h */,
1362F0FF1B4D51F400E06D8C /* RCTTextFieldManager.m */,
+ 58B511CC1A9E6C5C00147676 /* RCTTextManager.h */,
+ 58B511CD1A9E6C5C00147676 /* RCTTextManager.m */,
+ 19FC5C861D41A4220090108F /* RCTTextSelection.h */,
+ 19FC5C841D41A4120090108F /* RCTTextSelection.m */,
131B6ABC1AF0CD0600FFC3E0 /* RCTTextView.h */,
131B6ABD1AF0CD0600FFC3E0 /* RCTTextView.m */,
131B6ABE1AF0CD0600FFC3E0 /* RCTTextViewManager.h */,
131B6ABF1AF0CD0600FFC3E0 /* RCTTextViewManager.m */,
- 58B5119C1A9E6C1200147676 /* Products */,
);
indentWidth = 2;
sourceTree = "";
@@ -180,8 +192,10 @@
2D3B5F3B1D9B106F00451313 /* RCTTextView.m in Sources */,
2D3B5F3A1D9B106F00451313 /* RCTTextFieldManager.m in Sources */,
2D3B5F341D9B103100451313 /* RCTRawTextManager.m in Sources */,
+ 59F60E921E661BDD0081153B /* RCTShadowTextField.m in Sources */,
AF3225FA1DE5574F00D3E7E7 /* RCTConvert+Text.m in Sources */,
2D3B5F3C1D9B106F00451313 /* RCTTextViewManager.m in Sources */,
+ 59F60E941E661BDD0081153B /* RCTShadowTextView.m in Sources */,
2D3B5F331D9B102D00451313 /* RCTTextSelection.m in Sources */,
2D3B5F351D9B103300451313 /* RCTShadowRawText.m in Sources */,
);
@@ -198,8 +212,10 @@
1362F1001B4D51F400E06D8C /* RCTTextField.m in Sources */,
58B512161A9E6EFF00147676 /* RCTText.m in Sources */,
1362F1011B4D51F400E06D8C /* RCTTextFieldManager.m in Sources */,
+ 59F60E911E661BDD0081153B /* RCTShadowTextField.m in Sources */,
AF3225F91DE5574F00D3E7E7 /* RCTConvert+Text.m in Sources */,
131B6AC11AF0CD0600FFC3E0 /* RCTTextViewManager.m in Sources */,
+ 59F60E931E661BDD0081153B /* RCTShadowTextView.m in Sources */,
58B511CF1A9E6C5C00147676 /* RCTShadowRawText.m in Sources */,
58B511D01A9E6C5C00147676 /* RCTShadowText.m in Sources */,
);
diff --git a/Libraries/Text/RCTTextFieldManager.m b/Libraries/Text/RCTTextFieldManager.m
index 72e205ae417322..27287c32afc262 100644
--- a/Libraries/Text/RCTTextFieldManager.m
+++ b/Libraries/Text/RCTTextFieldManager.m
@@ -14,6 +14,7 @@
#import
#import "RCTConvert+Text.h"
+#import "RCTShadowTextField.h"
#import "RCTTextField.h"
@@ -21,6 +22,11 @@ @implementation RCTTextFieldManager
RCT_EXPORT_MODULE()
+- (RCTShadowView *)shadowView
+{
+ return [RCTShadowTextField new];
+}
+
- (UIView *)view
{
return [[RCTTextField alloc] initWithEventDispatcher:self.bridge.eventDispatcher];
diff --git a/Libraries/Text/RCTTextView.m b/Libraries/Text/RCTTextView.m
index 415c0df826b0c2..83cde446a19355 100644
--- a/Libraries/Text/RCTTextView.m
+++ b/Libraries/Text/RCTTextView.m
@@ -238,6 +238,7 @@ - (void)performPendingTextUpdate
[_textView layoutIfNeeded];
[self updatePlaceholderVisibility];
+ [self updateContentSize];
_blockTextShouldChange = NO;
}
diff --git a/Libraries/Text/RCTTextViewManager.m b/Libraries/Text/RCTTextViewManager.m
index c599526b9f968c..7b7f5d0473d422 100644
--- a/Libraries/Text/RCTTextViewManager.m
+++ b/Libraries/Text/RCTTextViewManager.m
@@ -15,12 +15,18 @@
#import
#import "RCTConvert+Text.h"
+#import "RCTShadowTextView.h"
#import "RCTTextView.h"
@implementation RCTTextViewManager
RCT_EXPORT_MODULE()
+- (RCTShadowView *)shadowView
+{
+ return [RCTShadowTextView new];
+}
+
- (UIView *)view
{
return [[RCTTextView alloc] initWithEventDispatcher:self.bridge.eventDispatcher];
diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js
index 1542c9aa503236..db3a22e878e13d 100644
--- a/Libraries/Text/Text.js
+++ b/Libraries/Text/Text.js
@@ -95,6 +95,7 @@ const viewConfig = {
* ```
*/
+// $FlowFixMe(>=0.41.0)
const Text = React.createClass({
propTypes: {
/**
@@ -248,6 +249,7 @@ const Text = React.createClass({
this._handlers = {
onStartShouldSetResponder: (): bool => {
const shouldSetFromProps = this.props.onStartShouldSetResponder &&
+ // $FlowFixMe(>=0.41.0)
this.props.onStartShouldSetResponder();
const setResponder = shouldSetFromProps || this._hasPressHandler();
if (setResponder && !this.touchableHandleActivePressIn) {
@@ -288,33 +290,44 @@ const Text = React.createClass({
return this.props.pressRetentionOffset || PRESS_RECT_OFFSET;
};
}
+ // $FlowFixMe(>=0.41.0)
return setResponder;
},
onResponderGrant: function(e: SyntheticEvent, dispatchID: string) {
+ // $FlowFixMe(>=0.41.0)
this.touchableHandleResponderGrant(e, dispatchID);
this.props.onResponderGrant &&
+ // $FlowFixMe(>=0.41.0)
this.props.onResponderGrant.apply(this, arguments);
}.bind(this),
onResponderMove: function(e: SyntheticEvent) {
+ // $FlowFixMe(>=0.41.0)
this.touchableHandleResponderMove(e);
this.props.onResponderMove &&
+ // $FlowFixMe(>=0.41.0)
this.props.onResponderMove.apply(this, arguments);
}.bind(this),
onResponderRelease: function(e: SyntheticEvent) {
+ // $FlowFixMe(>=0.41.0)
this.touchableHandleResponderRelease(e);
this.props.onResponderRelease &&
+ // $FlowFixMe(>=0.41.0)
this.props.onResponderRelease.apply(this, arguments);
}.bind(this),
onResponderTerminate: function(e: SyntheticEvent) {
+ // $FlowFixMe(>=0.41.0)
this.touchableHandleResponderTerminate(e);
this.props.onResponderTerminate &&
+ // $FlowFixMe(>=0.41.0)
this.props.onResponderTerminate.apply(this, arguments);
}.bind(this),
onResponderTerminationRequest: function(): bool {
// Allow touchable or props.onResponderTerminationRequest to deny
// the request
+ // $FlowFixMe(>=0.41.0)
var allowTermination = this.touchableHandleResponderTerminationRequest();
if (allowTermination && this.props.onResponderTerminationRequest) {
+ // $FlowFixMe(>=0.41.0)
allowTermination = this.props.onResponderTerminationRequest.apply(this, arguments);
}
return allowTermination;
diff --git a/Libraries/Utilities/BackAndroid.js b/Libraries/Utilities/BackAndroid.js
new file mode 100644
index 00000000000000..0289b34c65d82c
--- /dev/null
+++ b/Libraries/Utilities/BackAndroid.js
@@ -0,0 +1,49 @@
+/**
+ * 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.
+ *
+ * BackAndroid has been moved to BackHandler. This stub calls BackHandler methods
+ * after generating a warning to remind users to move to the new BackHandler module.
+ *
+ * @providesModule BackAndroid
+ */
+
+'use strict';
+
+var BackHandler = require('BackHandler');
+
+var warning = require('fbjs/lib/warning');
+
+/**
+ * Deprecated. Use BackHandler instead.
+ */
+var BackAndroid = {
+
+ exitApp: function() {
+ warning(false, 'BackAndroid is deprecated. Please use BackHandler instead.');
+ BackHandler.exitApp();
+ },
+
+ addEventListener: function (
+ eventName: BackPressEventName,
+ handler: Function
+ ): {remove: () => void} {
+ warning(false, 'BackAndroid is deprecated. Please use BackHandler instead.');
+ return BackHandler.addEventListener(eventName, handler);
+ },
+
+ removeEventListener: function(
+ eventName: BackPressEventName,
+ handler: Function
+ ): void {
+ warning(false, 'BackAndroid is deprecated. Please use BackHandler instead.');
+ BackHandler.removeEventListener(eventName, handler);
+ },
+
+};
+
+module.exports = BackAndroid;
diff --git a/Libraries/Utilities/BackAndroid.android.js b/Libraries/Utilities/BackHandler.android.js
similarity index 75%
rename from Libraries/Utilities/BackAndroid.android.js
rename to Libraries/Utilities/BackHandler.android.js
index c3295d927b37ef..d8ca9b5eb567c9 100644
--- a/Libraries/Utilities/BackAndroid.android.js
+++ b/Libraries/Utilities/BackHandler.android.js
@@ -6,7 +6,7 @@
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
- * @providesModule BackAndroid
+ * @providesModule BackHandler
*/
'use strict';
@@ -34,20 +34,29 @@ RCTDeviceEventEmitter.addListener(DEVICE_BACK_EVENT, function() {
}
if (invokeDefault) {
- BackAndroid.exitApp();
+ BackHandler.exitApp();
}
});
/**
- * Detect hardware back button presses, and programmatically invoke the default back button
+ * Detect hardware button presses for back navigation.
+ *
+ * Android: Detect hardware back button presses, and programmatically invoke the default back button
* functionality to exit the app if there are no listeners or if none of the listeners return true.
+ *
+ * tvOS: Detect presses of the menu button on the TV remote. (Still to be implemented:
+ * programmatically disable menu button handling
+ * functionality to exit the app if there are no listeners or if none of the listeners return true.)
+ *
+ * iOS: Not applicable.
+ *
* The event subscriptions are called in reverse order (i.e. last registered subscription first),
* and if one subscription returns true then subscriptions registered earlier will not be called.
*
* Example:
*
* ```javascript
- * BackAndroid.addEventListener('hardwareBackPress', function() {
+ * BackHandler.addEventListener('hardwareBackPress', function() {
* // this.onMainScreen and this.goBack are just examples, you need to use your own implementation here
* // Typically you would use the navigator here to go to the last state.
*
@@ -59,7 +68,7 @@ RCTDeviceEventEmitter.addListener(DEVICE_BACK_EVENT, function() {
* });
* ```
*/
-var BackAndroid = {
+var BackHandler = {
exitApp: function() {
DeviceEventManager.invokeDefaultBackPressHandler();
@@ -71,7 +80,7 @@ var BackAndroid = {
): {remove: () => void} {
_backPressSubscriptions.add(handler);
return {
- remove: () => BackAndroid.removeEventListener(eventName, handler),
+ remove: () => BackHandler.removeEventListener(eventName, handler),
};
},
@@ -84,4 +93,4 @@ var BackAndroid = {
};
-module.exports = BackAndroid;
+module.exports = BackHandler;
diff --git a/Libraries/Utilities/BackHandler.ios.js b/Libraries/Utilities/BackHandler.ios.js
new file mode 100644
index 00000000000000..958ec69e5c0558
--- /dev/null
+++ b/Libraries/Utilities/BackHandler.ios.js
@@ -0,0 +1,116 @@
+/**
+ * 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.
+ *
+ * On Apple TV, this implements back navigation using the TV remote's menu button.
+ * On iOS, this just implements a stub.
+ *
+ * @providesModule BackHandler
+ */
+
+'use strict';
+
+const Platform = require('Platform');
+const TVEventHandler = require('TVEventHandler');
+
+type BackPressEventName = $Enum<{
+ backPress: string,
+}>;
+
+function emptyFunction() {}
+
+/**
+ * Detect hardware button presses for back navigation.
+ *
+ * Android: Detect hardware back button presses, and programmatically invoke the default back button
+ * functionality to exit the app if there are no listeners or if none of the listeners return true.
+ *
+ * tvOS: Detect presses of the menu button on the TV remote. (Still to be implemented:
+ * programmatically disable menu button handling
+ * functionality to exit the app if there are no listeners or if none of the listeners return true.)
+ *
+ * iOS: Not applicable.
+ *
+ * The event subscriptions are called in reverse order (i.e. last registered subscription first),
+ * and if one subscription returns true then subscriptions registered earlier will not be called.
+ *
+ * Example:
+ *
+ * ```javascript
+ * BackHandler.addEventListener('hardwareBackPress', function() {
+ * // this.onMainScreen and this.goBack are just examples, you need to use your own implementation here
+ * // Typically you would use the navigator here to go to the last state.
+ *
+ * if (!this.onMainScreen()) {
+ * this.goBack();
+ * return true;
+ * }
+ * return false;
+ * });
+ * ```
+ */
+let BackHandler;
+
+if (Platform.isTVOS) {
+ const _tvEventHandler = new TVEventHandler();
+ var _backPressSubscriptions = new Set();
+
+ _tvEventHandler.enable(this, function(cmp, evt) {
+ if (evt && evt.eventType === 'menu') {
+ var backPressSubscriptions = new Set(_backPressSubscriptions);
+ var invokeDefault = true;
+ var subscriptions = [...backPressSubscriptions].reverse();
+ for (var i = 0; i < subscriptions.length; ++i) {
+ if (subscriptions[i]()) {
+ invokeDefault = false;
+ break;
+ }
+ }
+
+ if (invokeDefault) {
+ BackHandler.exitApp();
+ }
+ }
+ });
+
+ BackHandler = {
+ exitApp: emptyFunction,
+
+ addEventListener: function (
+ eventName: BackPressEventName,
+ handler: Function
+ ): {remove: () => void} {
+ _backPressSubscriptions.add(handler);
+ return {
+ remove: () => BackHandler.removeEventListener(eventName, handler),
+ };
+ },
+
+ removeEventListener: function(
+ eventName: BackPressEventName,
+ handler: Function
+ ): void {
+ _backPressSubscriptions.delete(handler);
+ },
+
+ };
+
+} else {
+
+ BackHandler = {
+ exitApp: emptyFunction,
+ addEventListener() {
+ return {
+ remove: emptyFunction,
+ };
+ },
+ removeEventListener: emptyFunction,
+ };
+
+}
+
+module.exports = BackHandler;
diff --git a/Libraries/Utilities/MatrixMath.js b/Libraries/Utilities/MatrixMath.js
index c3e088751288fa..e5f82ea1b3eab5 100755
--- a/Libraries/Utilities/MatrixMath.js
+++ b/Libraries/Utilities/MatrixMath.js
@@ -1,5 +1,10 @@
/**
- * Copyright 2004-present Facebook. All Rights Reserved.
+ * 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 MatrixMath
* @noflow
diff --git a/Libraries/Utilities/RCTLog.js b/Libraries/Utilities/RCTLog.js
index b08884ae93ab44..9f218c91787c2c 100644
--- a/Libraries/Utilities/RCTLog.js
+++ b/Libraries/Utilities/RCTLog.js
@@ -11,11 +11,11 @@
*/
'use strict';
-var BatchedBridge = require('BatchedBridge');
+const BatchedBridge = require('BatchedBridge');
-var invariant = require('fbjs/lib/invariant');
+const invariant = require('fbjs/lib/invariant');
-var levelsMap = {
+const levelsMap = {
log: 'log',
info: 'info',
warn: 'warn',
@@ -25,18 +25,24 @@ var levelsMap = {
class RCTLog {
// level one of log, info, warn, error, mustfix
- static logIfNoNativeHook() {
- var args = Array.prototype.slice.call(arguments);
- var level = args.shift();
- var logFn = levelsMap[level];
+ static logIfNoNativeHook(...args) {
+ if (typeof global.nativeLoggingHook === 'undefined') {
+ // We already printed in xcode, so only log here if using a js debugger
+ RCTLog.logToConsole(...args);
+ }
+
+ return true;
+ }
+
+ // Log to console regardless of nativeLoggingHook
+ static logToConsole(level, ...args) {
+ const logFn = levelsMap[level];
invariant(
logFn,
'Level "' + level + '" not one of ' + Object.keys(levelsMap)
);
- if (typeof global.nativeLoggingHook === 'undefined') {
- // We already printed in xcode, so only log here if using a js debugger
- console[logFn].apply(console, args);
- }
+
+ console[logFn](...args);
return true;
}
diff --git a/Libraries/Utilities/buildStyleInterpolator.js b/Libraries/Utilities/buildStyleInterpolator.js
index 195c29a7cd6119..06dee18987239e 100644
--- a/Libraries/Utilities/buildStyleInterpolator.js
+++ b/Libraries/Utilities/buildStyleInterpolator.js
@@ -1,5 +1,10 @@
/**
- * Copyright 2004-present Facebook. All Rights Reserved.
+ * 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 buildStyleInterpolator
*/
diff --git a/Libraries/Utilities/differ/sizesDiffer.js b/Libraries/Utilities/differ/sizesDiffer.js
index a431cd072273c8..7b24ea52f8dc43 100644
--- a/Libraries/Utilities/differ/sizesDiffer.js
+++ b/Libraries/Utilities/differ/sizesDiffer.js
@@ -1,5 +1,10 @@
/**
- * Copyright 2004-present Facebook. All Rights Reserved.
+ * 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 sizesDiffer
*/
diff --git a/Libraries/Utilities/dismissKeyboard.js b/Libraries/Utilities/dismissKeyboard.js
index d8949e8b306219..183fa4a88caf3a 100644
--- a/Libraries/Utilities/dismissKeyboard.js
+++ b/Libraries/Utilities/dismissKeyboard.js
@@ -1,5 +1,10 @@
/**
- * Copyright 2004-present Facebook. All Rights Reserved.
+ * 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 dismissKeyboard
*
diff --git a/Libraries/react-native/react-native-implementation.js b/Libraries/react-native/react-native-implementation.js
index 0c5f44e4c266c1..d11a202215d013 100644
--- a/Libraries/react-native/react-native-implementation.js
+++ b/Libraries/react-native/react-native-implementation.js
@@ -34,12 +34,12 @@ const ReactNative = {
get Button() { return require('Button'); },
get DatePickerIOS() { return require('DatePickerIOS'); },
get DrawerLayoutAndroid() { return require('DrawerLayoutAndroid'); },
+ get FlatList() { return require('FlatList'); },
get Image() { return require('Image'); },
get ImageEditor() { return require('ImageEditor'); },
get ImageStore() { return require('ImageStore'); },
get KeyboardAvoidingView() { return require('KeyboardAvoidingView'); },
get ListView() { return require('ListView'); },
- get MapView() { return require('MapView'); },
get Modal() { return require('Modal'); },
get Navigator() { return require('Navigator'); },
get NavigatorIOS() { return require('NavigatorIOS'); },
@@ -48,6 +48,7 @@ const ReactNative = {
get ProgressBarAndroid() { return require('ProgressBarAndroid'); },
get ProgressViewIOS() { return require('ProgressViewIOS'); },
get ScrollView() { return require('ScrollView'); },
+ get SectionList() { return require('SectionList'); },
get SegmentedControlIOS() { return require('SegmentedControlIOS'); },
get Slider() { return require('Slider'); },
get SnapshotViewIOS() { return require('SnapshotViewIOS'); },
@@ -67,6 +68,7 @@ const ReactNative = {
get TouchableWithoutFeedback() { return require('TouchableWithoutFeedback'); },
get View() { return require('View'); },
get ViewPagerAndroid() { return require('ViewPagerAndroid'); },
+ get VirtualizedList() { return require('VirtualizedList'); },
get WebView() { return require('WebView'); },
// APIs
@@ -78,7 +80,8 @@ const ReactNative = {
get AppRegistry() { return require('AppRegistry'); },
get AppState() { return require('AppState'); },
get AsyncStorage() { return require('AsyncStorage'); },
- get BackAndroid() { return require('BackAndroid'); },
+ get BackAndroid() { return require('BackAndroid'); }, // deprecated: use BackHandler instead
+ get BackHandler() { return require('BackHandler'); },
get CameraRoll() { return require('CameraRoll'); },
get Clipboard() { return require('Clipboard'); },
get DatePickerAndroid() { return require('DatePickerAndroid'); },
@@ -103,6 +106,7 @@ const ReactNative = {
get StyleSheet() { return require('StyleSheet'); },
get Systrace() { return require('Systrace'); },
get TimePickerAndroid() { return require('TimePickerAndroid'); },
+ get TVEventHandler() { return require('TVEventHandler'); },
get UIManager() { return require('UIManager'); },
get Vibration() { return require('Vibration'); },
get VibrationIOS() { return require('VibrationIOS'); },
diff --git a/React.podspec b/React.podspec
index a00afd5786aa27..e6352b3fd821d2 100644
--- a/React.podspec
+++ b/React.podspec
@@ -60,7 +60,7 @@ Pod::Spec.new do |s|
end
s.subspec "jschelpers" do |ss|
- ss.source_files = "ReactCommon/jschelpers/{JavaScriptCore,JSCWrapper}.{cpp,h}"
+ ss.source_files = "ReactCommon/jschelpers/{JavaScriptCore,JSCWrapper}.{cpp,h}", "ReactCommon/jschelpers/systemJSCWrapper.cpp"
ss.private_header_files = "ReactCommon/jschelpers/{JavaScriptCore,JSCWrapper}.h"
ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "$(PODS_TARGET_SRCROOT)/ReactCommon" }
ss.framework = "JavaScriptCore"
diff --git a/React/Base/RCTBridgeModule.h b/React/Base/RCTBridgeModule.h
index 6eb24bdb9d338b..4bfa4b3210a5d4 100644
--- a/React/Base/RCTBridgeModule.h
+++ b/React/Base/RCTBridgeModule.h
@@ -154,7 +154,7 @@ RCT_EXTERN void RCTRegisterModule(Class); \
*/
#define RCT_REMAP_METHOD(js_name, method) \
RCT_EXTERN_REMAP_METHOD(js_name, method) \
- - (void)method
+ - (void)method;
/**
* Use this macro in a private Objective-C implementation file to automatically
diff --git a/React/Base/RCTConvert.h b/React/Base/RCTConvert.h
index 57e8333dfd27db..dbd4d1f7b8b5a0 100644
--- a/React/Base/RCTConvert.h
+++ b/React/Base/RCTConvert.h
@@ -112,6 +112,7 @@ typedef id NSPropertyList;
typedef BOOL css_backface_visibility_t;
+ (YGOverflow)YGOverflow:(id)json;
++ (YGDisplay)YGDisplay:(id)json;
+ (css_backface_visibility_t)css_backface_visibility_t:(id)json;
+ (YGFlexDirection)YGFlexDirection:(id)json;
+ (YGJustify)YGJustify:(id)json;
diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m
index d8a0e9df2ce370..256fd854bc6e1f 100644
--- a/React/Base/RCTConvert.m
+++ b/React/Base/RCTConvert.m
@@ -507,7 +507,9 @@ + (YGValue)YGValue:(id)json
return (YGValue) { [json floatValue], YGUnitPoint };
} else if ([json isKindOfClass:[NSString class]]) {
NSString *s = (NSString *) json;
- if ([s hasSuffix:@"%"]) {
+ if ([s isEqualToString:@"auto"]) {
+ return (YGValue) { YGUndefined, YGUnitAuto };
+ } else if ([s hasSuffix:@"%"]) {
return (YGValue) { [[s substringToIndex:s.length] floatValue], YGUnitPercent };
} else {
RCTLogConvertError(json, @"a YGValue. Did you forget the % or pt suffix?");
@@ -643,6 +645,11 @@ + (NSPropertyList)NSPropertyList:(id)json
@"scroll": @(YGOverflowScroll),
}), YGOverflowVisible, intValue)
+RCT_ENUM_CONVERTER(YGDisplay, (@{
+ @"flex": @(YGDisplayFlex),
+ @"none": @(YGDisplayNone),
+}), YGDisplayFlex, intValue)
+
RCT_ENUM_CONVERTER(YGFlexDirection, (@{
@"row": @(YGFlexDirectionRow),
@"row-reverse": @(YGFlexDirectionRowReverse),
@@ -664,7 +671,9 @@ + (NSPropertyList)NSPropertyList:(id)json
@"center": @(YGAlignCenter),
@"auto": @(YGAlignAuto),
@"stretch": @(YGAlignStretch),
- @"baseline": @(YGAlignBaseline)
+ @"baseline": @(YGAlignBaseline),
+ @"space-between": @(YGAlignSpaceBetween),
+ @"space-around": @(YGAlignSpaceAround)
}), YGAlignFlexStart, intValue)
RCT_ENUM_CONVERTER(YGDirection, (@{
diff --git a/React/Base/RCTRootContentView.h b/React/Base/RCTRootContentView.h
index 5092b5d3e63817..f405a85506cb33 100644
--- a/React/Base/RCTRootContentView.h
+++ b/React/Base/RCTRootContentView.h
@@ -22,6 +22,7 @@
@property (nonatomic, readonly, strong) RCTTouchHandler *touchHandler;
@property (nonatomic, assign) BOOL passThroughTouches;
@property (nonatomic, assign) RCTRootViewSizeFlexibility sizeFlexibility;
+@property (nonatomic, readonly) CGSize availableSize;
- (instancetype)initWithFrame:(CGRect)frame
bridge:(RCTBridge *)bridge
diff --git a/React/Base/RCTRootContentView.m b/React/Base/RCTRootContentView.m
index 995a71f708d0c4..f4fb62b5320649 100644
--- a/React/Base/RCTRootContentView.m
+++ b/React/Base/RCTRootContentView.m
@@ -72,20 +72,22 @@ - (void)setSizeFlexibility:(RCTRootViewSizeFlexibility)sizeFlexibility
[self setNeedsLayout];
}
-- (void)updateAvailableSize
+- (CGSize)availableSize
{
- if (!self.reactTag || !_bridge.isValid) {
- return;
- }
-
CGSize size = self.bounds.size;
- CGSize availableSize =
- CGSizeMake(
+ return CGSizeMake(
_sizeFlexibility & RCTRootViewSizeFlexibilityWidth ? INFINITY : size.width,
_sizeFlexibility & RCTRootViewSizeFlexibilityHeight ? INFINITY : size.height
);
+}
+
+- (void)updateAvailableSize
+{
+ if (!self.reactTag || !_bridge.isValid) {
+ return;
+ }
- [_bridge.uiManager setAvailableSize:availableSize forRootView:self];
+ [_bridge.uiManager setAvailableSize:self.availableSize forRootView:self];
}
- (void)setBackgroundColor:(UIColor *)backgroundColor
diff --git a/React/Base/RCTRootView.m b/React/Base/RCTRootView.m
index 839640a8fbe482..db1ed02343c415 100644
--- a/React/Base/RCTRootView.m
+++ b/React/Base/RCTRootView.m
@@ -153,10 +153,22 @@ - (void)setPassThroughTouches:(BOOL)passThroughTouches
- (CGSize)sizeThatFits:(CGSize)size
{
- return CGSizeMake(
- _sizeFlexibility & RCTRootViewSizeFlexibilityWidth ? MIN(_intrinsicContentSize.width, size.width) : size.width,
- _sizeFlexibility & RCTRootViewSizeFlexibilityHeight ? MIN(_intrinsicContentSize.height, size.height) : size.height
- );
+ CGSize fitSize = _intrinsicContentSize;
+ CGSize currentSize = self.bounds.size;
+
+ // Following the current `size` and current `sizeFlexibility` policy.
+ fitSize = CGSizeMake(
+ _sizeFlexibility & RCTRootViewSizeFlexibilityWidth ? fitSize.width : currentSize.width,
+ _sizeFlexibility & RCTRootViewSizeFlexibilityHeight ? fitSize.height : currentSize.height
+ );
+
+ // Following the given size constraints.
+ fitSize = CGSizeMake(
+ MIN(size.width, fitSize.width),
+ MIN(size.height, fitSize.height)
+ );
+
+ return fitSize;
}
- (void)layoutSubviews
diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm
index 02f65e2a559a87..431c59f4f8b040 100644
--- a/React/CxxBridge/RCTCxxBridge.mm
+++ b/React/CxxBridge/RCTCxxBridge.mm
@@ -1137,6 +1137,10 @@ - (void)enqueueJSCall:(NSString *)module method:(NSString *)method args:(NSArray
*/
- (void)enqueueCallback:(NSNumber *)cbID args:(NSArray *)args
{
+ if (!self.valid) {
+ return;
+ }
+
/**
* AnyThread
*/
diff --git a/React/Modules/RCTDevSettings.mm b/React/Modules/RCTDevSettings.mm
index b41733683c3d31..171b2532094946 100644
--- a/React/Modules/RCTDevSettings.mm
+++ b/React/Modules/RCTDevSettings.mm
@@ -228,8 +228,9 @@ - (void)_remoteDebugSettingDidChange
{
// This value is passed as a command-line argument, so fall back to reading from NSUserDefaults directly
NSString *executorOverride = [[NSUserDefaults standardUserDefaults] stringForKey:kRCTDevSettingExecutorOverrideClass];
- if (executorOverride) {
- self.executorClass = NSClassFromString(executorOverride);
+ Class executorOverrideClass = executorOverride ? NSClassFromString(executorOverride) : nil;
+ if (executorOverrideClass) {
+ self.executorClass = executorOverrideClass;
} else {
BOOL enabled = self.isRemoteDebuggingAvailable && self.isDebuggingRemotely;
self.executorClass = enabled ? objc_getClass("RCTWebSocketExecutor") : nil;
diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m
index 288f3d61e1b536..b672cafbe1046b 100644
--- a/React/Modules/RCTUIManager.m
+++ b/React/Modules/RCTUIManager.m
@@ -27,6 +27,7 @@
#import "RCTModuleData.h"
#import "RCTModuleMethod.h"
#import "RCTProfile.h"
+#import "RCTRootContentView.h"
#import "RCTRootShadowView.h"
#import "RCTRootViewInternal.h"
#import "RCTScrollableProtocol.h"
@@ -236,8 +237,13 @@ @implementation RCTUIManager
- (void)didReceiveNewContentSizeMultiplier
{
// Report the event across the bridge.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ [_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions"
+ body:RCTExportedDimensions(_bridge)];
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateContentSizeMultiplier"
body:@([_bridge.accessibilityManager multiplier])];
+#pragma clang diagnostic pop
dispatch_async(RCTGetUIManagerQueue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification
@@ -260,7 +266,7 @@ - (void)interfaceOrientationDidChange
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions"
- body:RCTExportedDimensions()];
+ body:RCTExportedDimensions(_bridge)];
#pragma clang diagnostic pop
}
@@ -376,7 +382,7 @@ - (dispatch_queue_t)methodQueue
return RCTGetUIManagerQueue();
}
-- (void)registerRootView:(UIView *)rootView
+- (void)registerRootView:(RCTRootContentView *)rootView
{
RCTAssertMainQueue();
@@ -388,6 +394,8 @@ - (void)registerRootView:(UIView *)rootView
RCTAssert(existingView == nil || existingView == rootView,
@"Expect all root views to have unique tag. Added %@ twice", reactTag);
+ CGSize availableSize = rootView.availableSize;
+
// Register view
_viewRegistry[reactTag] = rootView;
@@ -398,6 +406,7 @@ - (void)registerRootView:(UIView *)rootView
}
RCTRootShadowView *shadowView = [RCTRootShadowView new];
+ shadowView.availableSize = availableSize;
shadowView.reactTag = reactTag;
shadowView.backgroundColor = rootView.backgroundColor;
shadowView.viewName = NSStringFromClass([rootView class]);
@@ -1541,23 +1550,26 @@ static void RCTMeasureLayout(RCTShadowView *view,
constants[@"customBubblingEventTypes"] = bubblingEvents;
constants[@"customDirectEventTypes"] = directEvents;
- constants[@"Dimensions"] = RCTExportedDimensions();
+ constants[@"Dimensions"] = RCTExportedDimensions(_bridge);
return constants;
}
-static NSDictionary *RCTExportedDimensions()
+static NSDictionary *RCTExportedDimensions(RCTBridge *bridge)
{
RCTAssertMainQueue();
// Don't use RCTScreenSize since it the interface orientation doesn't apply to it
CGRect screenSize = [[UIScreen mainScreen] bounds];
+ NSDictionary *dims = @{
+ @"width": @(screenSize.size.width),
+ @"height": @(screenSize.size.height),
+ @"scale": @(RCTScreenScale()),
+ @"fontScale": @(bridge.accessibilityManager.multiplier)
+ };
return @{
- @"window": @{
- @"width": @(screenSize.size.width),
- @"height": @(screenSize.size.height),
- @"scale": @(RCTScreenScale()),
- },
+ @"window": dims,
+ @"screen": dims
};
}
@@ -1580,11 +1592,6 @@ static void RCTMeasureLayout(RCTShadowView *view,
}];
}
-RCT_EXPORT_METHOD(getContentSizeMultiplier:(nonnull RCTResponseSenderBlock)callback)
-{
- callback(@[@(_bridge.accessibilityManager.multiplier)]);
-}
-
- (void)rootViewForReactTag:(NSNumber *)reactTag withCompletion:(void (^)(UIView *view))completion
{
RCTAssertMainQueue();
@@ -1656,6 +1663,12 @@ - (void)setFrame:(CGRect)frame forView:(UIView *)view
[self setSize:frame.size forView:view];
}
+RCT_EXPORT_METHOD(getContentSizeMultiplier:(nonnull RCTResponseSenderBlock)callback)
+{
+ RCTLogWarn(@"`getContentSizeMultiplier` is deprecated. Instead, use `PixelRatio.getFontScale()` and listen to the `didUpdateDimensions` event.");
+ callback(@[@(_bridge.accessibilityManager.multiplier)]);
+}
+
@end
@implementation RCTBridge (RCTUIManager)
diff --git a/React/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj
index 43c3a4497e2360..1e2d1be93f3a55 100644
--- a/React/React.xcodeproj/project.pbxproj
+++ b/React/React.xcodeproj/project.pbxproj
@@ -19,7 +19,6 @@
1339578B1DF76D3500EC27BE /* Yoga.h in Headers */ = {isa = PBXBuildFile; fileRef = 130A77081DF767AF001F9587 /* Yoga.h */; };
133CAE8E1B8E5CFD00F6AD92 /* RCTDatePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 133CAE8D1B8E5CFD00F6AD92 /* RCTDatePicker.m */; };
13456E931ADAD2DE009F94A7 /* RCTConvert+CoreLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 13456E921ADAD2DE009F94A7 /* RCTConvert+CoreLocation.m */; };
- 13456E961ADAD482009F94A7 /* RCTConvert+MapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 13456E951ADAD482009F94A7 /* RCTConvert+MapKit.m */; };
134FCB3D1A6E7F0800051CC8 /* RCTJSCExecutor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 134FCB3A1A6E7F0800051CC8 /* RCTJSCExecutor.mm */; };
13513F3C1B1F43F400FCE529 /* RCTProgressViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13513F3B1B1F43F400FCE529 /* RCTProgressViewManager.m */; };
13723B501A82FD3C00F88898 /* RCTStatusBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13723B4F1A82FD3C00F88898 /* RCTStatusBarManager.m */; };
@@ -35,7 +34,6 @@
13AB5E021DF777F2001A8C30 /* Yoga.c in Sources */ = {isa = PBXBuildFile; fileRef = 130A77071DF767AF001F9587 /* Yoga.c */; };
13AB90C11B6FA36700713B4F /* RCTComponentData.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AB90C01B6FA36700713B4F /* RCTComponentData.m */; };
13AF20451AE707F9005F5298 /* RCTSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AF20441AE707F9005F5298 /* RCTSlider.m */; };
- 13AFBCA01C07247D00BBAEAA /* RCTMapOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AFBC9F1C07247D00BBAEAA /* RCTMapOverlay.m */; };
13B07FEF1A69327A00A75B9A /* RCTAlertManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FE81A69327A00A75B9A /* RCTAlertManager.m */; };
13B07FF01A69327A00A75B9A /* RCTExceptionsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FEA1A69327A00A75B9A /* RCTExceptionsManager.m */; };
13B07FF21A69327A00A75B9A /* RCTTiming.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FEE1A69327A00A75B9A /* RCTTiming.m */; };
@@ -47,7 +45,6 @@
13B0801D1A69489C00A75B9A /* RCTNavItemManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B080131A69489C00A75B9A /* RCTNavItemManager.m */; };
13B080201A69489C00A75B9A /* RCTActivityIndicatorViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B080191A69489C00A75B9A /* RCTActivityIndicatorViewManager.m */; };
13B080261A694A8400A75B9A /* RCTWrapperViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B080241A694A8400A75B9A /* RCTWrapperViewController.m */; };
- 13B202041BFB948C00C07393 /* RCTMapAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B202031BFB948C00C07393 /* RCTMapAnnotation.m */; };
13BB3D021BECD54500932C10 /* RCTImageSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BB3D011BECD54500932C10 /* RCTImageSource.m */; };
13BCE8091C99CB9D00DD7AAD /* RCTRootShadowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BCE8081C99CB9D00DD7AAD /* RCTRootShadowView.m */; };
13C156051AB1A2840079392D /* RCTWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13C156021AB1A2840079392D /* RCTWebView.m */; };
@@ -64,8 +61,6 @@
13E41EEB1C05CA0B00CD8DAC /* RCTProfileTrampoline-i386.S in Sources */ = {isa = PBXBuildFile; fileRef = 14BF717F1C04793D00C97D0C /* RCTProfileTrampoline-i386.S */; };
13F17A851B8493E5007D4C75 /* RCTRedBox.m in Sources */ = {isa = PBXBuildFile; fileRef = 13F17A841B8493E5007D4C75 /* RCTRedBox.m */; };
142014191B32094000CC17BA /* RCTPerformanceLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 142014171B32094000CC17BA /* RCTPerformanceLogger.m */; };
- 14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE21AAC4AE100FC20F4 /* RCTMap.m */; };
- 14435CE61AAC4AE100FC20F4 /* RCTMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE41AAC4AE100FC20F4 /* RCTMapManager.m */; };
1450FF861BCFF28A00208362 /* RCTProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF811BCFF28A00208362 /* RCTProfile.m */; };
1450FF871BCFF28A00208362 /* RCTProfileTrampoline-arm.S in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF821BCFF28A00208362 /* RCTProfileTrampoline-arm.S */; };
1450FF881BCFF28A00208362 /* RCTProfileTrampoline-arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF831BCFF28A00208362 /* RCTProfileTrampoline-arm64.S */; };
@@ -82,6 +77,8 @@
14F7A0F01BDA714B003C6C10 /* RCTFPSGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F7A0EF1BDA714B003C6C10 /* RCTFPSGraph.m */; };
191E3EBE1C29D9AF00C180A6 /* RCTRefreshControlManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 191E3EBD1C29D9AF00C180A6 /* RCTRefreshControlManager.m */; };
191E3EC11C29DC3800C180A6 /* RCTRefreshControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 191E3EC01C29DC3800C180A6 /* RCTRefreshControl.m */; };
+ 2638623A1E732AB60010FEBF /* systemJSCWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65F3E41D1E73031C009375BD /* systemJSCWrapper.cpp */; };
+ 2638623B1E732AB70010FEBF /* systemJSCWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65F3E41D1E73031C009375BD /* systemJSCWrapper.cpp */; };
2D074E381E609E65001D6DD0 /* RCTReconnectingWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = A12E9E281E5DEB860029001B /* RCTReconnectingWebSocket.h */; };
2D074E391E609E68001D6DD0 /* RCTSRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = A12E9E291E5DEB860029001B /* RCTSRWebSocket.h */; };
2D3B5E931D9B087300451313 /* RCTErrorInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */; };
@@ -133,12 +130,7 @@
2D3B5EC91D9B095C00451313 /* RCTBorderDrawing.m in Sources */ = {isa = PBXBuildFile; fileRef = 13CC8A811B17642100940AE7 /* RCTBorderDrawing.m */; };
2D3B5ECA1D9B095F00451313 /* RCTComponentData.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AB90C01B6FA36700713B4F /* RCTComponentData.m */; };
2D3B5ECB1D9B096200451313 /* RCTConvert+CoreLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 13456E921ADAD2DE009F94A7 /* RCTConvert+CoreLocation.m */; };
- 2D3B5ECC1D9B096500451313 /* RCTConvert+MapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 13456E951ADAD482009F94A7 /* RCTConvert+MapKit.m */; };
2D3B5ECF1D9B096F00451313 /* RCTFont.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D37B5811D522B190042D5B5 /* RCTFont.mm */; };
- 2D3B5ED01D9B097200451313 /* RCTMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE21AAC4AE100FC20F4 /* RCTMap.m */; };
- 2D3B5ED11D9B097500451313 /* RCTMapAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B202031BFB948C00C07393 /* RCTMapAnnotation.m */; };
- 2D3B5ED21D9B097800451313 /* RCTMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE41AAC4AE100FC20F4 /* RCTMapManager.m */; };
- 2D3B5ED31D9B097B00451313 /* RCTMapOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AFBC9F1C07247D00BBAEAA /* RCTMapOverlay.m */; };
2D3B5ED41D9B097D00451313 /* RCTModalHostView.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A1FE8B1B62640A00BE0E65 /* RCTModalHostView.m */; };
2D3B5ED51D9B098000451313 /* RCTModalHostViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83392EB21B6634E10013B15F /* RCTModalHostViewController.m */; };
2D3B5ED61D9B098400451313 /* RCTModalHostViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A1FE8E1B62643A00BE0E65 /* RCTModalHostViewManager.m */; };
@@ -162,6 +154,7 @@
2D3B5EF01D9B09E300451313 /* RCTWrapperViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B080241A694A8400A75B9A /* RCTWrapperViewController.m */; };
2D3B5EF11D9B09E700451313 /* UIView+React.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067541A70F44B002CDEE1 /* UIView+React.m */; };
2D74EAFA1DAE9590003B751B /* RCTMultipartDataTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 006FC4131D9B20820057AAAD /* RCTMultipartDataTask.m */; };
+ 2D7FEB891E734B5700D3238C /* systemJSCWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65F3E41D1E73031C009375BD /* systemJSCWrapper.cpp */; };
2D8C2E331DA40441000EE098 /* RCTMultipartStreamReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 001BFCCF1D8381DE008E587E /* RCTMultipartStreamReader.m */; };
2D9F8B9B1DE398DB00A16144 /* RCTPlatform.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7749431DC1065C007EC8D8 /* RCTPlatform.m */; };
2DD0EFE11DA84F2800B0C975 /* RCTStatusBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13723B4F1A82FD3C00F88898 /* RCTStatusBarManager.m */; };
@@ -251,12 +244,7 @@
3D302F701DF828F800D6DDAE /* RCTComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 13C325281AA63B6A0048765F /* RCTComponent.h */; };
3D302F711DF828F800D6DDAE /* RCTComponentData.h in Headers */ = {isa = PBXBuildFile; fileRef = 13AB90BF1B6FA36700713B4F /* RCTComponentData.h */; };
3D302F721DF828F800D6DDAE /* RCTConvert+CoreLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 13456E911ADAD2DE009F94A7 /* RCTConvert+CoreLocation.h */; };
- 3D302F731DF828F800D6DDAE /* RCTConvert+MapKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 13456E941ADAD482009F94A7 /* RCTConvert+MapKit.h */; };
3D302F761DF828F800D6DDAE /* RCTFont.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D37B5801D522B190042D5B5 /* RCTFont.h */; };
- 3D302F771DF828F800D6DDAE /* RCTMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 14435CE11AAC4AE100FC20F4 /* RCTMap.h */; };
- 3D302F781DF828F800D6DDAE /* RCTMapAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = 13B202021BFB948C00C07393 /* RCTMapAnnotation.h */; };
- 3D302F791DF828F800D6DDAE /* RCTMapManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 14435CE31AAC4AE100FC20F4 /* RCTMapManager.h */; };
- 3D302F7A1DF828F800D6DDAE /* RCTMapOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 13AFBC9E1C07247D00BBAEAA /* RCTMapOverlay.h */; };
3D302F7B1DF828F800D6DDAE /* RCTModalHostView.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A1FE8A1B62640A00BE0E65 /* RCTModalHostView.h */; };
3D302F7C1DF828F800D6DDAE /* RCTModalHostViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 83392EB11B6634E10013B15F /* RCTModalHostViewController.h */; };
3D302F7D1DF828F800D6DDAE /* RCTModalHostViewManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A1FE8D1B62643A00BE0E65 /* RCTModalHostViewManager.h */; };
@@ -367,12 +355,7 @@
3D302FEC1DF8290600D6DDAE /* RCTComponent.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13C325281AA63B6A0048765F /* RCTComponent.h */; };
3D302FED1DF8290600D6DDAE /* RCTComponentData.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13AB90BF1B6FA36700713B4F /* RCTComponentData.h */; };
3D302FEE1DF8290600D6DDAE /* RCTConvert+CoreLocation.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13456E911ADAD2DE009F94A7 /* RCTConvert+CoreLocation.h */; };
- 3D302FEF1DF8290600D6DDAE /* RCTConvert+MapKit.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13456E941ADAD482009F94A7 /* RCTConvert+MapKit.h */; };
3D302FF21DF8290600D6DDAE /* RCTFont.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D37B5801D522B190042D5B5 /* RCTFont.h */; };
- 3D302FF31DF8290600D6DDAE /* RCTMap.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 14435CE11AAC4AE100FC20F4 /* RCTMap.h */; };
- 3D302FF41DF8290600D6DDAE /* RCTMapAnnotation.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13B202021BFB948C00C07393 /* RCTMapAnnotation.h */; };
- 3D302FF51DF8290600D6DDAE /* RCTMapManager.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 14435CE31AAC4AE100FC20F4 /* RCTMapManager.h */; };
- 3D302FF61DF8290600D6DDAE /* RCTMapOverlay.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13AFBC9E1C07247D00BBAEAA /* RCTMapOverlay.h */; };
3D302FF71DF8290600D6DDAE /* RCTModalHostView.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 83A1FE8A1B62640A00BE0E65 /* RCTModalHostView.h */; };
3D302FF81DF8290600D6DDAE /* RCTModalHostViewController.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 83392EB11B6634E10013B15F /* RCTModalHostViewController.h */; };
3D302FF91DF8290600D6DDAE /* RCTModalHostViewManager.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 83A1FE8D1B62643A00BE0E65 /* RCTModalHostViewManager.h */; };
@@ -515,14 +498,9 @@
3D80D96B1DF6FA890028D040 /* RCTComponent.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13C325281AA63B6A0048765F /* RCTComponent.h */; };
3D80D96C1DF6FA890028D040 /* RCTComponentData.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13AB90BF1B6FA36700713B4F /* RCTComponentData.h */; };
3D80D96D1DF6FA890028D040 /* RCTConvert+CoreLocation.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13456E911ADAD2DE009F94A7 /* RCTConvert+CoreLocation.h */; };
- 3D80D96E1DF6FA890028D040 /* RCTConvert+MapKit.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13456E941ADAD482009F94A7 /* RCTConvert+MapKit.h */; };
3D80D96F1DF6FA890028D040 /* RCTDatePicker.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 133CAE8C1B8E5CFD00F6AD92 /* RCTDatePicker.h */; };
3D80D9701DF6FA890028D040 /* RCTDatePickerManager.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 58C571C01AA56C1900CDF9C8 /* RCTDatePickerManager.h */; };
3D80D9711DF6FA890028D040 /* RCTFont.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D37B5801D522B190042D5B5 /* RCTFont.h */; };
- 3D80D9721DF6FA890028D040 /* RCTMap.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 14435CE11AAC4AE100FC20F4 /* RCTMap.h */; };
- 3D80D9731DF6FA890028D040 /* RCTMapAnnotation.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13B202021BFB948C00C07393 /* RCTMapAnnotation.h */; };
- 3D80D9741DF6FA890028D040 /* RCTMapManager.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 14435CE31AAC4AE100FC20F4 /* RCTMapManager.h */; };
- 3D80D9751DF6FA890028D040 /* RCTMapOverlay.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13AFBC9E1C07247D00BBAEAA /* RCTMapOverlay.h */; };
3D80D9761DF6FA890028D040 /* RCTModalHostView.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 83A1FE8A1B62640A00BE0E65 /* RCTModalHostView.h */; };
3D80D9771DF6FA890028D040 /* RCTModalHostViewController.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 83392EB11B6634E10013B15F /* RCTModalHostViewController.h */; };
3D80D9781DF6FA890028D040 /* RCTModalHostViewManager.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 83A1FE8D1B62643A00BE0E65 /* RCTModalHostViewManager.h */; };
@@ -638,14 +616,9 @@
3D80DA651DF820620028D040 /* RCTComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 13C325281AA63B6A0048765F /* RCTComponent.h */; };
3D80DA661DF820620028D040 /* RCTComponentData.h in Headers */ = {isa = PBXBuildFile; fileRef = 13AB90BF1B6FA36700713B4F /* RCTComponentData.h */; };
3D80DA671DF820620028D040 /* RCTConvert+CoreLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 13456E911ADAD2DE009F94A7 /* RCTConvert+CoreLocation.h */; };
- 3D80DA681DF820620028D040 /* RCTConvert+MapKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 13456E941ADAD482009F94A7 /* RCTConvert+MapKit.h */; };
3D80DA691DF820620028D040 /* RCTDatePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 133CAE8C1B8E5CFD00F6AD92 /* RCTDatePicker.h */; };
3D80DA6A1DF820620028D040 /* RCTDatePickerManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 58C571C01AA56C1900CDF9C8 /* RCTDatePickerManager.h */; };
3D80DA6B1DF820620028D040 /* RCTFont.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D37B5801D522B190042D5B5 /* RCTFont.h */; };
- 3D80DA6C1DF820620028D040 /* RCTMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 14435CE11AAC4AE100FC20F4 /* RCTMap.h */; };
- 3D80DA6D1DF820620028D040 /* RCTMapAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = 13B202021BFB948C00C07393 /* RCTMapAnnotation.h */; };
- 3D80DA6E1DF820620028D040 /* RCTMapManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 14435CE31AAC4AE100FC20F4 /* RCTMapManager.h */; };
- 3D80DA6F1DF820620028D040 /* RCTMapOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 13AFBC9E1C07247D00BBAEAA /* RCTMapOverlay.h */; };
3D80DA701DF820620028D040 /* RCTModalHostView.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A1FE8A1B62640A00BE0E65 /* RCTModalHostView.h */; };
3D80DA711DF820620028D040 /* RCTModalHostViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 83392EB11B6634E10013B15F /* RCTModalHostViewController.h */; };
3D80DA721DF820620028D040 /* RCTModalHostViewManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A1FE8D1B62643A00BE0E65 /* RCTModalHostViewManager.h */; };
@@ -909,12 +882,7 @@
3D302FEC1DF8290600D6DDAE /* RCTComponent.h in Copy Headers */,
3D302FED1DF8290600D6DDAE /* RCTComponentData.h in Copy Headers */,
3D302FEE1DF8290600D6DDAE /* RCTConvert+CoreLocation.h in Copy Headers */,
- 3D302FEF1DF8290600D6DDAE /* RCTConvert+MapKit.h in Copy Headers */,
3D302FF21DF8290600D6DDAE /* RCTFont.h in Copy Headers */,
- 3D302FF31DF8290600D6DDAE /* RCTMap.h in Copy Headers */,
- 3D302FF41DF8290600D6DDAE /* RCTMapAnnotation.h in Copy Headers */,
- 3D302FF51DF8290600D6DDAE /* RCTMapManager.h in Copy Headers */,
- 3D302FF61DF8290600D6DDAE /* RCTMapOverlay.h in Copy Headers */,
3D302FF71DF8290600D6DDAE /* RCTModalHostView.h in Copy Headers */,
3D302FF81DF8290600D6DDAE /* RCTModalHostViewController.h in Copy Headers */,
3D302FF91DF8290600D6DDAE /* RCTModalHostViewManager.h in Copy Headers */,
@@ -1073,14 +1041,9 @@
3D80D96B1DF6FA890028D040 /* RCTComponent.h in Copy Headers */,
3D80D96C1DF6FA890028D040 /* RCTComponentData.h in Copy Headers */,
3D80D96D1DF6FA890028D040 /* RCTConvert+CoreLocation.h in Copy Headers */,
- 3D80D96E1DF6FA890028D040 /* RCTConvert+MapKit.h in Copy Headers */,
3D80D96F1DF6FA890028D040 /* RCTDatePicker.h in Copy Headers */,
3D80D9701DF6FA890028D040 /* RCTDatePickerManager.h in Copy Headers */,
3D80D9711DF6FA890028D040 /* RCTFont.h in Copy Headers */,
- 3D80D9721DF6FA890028D040 /* RCTMap.h in Copy Headers */,
- 3D80D9731DF6FA890028D040 /* RCTMapAnnotation.h in Copy Headers */,
- 3D80D9741DF6FA890028D040 /* RCTMapManager.h in Copy Headers */,
- 3D80D9751DF6FA890028D040 /* RCTMapOverlay.h in Copy Headers */,
3D80D9761DF6FA890028D040 /* RCTModalHostView.h in Copy Headers */,
3D80D9771DF6FA890028D040 /* RCTModalHostViewController.h in Copy Headers */,
3D80D9781DF6FA890028D040 /* RCTModalHostViewManager.h in Copy Headers */,
@@ -1186,8 +1149,6 @@
13442BF41AA90E0B0037E5B0 /* RCTViewControllerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTViewControllerProtocol.h; sourceTree = ""; };
13456E911ADAD2DE009F94A7 /* RCTConvert+CoreLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+CoreLocation.h"; sourceTree = ""; };
13456E921ADAD2DE009F94A7 /* RCTConvert+CoreLocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+CoreLocation.m"; sourceTree = ""; };
- 13456E941ADAD482009F94A7 /* RCTConvert+MapKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+MapKit.h"; sourceTree = ""; };
- 13456E951ADAD482009F94A7 /* RCTConvert+MapKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+MapKit.m"; sourceTree = ""; };
1345A83A1B265A0E00583190 /* RCTURLRequestDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTURLRequestDelegate.h; sourceTree = ""; };
1345A83B1B265A0E00583190 /* RCTURLRequestHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTURLRequestHandler.h; sourceTree = ""; };
134FCB391A6E7F0800051CC8 /* RCTJSCExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = RCTJSCExecutor.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
@@ -1219,8 +1180,6 @@
13AF1F851AE6E777005F5298 /* RCTDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDefines.h; sourceTree = ""; };
13AF20431AE707F8005F5298 /* RCTSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSlider.h; sourceTree = ""; };
13AF20441AE707F9005F5298 /* RCTSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSlider.m; sourceTree = ""; };
- 13AFBC9E1C07247D00BBAEAA /* RCTMapOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMapOverlay.h; sourceTree = ""; };
- 13AFBC9F1C07247D00BBAEAA /* RCTMapOverlay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMapOverlay.m; sourceTree = ""; };
13AFBCA11C07287B00BBAEAA /* RCTBridgeMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTBridgeMethod.h; sourceTree = ""; };
13AFBCA21C07287B00BBAEAA /* RCTRootViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootViewDelegate.h; sourceTree = ""; };
13B07FE71A69327A00A75B9A /* RCTAlertManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAlertManager.h; sourceTree = ""; };
@@ -1245,8 +1204,6 @@
13B080191A69489C00A75B9A /* RCTActivityIndicatorViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTActivityIndicatorViewManager.m; sourceTree = ""; };
13B080231A694A8400A75B9A /* RCTWrapperViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTWrapperViewController.h; sourceTree = ""; };
13B080241A694A8400A75B9A /* RCTWrapperViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTWrapperViewController.m; sourceTree = ""; };
- 13B202021BFB948C00C07393 /* RCTMapAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMapAnnotation.h; sourceTree = ""; };
- 13B202031BFB948C00C07393 /* RCTMapAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMapAnnotation.m; sourceTree = ""; };
13BB3D001BECD54500932C10 /* RCTImageSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = RCTImageSource.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
13BB3D011BECD54500932C10 /* RCTImageSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageSource.m; sourceTree = ""; };
13BCE8071C99CB9D00DD7AAD /* RCTRootShadowView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootShadowView.h; sourceTree = ""; };
@@ -1282,10 +1239,6 @@
142014171B32094000CC17BA /* RCTPerformanceLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPerformanceLogger.m; sourceTree = ""; };
142014181B32094000CC17BA /* RCTPerformanceLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPerformanceLogger.h; sourceTree = ""; };
1436DD071ADE7AA000A5ED7D /* RCTFrameUpdate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTFrameUpdate.h; sourceTree = ""; };
- 14435CE11AAC4AE100FC20F4 /* RCTMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMap.h; sourceTree = ""; };
- 14435CE21AAC4AE100FC20F4 /* RCTMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMap.m; sourceTree = ""; };
- 14435CE31AAC4AE100FC20F4 /* RCTMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMapManager.h; sourceTree = ""; };
- 14435CE41AAC4AE100FC20F4 /* RCTMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMapManager.m; sourceTree = ""; };
1450FF801BCFF28A00208362 /* RCTProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTProfile.h; sourceTree = ""; };
1450FF811BCFF28A00208362 /* RCTProfile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTProfile.m; sourceTree = ""; };
1450FF821BCFF28A00208362 /* RCTProfileTrampoline-arm.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "RCTProfileTrampoline-arm.S"; sourceTree = ""; };
@@ -1372,6 +1325,7 @@
594AD5CC1E46D87500B07237 /* RCTScrollContentViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTScrollContentViewManager.m; sourceTree = ""; };
597AD1BB1E577D7800152581 /* RCTRootContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootContentView.h; sourceTree = ""; };
597AD1BC1E577D7800152581 /* RCTRootContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRootContentView.m; sourceTree = ""; };
+ 65F3E41D1E73031C009375BD /* systemJSCWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = systemJSCWrapper.cpp; sourceTree = ""; };
68EFE4EC1CF6EB3000A1DE13 /* RCTBundleURLProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTBundleURLProvider.h; sourceTree = ""; };
68EFE4ED1CF6EB3900A1DE13 /* RCTBundleURLProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTBundleURLProvider.m; sourceTree = ""; };
6A15FB0C1BDF663500531DFB /* RCTRootViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootViewInternal.h; sourceTree = ""; };
@@ -1545,8 +1499,6 @@
13AB90C01B6FA36700713B4F /* RCTComponentData.m */,
13456E911ADAD2DE009F94A7 /* RCTConvert+CoreLocation.h */,
13456E921ADAD2DE009F94A7 /* RCTConvert+CoreLocation.m */,
- 13456E941ADAD482009F94A7 /* RCTConvert+MapKit.h */,
- 13456E951ADAD482009F94A7 /* RCTConvert+MapKit.m */,
945929C21DD62ADD00653A7D /* RCTConvert+Transform.h */,
945929C31DD62ADD00653A7D /* RCTConvert+Transform.m */,
133CAE8C1B8E5CFD00F6AD92 /* RCTDatePicker.h */,
@@ -1555,14 +1507,6 @@
58C571BF1AA56C1900CDF9C8 /* RCTDatePickerManager.m */,
3D37B5801D522B190042D5B5 /* RCTFont.h */,
3D37B5811D522B190042D5B5 /* RCTFont.mm */,
- 14435CE11AAC4AE100FC20F4 /* RCTMap.h */,
- 14435CE21AAC4AE100FC20F4 /* RCTMap.m */,
- 13B202021BFB948C00C07393 /* RCTMapAnnotation.h */,
- 13B202031BFB948C00C07393 /* RCTMapAnnotation.m */,
- 14435CE31AAC4AE100FC20F4 /* RCTMapManager.h */,
- 14435CE41AAC4AE100FC20F4 /* RCTMapManager.m */,
- 13AFBC9E1C07247D00BBAEAA /* RCTMapOverlay.h */,
- 13AFBC9F1C07247D00BBAEAA /* RCTMapOverlay.m */,
83A1FE8A1B62640A00BE0E65 /* RCTModalHostView.h */,
83A1FE8B1B62640A00BE0E65 /* RCTModalHostView.m */,
83392EB11B6634E10013B15F /* RCTModalHostViewController.h */,
@@ -1723,6 +1667,7 @@
3D4A621D1DDD3985001F41B4 /* jschelpers */ = {
isa = PBXGroup;
children = (
+ 65F3E41D1E73031C009375BD /* systemJSCWrapper.cpp */,
3D7A27DC1DE32541002E3F95 /* JavaScriptCore.h */,
3D7A27DD1DE32541002E3F95 /* JSCWrapper.cpp */,
3D7A27DE1DE32541002E3F95 /* JSCWrapper.h */,
@@ -1976,12 +1921,7 @@
3D302F701DF828F800D6DDAE /* RCTComponent.h in Headers */,
3D302F711DF828F800D6DDAE /* RCTComponentData.h in Headers */,
3D302F721DF828F800D6DDAE /* RCTConvert+CoreLocation.h in Headers */,
- 3D302F731DF828F800D6DDAE /* RCTConvert+MapKit.h in Headers */,
3D302F761DF828F800D6DDAE /* RCTFont.h in Headers */,
- 3D302F771DF828F800D6DDAE /* RCTMap.h in Headers */,
- 3D302F781DF828F800D6DDAE /* RCTMapAnnotation.h in Headers */,
- 3D302F791DF828F800D6DDAE /* RCTMapManager.h in Headers */,
- 3D302F7A1DF828F800D6DDAE /* RCTMapOverlay.h in Headers */,
3D302F7B1DF828F800D6DDAE /* RCTModalHostView.h in Headers */,
3D302F7C1DF828F800D6DDAE /* RCTModalHostViewController.h in Headers */,
3D302F7D1DF828F800D6DDAE /* RCTModalHostViewManager.h in Headers */,
@@ -2168,15 +2108,10 @@
3D80DA651DF820620028D040 /* RCTComponent.h in Headers */,
3D80DA661DF820620028D040 /* RCTComponentData.h in Headers */,
3D80DA671DF820620028D040 /* RCTConvert+CoreLocation.h in Headers */,
- 3D80DA681DF820620028D040 /* RCTConvert+MapKit.h in Headers */,
3D80DA691DF820620028D040 /* RCTDatePicker.h in Headers */,
3D80DA6A1DF820620028D040 /* RCTDatePickerManager.h in Headers */,
3D80DA6B1DF820620028D040 /* RCTFont.h in Headers */,
- 3D80DA6C1DF820620028D040 /* RCTMap.h in Headers */,
- 3D80DA6D1DF820620028D040 /* RCTMapAnnotation.h in Headers */,
- 3D80DA6E1DF820620028D040 /* RCTMapManager.h in Headers */,
B505583F1E43DFB900F71A00 /* RCTDevSettings.h in Headers */,
- 3D80DA6F1DF820620028D040 /* RCTMapOverlay.h in Headers */,
3D80DA701DF820620028D040 /* RCTModalHostView.h in Headers */,
3D80DA711DF820620028D040 /* RCTModalHostViewController.h in Headers */,
3D80DA721DF820620028D040 /* RCTModalHostViewManager.h in Headers */,
@@ -2487,7 +2422,6 @@
2DD0EFE11DA84F2800B0C975 /* RCTStatusBarManager.m in Sources */,
2D3B5EC91D9B095C00451313 /* RCTBorderDrawing.m in Sources */,
B50558411E43E13D00F71A00 /* RCTDevMenu.m in Sources */,
- 2D3B5ED31D9B097B00451313 /* RCTMapOverlay.m in Sources */,
2D3B5E991D9B089A00451313 /* RCTDisplayLink.m in Sources */,
2D9F8B9B1DE398DB00A16144 /* RCTPlatform.m in Sources */,
2D3B5EBF1D9B093300451313 /* RCTJSCProfiler.m in Sources */,
@@ -2509,7 +2443,6 @@
2D3B5EE31D9B09B700451313 /* RCTSegmentedControl.m in Sources */,
A12E9E251E5DEB4D0029001B /* RCTPackagerClient.m in Sources */,
2D3B5EB71D9B091800451313 /* RCTRedBox.m in Sources */,
- 2D3B5ED11D9B097500451313 /* RCTMapAnnotation.m in Sources */,
2D3B5EAF1D9B08FB00451313 /* RCTAccessibilityManager.m in Sources */,
2D3B5EF11D9B09E700451313 /* UIView+React.m in Sources */,
2D3B5E931D9B087300451313 /* RCTErrorInfo.m in Sources */,
@@ -2521,7 +2454,6 @@
2D3B5EE11D9B09B000451313 /* RCTScrollView.m in Sources */,
2D3B5ED81D9B098A00451313 /* RCTNavigatorManager.m in Sources */,
2D3B5E951D9B087C00451313 /* RCTAssert.m in Sources */,
- 2D3B5ED21D9B097800451313 /* RCTMapManager.m in Sources */,
2D3B5EB61D9B091400451313 /* RCTExceptionsManager.m in Sources */,
2D3B5EEB1D9B09D000451313 /* RCTTabBarItem.m in Sources */,
2D3B5E961D9B088500451313 /* RCTBatchedBridge.m in Sources */,
@@ -2535,11 +2467,11 @@
A12E9E261E5DEB510029001B /* RCTPackagerClientResponder.m in Sources */,
2D3B5EEE1D9B09DA00451313 /* RCTView.m in Sources */,
594AD5D01E46D87500B07237 /* RCTScrollContentShadowView.m in Sources */,
- 2D3B5ECC1D9B096500451313 /* RCTConvert+MapKit.m in Sources */,
2D3B5E981D9B089500451313 /* RCTConvert.m in Sources */,
2D3B5EA71D9B08CE00451313 /* RCTTouchHandler.m in Sources */,
3D05745A1DE5FFF500184BB4 /* RCTJavaScriptLoader.mm in Sources */,
2D3B5EA41D9B08C200451313 /* RCTPerformanceLogger.m in Sources */,
+ 2D7FEB891E734B5700D3238C /* systemJSCWrapper.cpp in Sources */,
2D3B5E9E1D9B08AD00451313 /* RCTJSStackFrame.m in Sources */,
2D3B5E941D9B087900451313 /* RCTBundleURLProvider.m in Sources */,
2D3B5EB81D9B091B00451313 /* RCTSourceCode.m in Sources */,
@@ -2553,7 +2485,6 @@
A12E9E5D1E5DF8720029001B /* RCTReloadPackagerMethod.m in Sources */,
3D5AC71A1E0056E0000F9153 /* RCTTVNavigationEventEmitter.m in Sources */,
3D7A27E31DE325DA002E3F95 /* RCTJSCErrorHandling.mm in Sources */,
- 2D3B5ED01D9B097200451313 /* RCTMap.m in Sources */,
2D3B5EA61D9B08CA00451313 /* RCTTouchEvent.m in Sources */,
2D8C2E331DA40441000EE098 /* RCTMultipartStreamReader.m in Sources */,
2D3B5EF01D9B09E300451313 /* RCTWrapperViewController.m in Sources */,
@@ -2608,6 +2539,7 @@
buildActionMask = 2147483647;
files = (
3D80D9191DF6F7CF0028D040 /* JSCWrapper.cpp in Sources */,
+ 2638623A1E732AB60010FEBF /* systemJSCWrapper.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2616,6 +2548,7 @@
buildActionMask = 2147483647;
files = (
3D80D91A1DF6F7CF0028D040 /* JSCWrapper.cpp in Sources */,
+ 2638623B1E732AB70010FEBF /* systemJSCWrapper.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2640,7 +2573,6 @@
buildActionMask = 2147483647;
files = (
597AD1BF1E577D7800152581 /* RCTRootContentView.m in Sources */,
- 13456E961ADAD482009F94A7 /* RCTConvert+MapKit.m in Sources */,
13723B501A82FD3C00F88898 /* RCTStatusBarManager.m in Sources */,
000E6CEB1AB0E980000CDF4D /* RCTSourceCode.m in Sources */,
14A43DF31C20B1C900794BC8 /* RCTJSCProfiler.m in Sources */,
@@ -2654,7 +2586,6 @@
131B6AF41AF1093D00FFC3E0 /* RCTSegmentedControl.m in Sources */,
830A229E1A66C68A008503DA /* RCTRootView.m in Sources */,
13B07FF01A69327A00A75B9A /* RCTExceptionsManager.m in Sources */,
- 13B202041BFB948C00C07393 /* RCTMapAnnotation.m in Sources */,
A12E9E8F1E5DFA620029001B /* RCTSamplingProfilerPackagerMethod.mm in Sources */,
13BCE8091C99CB9D00DD7AAD /* RCTRootShadowView.m in Sources */,
14C2CA711B3AC63800E6CBB2 /* RCTModuleMethod.m in Sources */,
@@ -2710,14 +2641,12 @@
13E067571A70F44B002CDEE1 /* RCTView.m in Sources */,
3D7749441DC1065C007EC8D8 /* RCTPlatform.m in Sources */,
A12E9E1E1E5DEA350029001B /* RCTPackagerClientResponder.m in Sources */,
- 13AFBCA01C07247D00BBAEAA /* RCTMapOverlay.m in Sources */,
13D9FEEE1CDCD93000158BD7 /* RCTKeyboardObserver.m in Sources */,
B233E6EA1D2D845D00BC68BA /* RCTI18nManager.m in Sources */,
13456E931ADAD2DE009F94A7 /* RCTConvert+CoreLocation.m in Sources */,
137327E91AA5CF210034F82E /* RCTTabBarItemManager.m in Sources */,
13A1F71E1A75392D00D3D453 /* RCTKeyCommands.m in Sources */,
83CBBA531A601E3B00E9B192 /* RCTUtils.m in Sources */,
- 14435CE61AAC4AE100FC20F4 /* RCTMapManager.m in Sources */,
191E3EC11C29DC3800C180A6 /* RCTRefreshControl.m in Sources */,
13C156051AB1A2840079392D /* RCTWebView.m in Sources */,
83CBBA601A601EAA00E9B192 /* RCTBridge.m in Sources */,
@@ -2736,7 +2665,6 @@
137327E71AA5CF210034F82E /* RCTTabBar.m in Sources */,
13F17A851B8493E5007D4C75 /* RCTRedBox.m in Sources */,
83392EB31B6634E10013B15F /* RCTModalHostViewController.m in Sources */,
- 14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */,
13B0801C1A69489C00A75B9A /* RCTNavItem.m in Sources */,
83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */,
A12E9E5B1E5DF8600029001B /* RCTReloadPackagerMethod.m in Sources */,
diff --git a/React/ReactCxx.xcodeproj/project.pbxproj b/React/ReactCxx.xcodeproj/project.pbxproj
index e30bc533291da0..1c3ebe943e2f52 100644
--- a/React/ReactCxx.xcodeproj/project.pbxproj
+++ b/React/ReactCxx.xcodeproj/project.pbxproj
@@ -21,6 +21,10 @@
130443DD1E401AF500D93A67 /* RCTConvert+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 130443C31E401A8C00D93A67 /* RCTConvert+Transform.h */; };
130443DE1E401B0D00D93A67 /* RCTTVView.h in Headers */ = {isa = PBXBuildFile; fileRef = 130443D61E401AD800D93A67 /* RCTTVView.h */; };
130443DF1E401B0D00D93A67 /* RCTTVView.m in Sources */ = {isa = PBXBuildFile; fileRef = 130443D71E401AD800D93A67 /* RCTTVView.m */; };
+ 130E3D881E6A082100ACE484 /* RCTDevSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 130E3D861E6A082100ACE484 /* RCTDevSettings.h */; };
+ 130E3D891E6A082100ACE484 /* RCTDevSettings.mm in Sources */ = {isa = PBXBuildFile; fileRef = 130E3D871E6A082100ACE484 /* RCTDevSettings.mm */; };
+ 130E3D8A1E6A083600ACE484 /* RCTDevSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 130E3D861E6A082100ACE484 /* RCTDevSettings.h */; };
+ 130E3D8B1E6A083900ACE484 /* RCTDevSettings.mm in Sources */ = {isa = PBXBuildFile; fileRef = 130E3D871E6A082100ACE484 /* RCTDevSettings.mm */; };
13134C841E296B2A00B9F3CB /* RCTCxxBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 13134C731E296B2A00B9F3CB /* RCTCxxBridge.h */; };
13134C851E296B2A00B9F3CB /* RCTCxxBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 13134C731E296B2A00B9F3CB /* RCTCxxBridge.h */; };
13134C861E296B2A00B9F3CB /* RCTCxxBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13134C741E296B2A00B9F3CB /* RCTCxxBridge.mm */; };
@@ -113,7 +117,7 @@
139D84B21E273B5600323FB7 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 139D84A51E273B5600323FB7 /* File.cpp */; };
139D84B31E273B5600323FB7 /* json.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 139D84A71E273B5600323FB7 /* json.cpp */; };
13A0C2891B74F71200B29F6F /* RCTDevLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A0C2861B74F71200B29F6F /* RCTDevLoadingView.m */; };
- 13A0C28A1B74F71200B29F6F /* RCTDevMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13A0C2881B74F71200B29F6F /* RCTDevMenu.mm */; };
+ 13A0C28A1B74F71200B29F6F /* RCTDevMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A0C2881B74F71200B29F6F /* RCTDevMenu.m */; };
13A1F71E1A75392D00D3D453 /* RCTKeyCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */; };
13A6E20E1C19AA0C00845B82 /* RCTParserUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A6E20D1C19AA0C00845B82 /* RCTParserUtils.m */; };
13AB5E011DF777F2001A8C30 /* YGNodeList.c in Sources */ = {isa = PBXBuildFile; fileRef = 130A77051DF767AF001F9587 /* YGNodeList.c */; };
@@ -312,7 +316,7 @@
2D3B5EB11D9B090100451313 /* RCTAppState.m in Sources */ = {isa = PBXBuildFile; fileRef = 1372B7091AB030C200659ED6 /* RCTAppState.m */; };
2D3B5EB21D9B090300451313 /* RCTAsyncLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A4E1AAE93D500E7D092 /* RCTAsyncLocalStorage.m */; };
2D3B5EB41D9B090A00451313 /* RCTDevLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A0C2861B74F71200B29F6F /* RCTDevLoadingView.m */; };
- 2D3B5EB51D9B091100451313 /* RCTDevMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13A0C2881B74F71200B29F6F /* RCTDevMenu.mm */; };
+ 2D3B5EB51D9B091100451313 /* RCTDevMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A0C2881B74F71200B29F6F /* RCTDevMenu.m */; };
2D3B5EB61D9B091400451313 /* RCTExceptionsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FEA1A69327A00A75B9A /* RCTExceptionsManager.m */; };
2D3B5EB71D9B091800451313 /* RCTRedBox.m in Sources */ = {isa = PBXBuildFile; fileRef = 13F17A841B8493E5007D4C75 /* RCTRedBox.m */; };
2D3B5EB81D9B091B00451313 /* RCTSourceCode.m in Sources */ = {isa = PBXBuildFile; fileRef = 000E6CEA1AB0E980000CDF4D /* RCTSourceCode.m */; };
@@ -1506,6 +1510,8 @@
130A77061DF767AF001F9587 /* YGNodeList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YGNodeList.h; sourceTree = ""; };
130A77071DF767AF001F9587 /* Yoga.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Yoga.c; sourceTree = ""; };
130A77081DF767AF001F9587 /* Yoga.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Yoga.h; sourceTree = ""; };
+ 130E3D861E6A082100ACE484 /* RCTDevSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDevSettings.h; sourceTree = ""; };
+ 130E3D871E6A082100ACE484 /* RCTDevSettings.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTDevSettings.mm; sourceTree = ""; };
13134C731E296B2A00B9F3CB /* RCTCxxBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTCxxBridge.h; sourceTree = ""; };
13134C741E296B2A00B9F3CB /* RCTCxxBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTCxxBridge.mm; sourceTree = ""; };
13134C771E296B2A00B9F3CB /* RCTMessageThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMessageThread.h; sourceTree = ""; };
@@ -1552,24 +1558,24 @@
137327E41AA5CF210034F82E /* RCTTabBarItemManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTabBarItemManager.m; sourceTree = ""; };
137327E51AA5CF210034F82E /* RCTTabBarManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTabBarManager.h; sourceTree = ""; };
137327E61AA5CF210034F82E /* RCTTabBarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTabBarManager.m; sourceTree = ""; };
- 139D7E391E25C5A300323FB7 /* bignum-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "bignum-dtoa.cc"; path = "double-conversion-1.1.1/src/bignum-dtoa.cc"; sourceTree = ""; };
- 139D7E3A1E25C5A300323FB7 /* bignum-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "bignum-dtoa.h"; path = "double-conversion-1.1.1/src/bignum-dtoa.h"; sourceTree = ""; };
- 139D7E3B1E25C5A300323FB7 /* bignum.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bignum.cc; path = "double-conversion-1.1.1/src/bignum.cc"; sourceTree = ""; };
- 139D7E3C1E25C5A300323FB7 /* bignum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bignum.h; path = "double-conversion-1.1.1/src/bignum.h"; sourceTree = ""; };
- 139D7E3D1E25C5A300323FB7 /* cached-powers.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "cached-powers.cc"; path = "double-conversion-1.1.1/src/cached-powers.cc"; sourceTree = ""; };
- 139D7E3E1E25C5A300323FB7 /* cached-powers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cached-powers.h"; path = "double-conversion-1.1.1/src/cached-powers.h"; sourceTree = ""; };
- 139D7E3F1E25C5A300323FB7 /* diy-fp.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "diy-fp.cc"; path = "double-conversion-1.1.1/src/diy-fp.cc"; sourceTree = ""; };
- 139D7E401E25C5A300323FB7 /* diy-fp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "diy-fp.h"; path = "double-conversion-1.1.1/src/diy-fp.h"; sourceTree = ""; };
- 139D7E411E25C5A300323FB7 /* double-conversion.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "double-conversion.cc"; path = "double-conversion-1.1.1/src/double-conversion.cc"; sourceTree = ""; };
- 139D7E421E25C5A300323FB7 /* double-conversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "double-conversion.h"; path = "double-conversion-1.1.1/src/double-conversion.h"; sourceTree = ""; };
- 139D7E431E25C5A300323FB7 /* fast-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "fast-dtoa.cc"; path = "double-conversion-1.1.1/src/fast-dtoa.cc"; sourceTree = ""; };
- 139D7E441E25C5A300323FB7 /* fast-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "fast-dtoa.h"; path = "double-conversion-1.1.1/src/fast-dtoa.h"; sourceTree = ""; };
- 139D7E451E25C5A300323FB7 /* fixed-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "fixed-dtoa.cc"; path = "double-conversion-1.1.1/src/fixed-dtoa.cc"; sourceTree = ""; };
- 139D7E461E25C5A300323FB7 /* fixed-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "fixed-dtoa.h"; path = "double-conversion-1.1.1/src/fixed-dtoa.h"; sourceTree = ""; };
- 139D7E471E25C5A300323FB7 /* ieee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ieee.h; path = "double-conversion-1.1.1/src/ieee.h"; sourceTree = ""; };
- 139D7E481E25C5A300323FB7 /* strtod.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = strtod.cc; path = "double-conversion-1.1.1/src/strtod.cc"; sourceTree = ""; };
- 139D7E491E25C5A300323FB7 /* strtod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = strtod.h; path = "double-conversion-1.1.1/src/strtod.h"; sourceTree = ""; };
- 139D7E4A1E25C5A300323FB7 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utils.h; path = "double-conversion-1.1.1/src/utils.h"; sourceTree = ""; };
+ 139D7E391E25C5A300323FB7 /* bignum-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "bignum-dtoa.cc"; path = "double-conversion-1.1.5/src/bignum-dtoa.cc"; sourceTree = ""; };
+ 139D7E3A1E25C5A300323FB7 /* bignum-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "bignum-dtoa.h"; path = "double-conversion-1.1.5/src/bignum-dtoa.h"; sourceTree = ""; };
+ 139D7E3B1E25C5A300323FB7 /* bignum.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bignum.cc; path = "double-conversion-1.1.5/src/bignum.cc"; sourceTree = ""; };
+ 139D7E3C1E25C5A300323FB7 /* bignum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bignum.h; path = "double-conversion-1.1.5/src/bignum.h"; sourceTree = ""; };
+ 139D7E3D1E25C5A300323FB7 /* cached-powers.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "cached-powers.cc"; path = "double-conversion-1.1.5/src/cached-powers.cc"; sourceTree = ""; };
+ 139D7E3E1E25C5A300323FB7 /* cached-powers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cached-powers.h"; path = "double-conversion-1.1.5/src/cached-powers.h"; sourceTree = ""; };
+ 139D7E3F1E25C5A300323FB7 /* diy-fp.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "diy-fp.cc"; path = "double-conversion-1.1.5/src/diy-fp.cc"; sourceTree = ""; };
+ 139D7E401E25C5A300323FB7 /* diy-fp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "diy-fp.h"; path = "double-conversion-1.1.5/src/diy-fp.h"; sourceTree = "