diff --git a/Libraries/Components/Navigation/NavigatorIOS.android.js b/Libraries/Components/Navigation/NavigatorIOS.android.js
deleted file mode 100644
index 260d55992..000000000
--- a/Libraries/Components/Navigation/NavigatorIOS.android.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @format
- */
-
-'use strict';
-
-module.exports = require('UnimplementedView');
diff --git a/Libraries/Components/Navigation/NavigatorIOS.ios.js b/Libraries/Components/Navigation/NavigatorIOS.ios.js
deleted file mode 100644
index 539b41d4b..000000000
--- a/Libraries/Components/Navigation/NavigatorIOS.ios.js
+++ /dev/null
@@ -1,932 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @format
- * @flow
- */
-
-'use strict';
-
-const EventEmitter = require('EventEmitter');
-const Image = require('Image');
-const RCTNavigatorManager = require('NativeModules').NavigatorManager;
-const React = require('React');
-const PropTypes = require('prop-types');
-const ReactNative = require('ReactNative');
-const StaticContainer = require('StaticContainer.react');
-const StyleSheet = require('StyleSheet');
-const TVEventHandler = require('TVEventHandler');
-const View = require('View');
-const DeprecatedViewPropTypes = require('DeprecatedViewPropTypes');
-
-const createReactClass = require('create-react-class');
-const invariant = require('fbjs/lib/invariant');
-const requireNativeComponent = require('requireNativeComponent');
-
-/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
- * found when Flow v0.54 was deployed. To see the error delete this comment and
- * run Flow. */
-const keyMirror = require('fbjs/lib/keyMirror');
-
-const TRANSITIONER_REF = 'transitionerRef';
-
-let __uid = 0;
-function getuid() {
- return __uid++;
-}
-
-class NavigatorTransitionerIOS extends React.Component<$FlowFixMeProps> {
- requestSchedulingNavigation(cb) {
- RCTNavigatorManager.requestSchedulingJavaScriptNavigation(
- ReactNative.findNodeHandle(this),
- cb,
- );
- }
-
- render() {
- return ;
- }
-}
-
-const SystemIconLabels = {
- done: true,
- cancel: true,
- edit: true,
- save: true,
- add: true,
- compose: true,
- reply: true,
- action: true,
- organize: true,
- bookmarks: true,
- search: true,
- refresh: true,
- stop: true,
- camera: true,
- trash: true,
- play: true,
- pause: true,
- rewind: true,
- 'fast-forward': true,
- undo: true,
- redo: true,
- 'page-curl': true,
-};
-const SystemIcons = keyMirror(SystemIconLabels);
-
-type SystemButtonType = $Enum;
-
-type Route = {
- component: Function,
- title: string,
- titleImage?: Object,
- passProps?: Object,
- backButtonTitle?: string,
- backButtonIcon?: Object,
- leftButtonTitle?: string,
- leftButtonIcon?: Object,
- leftButtonSystemIcon?: SystemButtonType,
- onLeftButtonPress?: Function,
- rightButtonTitle?: string,
- rightButtonIcon?: Object,
- rightButtonSystemIcon?: SystemButtonType,
- onRightButtonPress?: Function,
- wrapperStyle?: any,
-};
-
-type State = {
- idStack: Array,
- routeStack: Array,
- requestedTopOfStack: number,
- observedTopOfStack: number,
- progress: number,
- fromIndex: number,
- toIndex: number,
- makingNavigatorRequest: boolean,
- updatingAllIndicesAtOrBeyond: ?number,
-};
-
-type Event = Object;
-
-/**
- * Think of `` as simply a component that renders an
- * `RCTNavigator`, and moves the `RCTNavigator`'s `requestedTopOfStack` pointer
- * forward and backward. The `RCTNavigator` interprets changes in
- * `requestedTopOfStack` to be pushes and pops of children that are rendered.
- * `` always ensures that whenever the `requestedTopOfStack`
- * pointer is moved, that we've also rendered enough children so that the
- * `RCTNavigator` can carry out the push/pop with those children.
- * `` also removes children that will no longer be needed
- * (after the pop of a child has been fully completed/animated out).
- */
-
-/**
- * `NavigatorIOS` is a wrapper around
- * [`UINavigationController`](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/),
- * enabling you to implement a navigation stack. It works exactly the same as it
- * would on a native app using `UINavigationController`, providing the same
- * animations and behavior from UIKit.
- *
- * As the name implies, it is only available on iOS. Take a look at
- * [`React Navigation`](https://reactnavigation.org/) for a cross-platform
- * solution in JavaScript, or check out either of these components for native
- * solutions: [native-navigation](http://airbnb.io/native-navigation/),
- * [react-native-navigation](https://github.com/wix/react-native-navigation).
- *
- * To set up the navigator, provide the `initialRoute` prop with a route
- * object. A route object is used to describe each scene that your app
- * navigates to. `initialRoute` represents the first route in your navigator.
- *
- * ```
- * import PropTypes from 'prop-types';
- * import React, { Component } from 'react';
- * import { NavigatorIOS, Text } from 'react-native';
- *
- * export default class NavigatorIOSApp extends Component {
- * render() {
- * return (
- *
- * );
- * }
- * }
- *
- * class MyScene extends Component {
- * static propTypes = {
- * title: PropTypes.string.isRequired,
- * navigator: PropTypes.object.isRequired,
- * }
- *
- * _onForward = () => {
- * this.props.navigator.push({
- * title: 'Scene ' + nextIndex,
- * });
- * }
- *
- * render() {
- * return (
- *
- * Current Scene: { this.props.title }
- *
- * Tap me to load the next scene
- *
- *
- * )
- * }
- * }
- * ```
- *
- * In this code, the navigator renders the component specified in initialRoute,
- * which in this case is `MyScene`. This component will receive a `route` prop
- * and a `navigator` prop representing the navigator. The navigator's navigation
- * bar will render the title for the current scene, "My Initial Scene".
- *
- * You can optionally pass in a `passProps` property to your `initialRoute`.
- * `NavigatorIOS` passes this in as props to the rendered component:
- *
- * ```
- * initialRoute={{
- * component: MyScene,
- * title: 'My Initial Scene',
- * passProps: { myProp: 'foo' }
- * }}
- * ```
- *
- * You can then access the props passed in via `{this.props.myProp}`.
- *
- * #### Handling Navigation
- *
- * To trigger navigation functionality such as pushing or popping a view, you
- * have access to a `navigator` object. The object is passed in as a prop to any
- * component that is rendered by `NavigatorIOS`. You can then call the
- * relevant methods to perform the navigation action you need:
- *
- * ```
- * class MyView extends Component {
- * _handleBackPress() {
- * this.props.navigator.pop();
- * }
- *
- * _handleNextPress(nextRoute) {
- * this.props.navigator.push(nextRoute);
- * }
- *
- * render() {
- * const nextRoute = {
- * component: MyView,
- * title: 'Bar That',
- * passProps: { myProp: 'bar' }
- * };
- * return(
- * this._handleNextPress(nextRoute)}>
- *
- * See you on the other nav {this.props.myProp}!
- *
- *
- * );
- * }
- * }
- * ```
- *
- * You can also trigger navigator functionality from the `NavigatorIOS`
- * component:
- *
- * ```
- * class NavvyIOS extends Component {
- * _handleNavigationRequest() {
- * this.refs.nav.push({
- * component: MyView,
- * title: 'Genius',
- * passProps: { myProp: 'genius' },
- * });
- * }
- *
- * render() {
- * return (
- * this._handleNavigationRequest(),
- * }}
- * style={{flex: 1}}
- * />
- * );
- * }
- * }
- * ```
- *
- * The code above adds a `_handleNavigationRequest` private method that is
- * invoked from the `NavigatorIOS` component when the right navigation bar item
- * is pressed. To get access to the navigator functionality, a reference to it
- * is saved in the `ref` prop and later referenced to push a new scene into the
- * navigation stack.
- *
- * #### Navigation Bar Configuration
- *
- * Props passed to `NavigatorIOS` will set the default configuration
- * for the navigation bar. Props passed as properties to a route object will set
- * the configuration for that route's navigation bar, overriding any props
- * passed to the `NavigatorIOS` component.
- *
- * ```
- * _handleNavigationRequest() {
- * this.refs.nav.push({
- * //...
- * passProps: { myProp: 'genius' },
- * barTintColor: '#996699',
- * });
- * }
- *
- * render() {
- * return (
- *
- * );
- * }
- * ```
- *
- * In the example above the navigation bar color is changed when the new route
- * is pushed.
- *
- */
-const NavigatorIOS = createReactClass({
- displayName: 'NavigatorIOS',
-
- propTypes: {
- /**
- * NavigatorIOS uses `route` objects to identify child views, their props,
- * and navigation bar configuration. Navigation operations such as push
- * operations expect routes to look like this the `initialRoute`.
- */
- initialRoute: PropTypes.shape({
- /**
- * The React Class to render for this route
- */
- component: PropTypes.func.isRequired,
-
- /**
- * The title displayed in the navigation bar and the back button for this
- * route.
- */
- title: PropTypes.string.isRequired,
-
- /**
- * If set, a title image will appear instead of the text title.
- */
- titleImage: Image.propTypes.source,
-
- /**
- * Use this to specify additional props to pass to the rendered
- * component. `NavigatorIOS` will automatically pass in `route` and
- * `navigator` props to the component.
- */
- passProps: PropTypes.object,
-
- /**
- * If set, the left navigation button image will be displayed using this
- * source. Note that this doesn't apply to the header of the current
- * view, but to those views that are subsequently pushed.
- */
- backButtonIcon: Image.propTypes.source,
-
- /**
- * If set, the left navigation button text will be set to this. Note that
- * this doesn't apply to the left button of the current view, but to
- * those views that are subsequently pushed
- */
- backButtonTitle: PropTypes.string,
-
- /**
- * If set, the left navigation button image will be displayed using
- * this source.
- */
- leftButtonIcon: Image.propTypes.source,
-
- /**
- * If set, the left navigation button will display this text.
- */
- leftButtonTitle: PropTypes.string,
-
- /**
- * If set, the left header button will appear with this system icon
- *
- * Supported icons are `done`, `cancel`, `edit`, `save`, `add`,
- * `compose`, `reply`, `action`, `organize`, `bookmarks`, `search`,
- * `refresh`, `stop`, `camera`, `trash`, `play`, `pause`, `rewind`,
- * `fast-forward`, `undo`, `redo`, and `page-curl`
- */
- leftButtonSystemIcon: PropTypes.oneOf(Object.keys(SystemIcons)),
-
- /**
- * This function will be invoked when the left navigation bar item is
- * pressed.
- */
- onLeftButtonPress: PropTypes.func,
-
- /**
- * If set, the right navigation button image will be displayed using
- * this source.
- */
- rightButtonIcon: Image.propTypes.source,
-
- /**
- * If set, the right navigation button will display this text.
- */
- rightButtonTitle: PropTypes.string,
-
- /**
- * If set, the right header button will appear with this system icon
- *
- * See leftButtonSystemIcon for supported icons
- */
- rightButtonSystemIcon: PropTypes.oneOf(Object.keys(SystemIcons)),
-
- /**
- * This function will be invoked when the right navigation bar item is
- * pressed.
- */
- onRightButtonPress: PropTypes.func,
-
- /**
- * Styles for the navigation item containing the component.
- */
- wrapperStyle: DeprecatedViewPropTypes.style,
-
- /**
- * Boolean value that indicates whether the navigation bar is hidden.
- */
- navigationBarHidden: PropTypes.bool,
-
- /**
- * Boolean value that indicates whether to hide the 1px hairline
- * shadow.
- */
- shadowHidden: PropTypes.bool,
-
- /**
- * The color used for the buttons in the navigation bar.
- */
- tintColor: PropTypes.string,
-
- /**
- * The background color of the navigation bar.
- */
- barTintColor: PropTypes.string,
-
- /**
- * The style of the navigation bar. Supported values are 'default', 'black'.
- * Use 'black' instead of setting `barTintColor` to black. This produces
- * a navigation bar with the native iOS style with higher translucency.
- */
- barStyle: PropTypes.oneOf(['default', 'black']),
-
- /**
- * The text color of the navigation bar title.
- */
- titleTextColor: PropTypes.string,
-
- /**
- * Boolean value that indicates whether the navigation bar is
- * translucent.
- */
- translucent: PropTypes.bool,
- }).isRequired,
-
- /**
- * Boolean value that indicates whether the navigation bar is hidden
- * by default.
- */
- navigationBarHidden: PropTypes.bool,
-
- /**
- * Boolean value that indicates whether to hide the 1px hairline shadow
- * by default.
- */
- shadowHidden: PropTypes.bool,
-
- /**
- * The default wrapper style for components in the navigator.
- * A common use case is to set the `backgroundColor` for every scene.
- */
- itemWrapperStyle: DeprecatedViewPropTypes.style,
-
- /**
- * The default color used for the buttons in the navigation bar.
- */
- tintColor: PropTypes.string,
-
- /**
- * The default background color of the navigation bar.
- */
- barTintColor: PropTypes.string,
-
- /**
- * The style of the navigation bar. Supported values are 'default', 'black'.
- * Use 'black' instead of setting `barTintColor` to black. This produces
- * a navigation bar with the native iOS style with higher translucency.
- */
- barStyle: PropTypes.oneOf(['default', 'black']),
-
- /**
- * The default text color of the navigation bar title.
- */
- titleTextColor: PropTypes.string,
-
- /**
- * Boolean value that indicates whether the navigation bar is
- * translucent by default
- */
- translucent: PropTypes.bool,
-
- /**
- * Boolean value that indicates whether the interactive pop gesture is
- * enabled. This is useful for enabling/disabling the back swipe navigation
- * gesture.
- *
- * If this prop is not provided, the default behavior is for the back swipe
- * gesture to be enabled when the navigation bar is shown and disabled when
- * the navigation bar is hidden. Once you've provided the
- * `interactivePopGestureEnabled` prop, you can never restore the default
- * behavior.
- */
- interactivePopGestureEnabled: PropTypes.bool,
- },
-
- navigator: (undefined: ?Object),
-
- UNSAFE_componentWillMount: function() {
- // Precompute a pack of callbacks that's frequently generated and passed to
- // instances.
- this.navigator = {
- push: this.push,
- pop: this.pop,
- popN: this.popN,
- replace: this.replace,
- replaceAtIndex: this.replaceAtIndex,
- replacePrevious: this.replacePrevious,
- replacePreviousAndPop: this.replacePreviousAndPop,
- resetTo: this.resetTo,
- popToRoute: this.popToRoute,
- popToTop: this.popToTop,
- };
- },
-
- componentDidMount: function() {
- this._enableTVEventHandler();
- },
-
- componentWillUnmount: function() {
- this._disableTVEventHandler();
- },
-
- getDefaultProps: function(): Object {
- return {
- translucent: true,
- };
- },
-
- getInitialState: function(): State {
- return {
- idStack: [getuid()],
- routeStack: [this.props.initialRoute],
- // The navigation index that we wish to push/pop to.
- requestedTopOfStack: 0,
- // The last index that native has sent confirmation of completed push/pop
- // for. At this point, we can discard any views that are beyond the
- // `requestedTopOfStack`. A value of `null` means we have not received
- // any confirmation, ever. We may receive an `observedTopOfStack` without
- // ever requesting it - native can instigate pops of its own with the
- // backswipe gesture.
- observedTopOfStack: 0,
- progress: 1,
- fromIndex: 0,
- toIndex: 0,
- // Whether or not we are making a navigator request to push/pop. (Used
- // for performance optimization).
- makingNavigatorRequest: false,
- // Whether or not we are updating children of navigator and if so (not
- // `null`) which index marks the beginning of all updates. Used for
- // performance optimization.
- updatingAllIndicesAtOrBeyond: 0,
- };
- },
-
- _toFocusOnNavigationComplete: (undefined: any),
-
- _handleFocusRequest: function(item: any) {
- if (this.state.makingNavigatorRequest) {
- this._toFocusOnNavigationComplete = item;
- } else {
- this._getFocusEmitter().emit('focus', item);
- }
- },
-
- _focusEmitter: (undefined: ?EventEmitter),
-
- _getFocusEmitter: function(): EventEmitter {
- // Flow not yet tracking assignments to instance fields.
- let focusEmitter = this._focusEmitter;
- if (!focusEmitter) {
- focusEmitter = new EventEmitter();
- this._focusEmitter = focusEmitter;
- }
- return focusEmitter;
- },
-
- getChildContext: function(): {
- onFocusRequested: Function,
- focusEmitter: EventEmitter,
- } {
- return {
- onFocusRequested: this._handleFocusRequest,
- focusEmitter: this._getFocusEmitter(),
- };
- },
-
- childContextTypes: {
- onFocusRequested: PropTypes.func,
- focusEmitter: PropTypes.instanceOf(EventEmitter),
- },
-
- _tryLockNavigator: function(cb: () => void) {
- this.refs[TRANSITIONER_REF].requestSchedulingNavigation(
- acquiredLock => acquiredLock && cb(),
- );
- },
-
- _handleNavigatorStackChanged: function(e: Event) {
- const newObservedTopOfStack = e.nativeEvent.stackLength - 1;
-
- invariant(
- newObservedTopOfStack <= this.state.requestedTopOfStack,
- 'No navigator item should be pushed without JS knowing about it %s %s',
- newObservedTopOfStack,
- this.state.requestedTopOfStack,
- );
- const wasWaitingForConfirmation =
- this.state.requestedTopOfStack !== this.state.observedTopOfStack;
- if (wasWaitingForConfirmation) {
- invariant(
- newObservedTopOfStack === this.state.requestedTopOfStack,
- 'If waiting for observedTopOfStack to reach requestedTopOfStack, ' +
- 'the only valid observedTopOfStack should be requestedTopOfStack.',
- );
- }
- // Mark the most recent observation regardless of if we can lock the
- // navigator. `observedTopOfStack` merely represents what we've observed
- // and this first `setState` is only executed to update debugging
- // overlays/navigation bar.
- // Also reset progress, toIndex, and fromIndex as they might not end
- // in the correct states for a two possible reasons:
- // Progress isn't always 0 or 1 at the end, the system rounds
- // If the Navigator is offscreen these values won't be updated
- // TOOD: Revisit this decision when no longer relying on native navigator.
- const nextState = {
- observedTopOfStack: newObservedTopOfStack,
- makingNavigatorRequest: false,
- updatingAllIndicesAtOrBeyond: null,
- progress: 1,
- toIndex: newObservedTopOfStack,
- fromIndex: newObservedTopOfStack,
- };
- this.setState(nextState, this._eliminateUnneededChildren);
- },
-
- _eliminateUnneededChildren: function() {
- // Updating the indices that we're deleting and that's all. (Truth: Nothing
- // even uses the indices in this case, but let's make this describe the
- // truth anyways).
- const updatingAllIndicesAtOrBeyond =
- this.state.routeStack.length > this.state.observedTopOfStack + 1
- ? this.state.observedTopOfStack + 1
- : null;
- this.setState({
- idStack: this.state.idStack.slice(0, this.state.observedTopOfStack + 1),
- routeStack: this.state.routeStack.slice(
- 0,
- this.state.observedTopOfStack + 1,
- ),
- // Now we rerequest the top of stack that we observed.
- requestedTopOfStack: this.state.observedTopOfStack,
- makingNavigatorRequest: true,
- updatingAllIndicesAtOrBeyond: updatingAllIndicesAtOrBeyond,
- });
- },
-
- /**
- * Navigate forward to a new route.
- * @param route The new route to navigate to.
- */
- push: function(route: Route) {
- invariant(!!route, 'Must supply route to push');
- // Make sure all previous requests are caught up first. Otherwise reject.
- if (this.state.requestedTopOfStack === this.state.observedTopOfStack) {
- this._tryLockNavigator(() => {
- const nextStack = this.state.routeStack.concat([route]);
- const nextIDStack = this.state.idStack.concat([getuid()]);
- this.setState({
- // We have to make sure that we've also supplied enough views to
- // satisfy our request to adjust the `requestedTopOfStack`.
- idStack: nextIDStack,
- routeStack: nextStack,
- requestedTopOfStack: nextStack.length - 1,
- makingNavigatorRequest: true,
- updatingAllIndicesAtOrBeyond: nextStack.length - 1,
- });
- });
- }
- },
-
- /**
- * Go back N scenes at once. When N=1, behavior matches `pop()`.
- * @param n The number of scenes to pop.
- */
- popN: function(n: number) {
- if (n === 0) {
- return;
- }
- // Make sure all previous requests are caught up first. Otherwise reject.
- if (this.state.requestedTopOfStack === this.state.observedTopOfStack) {
- if (this.state.requestedTopOfStack > 0) {
- this._tryLockNavigator(() => {
- const newRequestedTopOfStack = this.state.requestedTopOfStack - n;
- invariant(newRequestedTopOfStack >= 0, 'Cannot pop below 0');
- this.setState({
- requestedTopOfStack: newRequestedTopOfStack,
- makingNavigatorRequest: true,
- updatingAllIndicesAtOrBeyond: this.state.requestedTopOfStack - n,
- });
- });
- }
- }
- },
-
- /**
- * Pop back to the previous scene.
- */
- pop: function() {
- this.popN(1);
- },
-
- /**
- * Replace a route in the navigation stack.
- *
- * @param route The new route that will replace the specified one.
- * @param index The route into the stack that should be replaced.
- * If it is negative, it counts from the back of the stack.
- */
- replaceAtIndex: function(route: Route, index: number) {
- invariant(!!route, 'Must supply route to replace');
- if (index < 0) {
- index += this.state.routeStack.length;
- }
-
- if (this.state.routeStack.length <= index) {
- return;
- }
-
- // I don't believe we need to lock for a replace since there's no
- // navigation actually happening
- const nextIDStack = this.state.idStack.slice();
- const nextRouteStack = this.state.routeStack.slice();
- nextIDStack[index] = getuid();
- nextRouteStack[index] = route;
-
- this.setState({
- idStack: nextIDStack,
- routeStack: nextRouteStack,
- makingNavigatorRequest: false,
- updatingAllIndicesAtOrBeyond: index,
- });
- },
-
- /**
- * Replace the route for the current scene and immediately
- * load the view for the new route.
- * @param route The new route to navigate to.
- */
- replace: function(route: Route) {
- this.replaceAtIndex(route, -1);
- },
-
- /**
- * Replace the route/view for the previous scene.
- * @param route The new route to will replace the previous scene.
- */
- replacePrevious: function(route: Route) {
- this.replaceAtIndex(route, -2);
- },
-
- /**
- * Go back to the topmost item in the navigation stack.
- */
- popToTop: function() {
- this.popToRoute(this.state.routeStack[0]);
- },
-
- /**
- * Go back to the item for a particular route object.
- * @param route The new route to navigate to.
- */
- popToRoute: function(route: Route) {
- const indexOfRoute = this.state.routeStack.indexOf(route);
- invariant(
- indexOfRoute !== -1,
- "Calling pop to route for a route that doesn't exist!",
- );
- const numToPop = this.state.routeStack.length - indexOfRoute - 1;
- this.popN(numToPop);
- },
-
- /**
- * Replaces the previous route/view and transitions back to it.
- * @param route The new route that replaces the previous scene.
- */
- replacePreviousAndPop: function(route: Route) {
- // Make sure all previous requests are caught up first. Otherwise reject.
- if (this.state.requestedTopOfStack !== this.state.observedTopOfStack) {
- return;
- }
- if (this.state.routeStack.length < 2) {
- return;
- }
- this._tryLockNavigator(() => {
- this.replacePrevious(route);
- this.setState({
- requestedTopOfStack: this.state.requestedTopOfStack - 1,
- makingNavigatorRequest: true,
- });
- });
- },
-
- /**
- * Replaces the top item and pop to it.
- * @param route The new route that will replace the topmost item.
- */
- resetTo: function(route: Route) {
- invariant(!!route, 'Must supply route to push');
- // Make sure all previous requests are caught up first. Otherwise reject.
- if (this.state.requestedTopOfStack !== this.state.observedTopOfStack) {
- return;
- }
- this.replaceAtIndex(route, 0);
- this.popToRoute(route);
- },
-
- _handleNavigationComplete: function(e: Event) {
- // Don't propagate to other NavigatorIOS instances this is nested in:
- e.stopPropagation();
-
- if (this._toFocusOnNavigationComplete) {
- this._getFocusEmitter().emit('focus', this._toFocusOnNavigationComplete);
- this._toFocusOnNavigationComplete = null;
- }
- this._handleNavigatorStackChanged(e);
- },
-
- _routeToStackItem: function(routeArg: Route, i: number) {
- const {component, wrapperStyle, passProps, ...route} = routeArg;
- const {itemWrapperStyle, ...props} = this.props;
- const shouldUpdateChild =
- this.state.updatingAllIndicesAtOrBeyond != null &&
- this.state.updatingAllIndicesAtOrBeyond >= i;
- const Component = component;
- return (
-
-
-
-
-
- );
- },
-
- _renderNavigationStackItems: function() {
- const shouldRecurseToNavigator =
- this.state.makingNavigatorRequest ||
- this.state.updatingAllIndicesAtOrBeyond !== null;
- // If not recursing update to navigator at all, may as well avoid
- // computation of navigator children.
- const items = shouldRecurseToNavigator
- ? this.state.routeStack.map(this._routeToStackItem)
- : null;
- return (
-
- =0.41.0)
- vertical={this.props.vertical}
- requestedTopOfStack={this.state.requestedTopOfStack}
- onNavigationComplete={this._handleNavigationComplete}
- interactivePopGestureEnabled={
- this.props.interactivePopGestureEnabled
- }>
- {items}
-
-
- );
- },
-
- _tvEventHandler: (undefined: ?TVEventHandler),
-
- _enableTVEventHandler: function() {
- this._tvEventHandler = new TVEventHandler();
- this._tvEventHandler.enable(this, function(cmp, evt) {
- if (evt && evt.eventType === 'menu') {
- cmp.pop();
- }
- });
- },
-
- _disableTVEventHandler: function() {
- if (this._tvEventHandler) {
- this._tvEventHandler.disable();
- delete this._tvEventHandler;
- }
- },
-
- render: function() {
- return (
- // $FlowFixMe(>=0.41.0)
- {this._renderNavigationStackItems()}
- );
- },
-});
-
-const styles = StyleSheet.create({
- stackItem: {
- backgroundColor: 'white',
- overflow: 'hidden',
- position: 'absolute',
- top: 0,
- left: 0,
- right: 0,
- bottom: 0,
- },
- transitioner: {
- flex: 1,
- },
-});
-
-const RCTNavigator = requireNativeComponent('RCTNavigator');
-const RCTNavigatorItem = requireNativeComponent('RCTNavItem');
-
-module.exports = NavigatorIOS;
diff --git a/Libraries/react-native/react-native-implementation.js b/Libraries/react-native/react-native-implementation.js
index 03d25f0fc..ff41d684b 100644
--- a/Libraries/react-native/react-native-implementation.js
+++ b/Libraries/react-native/react-native-implementation.js
@@ -66,9 +66,6 @@ const ReactNative = {
get Modal() {
return require('Modal');
},
- get NavigatorIOS() {
- return require('NavigatorIOS');
- },
get Picker() {
return require('Picker');
},
@@ -325,6 +322,13 @@ const ReactNative = {
'Learn about alternative navigation solutions at http://facebook.github.io/react-native/docs/navigation.html',
);
},
+ get NavigatorIOS() {
+ invariant(
+ false,
+ 'NavigatorIOS is deprecated and has been removed from this package. ' +
+ 'Learn about alternative navigation solutions at http://facebook.github.io/react-native/docs/navigation.html',
+ );
+ },
};
module.exports = ReactNative;
diff --git a/RNTester/js/NavigatorIOSBarStyleExample.js b/RNTester/js/NavigatorIOSBarStyleExample.js
deleted file mode 100644
index 07ca90edc..000000000
--- a/RNTester/js/NavigatorIOSBarStyleExample.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * Copyright (c) 2013-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * 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.
- *
- * @format
- */
-
-'use strict';
-
-var React = require('react');
-var ReactNative = require('react-native');
-var {NavigatorIOS, StatusBar, StyleSheet, Text, View} = ReactNative;
-
-class EmptyPage extends React.Component<{
- text: string,
-}> {
- render() {
- return (
-
- {this.props.text}
-
- );
- }
-}
-
-class NavigatorIOSColors extends React.Component<{}> {
- static title = ' - Custom Bar Style';
- static description = 'iOS navigation with custom nav bar colors';
-
- render() {
- // Set StatusBar with light contents to get better contrast
- StatusBar.setBarStyle('light-content');
-
- return (
- ',
- rightButtonTitle: 'Done',
- onRightButtonPress: () => {
- StatusBar.setBarStyle('default');
- this.props.onExampleExit();
- },
- passProps: {
- text: 'The nav bar is black with barStyle prop.',
- },
- }}
- barStyle="black"
- />
- );
- }
-}
-
-var styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- emptyPage: {
- flex: 1,
- paddingTop: 64,
- },
- emptyPageText: {
- margin: 10,
- },
-});
-
-NavigatorIOSColors.external = true;
-
-module.exports = NavigatorIOSColors;
diff --git a/RNTester/js/NavigatorIOSColorsExample.js b/RNTester/js/NavigatorIOSColorsExample.js
deleted file mode 100644
index d9a7cbb29..000000000
--- a/RNTester/js/NavigatorIOSColorsExample.js
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @format
- */
-
-'use strict';
-
-var React = require('react');
-var ReactNative = require('react-native');
-var {NavigatorIOS, StatusBar, StyleSheet, Text, View} = ReactNative;
-
-class EmptyPage extends React.Component {
- render() {
- return (
-
- {this.props.text}
-
- );
- }
-}
-
-class NavigatorIOSColors extends React.Component {
- static title = ' - Custom Colors';
- static description = 'iOS navigation with custom nav bar colors';
-
- render() {
- // Set StatusBar with light contents to get better contrast
- StatusBar.setBarStyle('light-content');
-
- return (
- ',
- rightButtonTitle: 'Done',
- onRightButtonPress: () => {
- StatusBar.setBarStyle('default');
- this.props.onExampleExit();
- },
- passProps: {
- text:
- 'The nav bar has custom colors with tintColor, ' +
- 'barTintColor and titleTextColor props.',
- },
- }}
- tintColor="#FFFFFF"
- barTintColor="#183E63"
- titleTextColor="#FFFFFF"
- translucent={true}
- />
- );
- }
-}
-
-var styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- emptyPage: {
- flex: 1,
- paddingTop: 64,
- },
- emptyPageText: {
- margin: 10,
- },
-});
-
-NavigatorIOSColors.external = true;
-
-module.exports = NavigatorIOSColors;
diff --git a/RNTester/js/NavigatorIOSExample.js b/RNTester/js/NavigatorIOSExample.js
deleted file mode 100644
index 252bf0e9e..000000000
--- a/RNTester/js/NavigatorIOSExample.js
+++ /dev/null
@@ -1,303 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @format
- * @flow
- */
-
-'use strict';
-
-const React = require('react');
-const ReactNative = require('react-native');
-const ViewExample = require('./ViewExample');
-
-const createExamplePage = require('./createExamplePage');
-const nativeImageSource = require('nativeImageSource');
-const {
- AlertIOS,
- NavigatorIOS,
- ScrollView,
- StyleSheet,
- Text,
- TouchableHighlight,
- View,
-} = ReactNative;
-
-class EmptyPage extends React.Component<$FlowFixMeProps> {
- render() {
- return (
-
- {this.props.text}
-
- );
- }
-}
-
-class NavigatorIOSExamplePage extends React.Component<$FlowFixMeProps> {
- render() {
- var recurseTitle = 'Recurse Navigation';
- if (!this.props.depth || this.props.depth === 1) {
- recurseTitle += ' - more examples here';
- }
- return (
-
-
-
- {this._renderRow(recurseTitle, () => {
- this.props.navigator.push({
- title: NavigatorIOSExample.title,
- component: NavigatorIOSExamplePage,
- backButtonTitle: 'Custom Back',
- passProps: {depth: this.props.depth ? this.props.depth + 1 : 1},
- });
- })}
- {this._renderRow('Push View Example', () => {
- this.props.navigator.push({
- title: 'Very Long Custom View Example Title',
- component: createExamplePage(null, ViewExample),
- });
- })}
- {this._renderRow('Custom title image Example', () => {
- this.props.navigator.push({
- title: 'Custom title image Example',
- titleImage: require('./relay.png'),
- component: createExamplePage(null, ViewExample),
- });
- })}
- {this._renderRow('Custom Right Button', () => {
- this.props.navigator.push({
- title: NavigatorIOSExample.title,
- component: EmptyPage,
- rightButtonTitle: 'Cancel',
- onRightButtonPress: () => this.props.navigator.pop(),
- passProps: {
- text: 'This page has a right button in the nav bar',
- },
- });
- })}
- {this._renderRow('Custom Right System Button', () => {
- this.props.navigator.push({
- title: NavigatorIOSExample.title,
- component: EmptyPage,
- rightButtonSystemIcon: 'bookmarks',
- onRightButtonPress: () => this.props.navigator.pop(),
- passProps: {
- text: 'This page has a right system button in the nav bar',
- },
- });
- })}
- {this._renderRow('Custom Left & Right Icons', () => {
- this.props.navigator.push({
- title: NavigatorIOSExample.title,
- component: EmptyPage,
- leftButtonTitle: 'Custom Left',
- onLeftButtonPress: () => this.props.navigator.pop(),
- rightButtonIcon: nativeImageSource({
- ios: 'NavBarButtonPlus',
- width: 17,
- height: 17,
- }),
- onRightButtonPress: () => {
- AlertIOS.alert(
- 'Bar Button Action',
- 'Recognized a tap on the bar button icon',
- [
- {
- text: 'OK',
- onPress: () => console.log('Tapped OK'),
- },
- ],
- );
- },
- passProps: {
- text:
- 'This page has an icon for the right button in the nav bar',
- },
- });
- })}
- {this._renderRow('Custom Left & Right System Icons', () => {
- this.props.navigator.push({
- title: NavigatorIOSExample.title,
- component: EmptyPage,
- leftButtonSystemIcon: 'cancel',
- onLeftButtonPress: () => this.props.navigator.pop(),
- rightButtonSystemIcon: 'search',
- onRightButtonPress: () => {
- AlertIOS.alert(
- 'Bar Button Action',
- 'Recognized a tap on the bar button icon',
- [
- {
- text: 'OK',
- onPress: () => console.log('Tapped OK'),
- },
- ],
- );
- },
- passProps: {
- text:
- 'This page has an icon for the right button in the nav bar',
- },
- });
- })}
- {this._renderRow('Pop', () => {
- this.props.navigator.pop();
- })}
- {this._renderRow('Pop to top', () => {
- this.props.navigator.popToTop();
- })}
- {this._renderReplace()}
- {this._renderReplacePrevious()}
- {this._renderReplacePreviousAndPop()}
- {this._renderRow(
- 'Exit NavigatorIOS Example',
- this.props.onExampleExit,
- )}
-
-
-
- );
- }
-
- _renderReplace = () => {
- if (!this.props.depth) {
- // this is to avoid replacing the top of the stack
- return null;
- }
- return this._renderRow('Replace here', () => {
- var prevRoute = this.props.route;
- this.props.navigator.replace({
- title: 'New Navigation',
- component: EmptyPage,
- rightButtonTitle: 'Undo',
- onRightButtonPress: () => this.props.navigator.replace(prevRoute),
- passProps: {
- text:
- 'The component is replaced, but there is currently no ' +
- 'way to change the right button or title of the current route',
- },
- });
- });
- };
-
- _renderReplacePrevious = () => {
- if (!this.props.depth || this.props.depth < 2) {
- // this is to avoid replacing the top of the stack
- return null;
- }
- return this._renderRow('Replace previous', () => {
- this.props.navigator.replacePrevious({
- title: 'Replaced',
- component: EmptyPage,
- passProps: {
- text: 'This is a replaced "previous" page',
- },
- wrapperStyle: styles.customWrapperStyle,
- });
- });
- };
-
- _renderReplacePreviousAndPop = () => {
- if (!this.props.depth || this.props.depth < 2) {
- // this is to avoid replacing the top of the stack
- return null;
- }
- return this._renderRow('Replace previous and pop', () => {
- this.props.navigator.replacePreviousAndPop({
- title: 'Replaced and Popped',
- component: EmptyPage,
- passProps: {
- text: 'This is a replaced "previous" page',
- },
- wrapperStyle: styles.customWrapperStyle,
- });
- });
- };
-
- _renderRow = (title: string, onPress: Function) => {
- return (
-
-
-
- {title}
-
-
-
-
- );
- };
-}
-
-class NavigatorIOSExample extends React.Component<$FlowFixMeProps> {
- static title = '';
- static description = 'iOS navigation capabilities';
- static external = true;
-
- render() {
- const {onExampleExit} = this.props;
- return (
-
- );
- }
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- customWrapperStyle: {
- backgroundColor: '#bbdddd',
- },
- emptyPage: {
- flex: 1,
- paddingTop: 64,
- },
- emptyPageText: {
- margin: 10,
- },
- list: {
- backgroundColor: '#eeeeee',
- marginTop: 10,
- },
- group: {
- backgroundColor: 'white',
- },
- groupSpace: {
- height: 15,
- },
- line: {
- backgroundColor: '#bbbbbb',
- height: StyleSheet.hairlineWidth,
- },
- row: {
- backgroundColor: 'white',
- justifyContent: 'center',
- paddingHorizontal: 15,
- paddingVertical: 15,
- },
- separator: {
- height: StyleSheet.hairlineWidth,
- backgroundColor: '#bbbbbb',
- marginLeft: 15,
- },
- rowNote: {
- fontSize: 17,
- },
- rowText: {
- fontSize: 17,
- fontWeight: '500',
- },
-});
-
-module.exports = NavigatorIOSExample;
diff --git a/RNTester/js/RNTesterList.ios.js b/RNTester/js/RNTesterList.ios.js
index f7a62efaa..bd717ea7d 100644
--- a/RNTester/js/RNTesterList.ios.js
+++ b/RNTester/js/RNTesterList.ios.js
@@ -92,21 +92,6 @@ const ComponentExamples: Array = [
module: require('./MultiColumnExample'),
supportsTVOS: true,
},
- {
- key: 'NavigatorIOSColorsExample',
- module: require('./NavigatorIOSColorsExample'),
- supportsTVOS: false,
- },
- {
- key: 'NavigatorIOSBarStyleExample',
- module: require('./NavigatorIOSBarStyleExample'),
- supportsTVOS: false,
- },
- {
- key: 'NavigatorIOSExample',
- module: require('./NavigatorIOSExample'),
- supportsTVOS: true,
- },
{
key: 'PickerExample',
module: require('./PickerExample'),
diff --git a/React/Views/RCTNavItem.h b/React/Views/RCTNavItem.h
deleted file mode 100644
index 9cabdf2e6..000000000
--- a/React/Views/RCTNavItem.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-#import
-
-#import
-
-@interface RCTNavItem : UIView
-
-@property (nonatomic, copy) NSString *title;
-@property (nonatomic, strong) UIImage *titleImage;
-@property (nonatomic, strong) UIImage *leftButtonIcon;
-@property (nonatomic, copy) NSString *leftButtonTitle;
-@property (nonatomic, assign) UIBarButtonSystemItem leftButtonSystemIcon;
-@property (nonatomic, strong) UIImage *rightButtonIcon;
-@property (nonatomic, copy) NSString *rightButtonTitle;
-@property (nonatomic, assign) UIBarButtonSystemItem rightButtonSystemIcon;
-@property (nonatomic, strong) UIImage *backButtonIcon;
-@property (nonatomic, copy) NSString *backButtonTitle;
-@property (nonatomic, assign) BOOL navigationBarHidden;
-@property (nonatomic, assign) BOOL shadowHidden;
-@property (nonatomic, strong) UIColor *tintColor;
-@property (nonatomic, strong) UIColor *barTintColor;
-@property (nonatomic, strong) UIColor *titleTextColor;
-@property (nonatomic, assign) BOOL translucent;
-#if !TARGET_OS_TV
-@property (nonatomic, assign) UIBarStyle barStyle;
-#endif
-
-@property (nonatomic, readonly) UIImageView *titleImageView;
-@property (nonatomic, readonly) UIBarButtonItem *backButtonItem;
-@property (nonatomic, readonly) UIBarButtonItem *leftButtonItem;
-@property (nonatomic, readonly) UIBarButtonItem *rightButtonItem;
-
-@property (nonatomic, copy) RCTBubblingEventBlock onLeftButtonPress;
-@property (nonatomic, copy) RCTBubblingEventBlock onRightButtonPress;
-
-@end
diff --git a/React/Views/RCTNavItem.m b/React/Views/RCTNavItem.m
deleted file mode 100644
index 58923e245..000000000
--- a/React/Views/RCTNavItem.m
+++ /dev/null
@@ -1,174 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-#import "RCTNavItem.h"
-
-@implementation RCTNavItem
-
-@synthesize backButtonItem = _backButtonItem;
-@synthesize leftButtonItem = _leftButtonItem;
-@synthesize rightButtonItem = _rightButtonItem;
-
-- (UIImageView *)titleImageView
-{
- if (_titleImage) {
- return [[UIImageView alloc] initWithImage:_titleImage];
- } else {
- return nil;
- }
-}
-
--(instancetype)init
-{
- if (self = [super init]) {
- _leftButtonSystemIcon = NSNotFound;
- _rightButtonSystemIcon = NSNotFound;
- }
- return self;
-}
-
-- (void)setBackButtonTitle:(NSString *)backButtonTitle
-{
- _backButtonTitle = backButtonTitle;
- _backButtonItem = nil;
-}
-
-- (void)setBackButtonIcon:(UIImage *)backButtonIcon
-{
- _backButtonIcon = backButtonIcon;
- _backButtonItem = nil;
-}
-
-- (UIBarButtonItem *)backButtonItem
-{
- if (!_backButtonItem) {
- if (_backButtonIcon) {
- _backButtonItem = [[UIBarButtonItem alloc] initWithImage:_backButtonIcon
- style:UIBarButtonItemStylePlain
- target:nil
- action:nil];
- } else if (_backButtonTitle.length) {
- _backButtonItem = [[UIBarButtonItem alloc] initWithTitle:_backButtonTitle
- style:UIBarButtonItemStylePlain
- target:nil
- action:nil];
- } else {
- _backButtonItem = nil;
- }
- }
- return _backButtonItem;
-}
-
-- (void)setLeftButtonTitle:(NSString *)leftButtonTitle
-{
- _leftButtonTitle = leftButtonTitle;
- _leftButtonItem = nil;
-}
-
-- (void)setLeftButtonIcon:(UIImage *)leftButtonIcon
-{
- _leftButtonIcon = leftButtonIcon;
- _leftButtonItem = nil;
-}
-
-- (void)setLeftButtonSystemIcon:(UIBarButtonSystemItem)leftButtonSystemIcon
-{
- _leftButtonSystemIcon = leftButtonSystemIcon;
- _leftButtonItem = nil;
-}
-
-- (UIBarButtonItem *)leftButtonItem
-{
- if (!_leftButtonItem) {
- if (_leftButtonIcon) {
- _leftButtonItem =
- [[UIBarButtonItem alloc] initWithImage:_leftButtonIcon
- style:UIBarButtonItemStylePlain
- target:self
- action:@selector(handleLeftButtonPress)];
-
- } else if (_leftButtonTitle.length) {
- _leftButtonItem =
- [[UIBarButtonItem alloc] initWithTitle:_leftButtonTitle
- style:UIBarButtonItemStylePlain
- target:self
- action:@selector(handleLeftButtonPress)];
-
- } else if (_leftButtonSystemIcon != NSNotFound) {
- _leftButtonItem =
- [[UIBarButtonItem alloc] initWithBarButtonSystemItem:_leftButtonSystemIcon
- target:self
- action:@selector(handleLeftButtonPress)];
- } else {
- _leftButtonItem = nil;
- }
- }
- return _leftButtonItem;
-}
-
-- (void)handleLeftButtonPress
-{
- if (_onLeftButtonPress) {
- _onLeftButtonPress(nil);
- }
-}
-
-- (void)setRightButtonTitle:(NSString *)rightButtonTitle
-{
- _rightButtonTitle = rightButtonTitle;
- _rightButtonItem = nil;
-}
-
-- (void)setRightButtonIcon:(UIImage *)rightButtonIcon
-{
- _rightButtonIcon = rightButtonIcon;
- _rightButtonItem = nil;
-}
-
-- (void)setRightButtonSystemIcon:(UIBarButtonSystemItem)rightButtonSystemIcon
-{
- _rightButtonSystemIcon = rightButtonSystemIcon;
- _rightButtonItem = nil;
-}
-
-- (UIBarButtonItem *)rightButtonItem
-{
- if (!_rightButtonItem) {
- if (_rightButtonIcon) {
- _rightButtonItem =
- [[UIBarButtonItem alloc] initWithImage:_rightButtonIcon
- style:UIBarButtonItemStylePlain
- target:self
- action:@selector(handleRightButtonPress)];
-
- } else if (_rightButtonTitle.length) {
- _rightButtonItem =
- [[UIBarButtonItem alloc] initWithTitle:_rightButtonTitle
- style:UIBarButtonItemStylePlain
- target:self
- action:@selector(handleRightButtonPress)];
-
- } else if (_rightButtonSystemIcon != NSNotFound) {
- _rightButtonItem =
- [[UIBarButtonItem alloc] initWithBarButtonSystemItem:_rightButtonSystemIcon
- target:self
- action:@selector(handleRightButtonPress)];
- } else {
- _rightButtonItem = nil;
- }
- }
- return _rightButtonItem;
-}
-
-- (void)handleRightButtonPress
-{
- if (_onRightButtonPress) {
- _onRightButtonPress(nil);
- }
-}
-
-@end
diff --git a/React/Views/RCTNavItemManager.h b/React/Views/RCTNavItemManager.h
deleted file mode 100644
index 8fcb61c36..000000000
--- a/React/Views/RCTNavItemManager.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-#import
-#import
-
-@interface RCTConvert (BarButtonSystemItem)
-
-+ (UIBarButtonSystemItem)UIBarButtonSystemItem:(id)json;
-
-@end
-
-@interface RCTNavItemManager : RCTViewManager
-
-@end
diff --git a/React/Views/RCTNavItemManager.m b/React/Views/RCTNavItemManager.m
deleted file mode 100644
index d9d349c5a..000000000
--- a/React/Views/RCTNavItemManager.m
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-#import "RCTNavItemManager.h"
-
-#import "RCTConvert.h"
-#import "RCTNavItem.h"
-
-@implementation RCTConvert (BarButtonSystemItem)
-
-RCT_ENUM_CONVERTER(UIBarButtonSystemItem, (@{
- @"done": @(UIBarButtonSystemItemDone),
- @"cancel": @(UIBarButtonSystemItemCancel),
- @"edit": @(UIBarButtonSystemItemEdit),
- @"save": @(UIBarButtonSystemItemSave),
- @"add": @(UIBarButtonSystemItemAdd),
- @"flexible-space": @(UIBarButtonSystemItemFlexibleSpace),
- @"fixed-space": @(UIBarButtonSystemItemFixedSpace),
- @"compose": @(UIBarButtonSystemItemCompose),
- @"reply": @(UIBarButtonSystemItemReply),
- @"action": @(UIBarButtonSystemItemAction),
- @"organize": @(UIBarButtonSystemItemOrganize),
- @"bookmarks": @(UIBarButtonSystemItemBookmarks),
- @"search": @(UIBarButtonSystemItemSearch),
- @"refresh": @(UIBarButtonSystemItemRefresh),
- @"stop": @(UIBarButtonSystemItemStop),
- @"camera": @(UIBarButtonSystemItemCamera),
- @"trash": @(UIBarButtonSystemItemTrash),
- @"play": @(UIBarButtonSystemItemPlay),
- @"pause": @(UIBarButtonSystemItemPause),
- @"rewind": @(UIBarButtonSystemItemRewind),
- @"fast-forward": @(UIBarButtonSystemItemFastForward),
- @"undo": @(UIBarButtonSystemItemUndo),
- @"redo": @(UIBarButtonSystemItemRedo),
- @"page-curl": @(UIBarButtonSystemItemPageCurl)
-}), NSNotFound, integerValue);
-
-@end
-
-@implementation RCTNavItemManager
-
-RCT_EXPORT_MODULE()
-
-- (UIView *)view
-{
- return [RCTNavItem new];
-}
-
-RCT_EXPORT_VIEW_PROPERTY(navigationBarHidden, BOOL)
-RCT_EXPORT_VIEW_PROPERTY(shadowHidden, BOOL)
-RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor)
-RCT_EXPORT_VIEW_PROPERTY(barTintColor, UIColor)
-#if !TARGET_OS_TV
-RCT_EXPORT_VIEW_PROPERTY(barStyle, UIBarStyle)
-#endif
-RCT_EXPORT_VIEW_PROPERTY(translucent, BOOL)
-
-RCT_EXPORT_VIEW_PROPERTY(title, NSString)
-RCT_EXPORT_VIEW_PROPERTY(titleTextColor, UIColor)
-RCT_EXPORT_VIEW_PROPERTY(titleImage, UIImage)
-
-RCT_EXPORT_VIEW_PROPERTY(backButtonIcon, UIImage)
-RCT_EXPORT_VIEW_PROPERTY(backButtonTitle, NSString)
-
-RCT_EXPORT_VIEW_PROPERTY(leftButtonTitle, NSString)
-RCT_EXPORT_VIEW_PROPERTY(leftButtonIcon, UIImage)
-RCT_EXPORT_VIEW_PROPERTY(leftButtonSystemIcon, UIBarButtonSystemItem)
-
-RCT_EXPORT_VIEW_PROPERTY(rightButtonIcon, UIImage)
-RCT_EXPORT_VIEW_PROPERTY(rightButtonTitle, NSString)
-RCT_EXPORT_VIEW_PROPERTY(rightButtonSystemIcon, UIBarButtonSystemItem)
-
-RCT_EXPORT_VIEW_PROPERTY(onLeftButtonPress, RCTBubblingEventBlock)
-RCT_EXPORT_VIEW_PROPERTY(onRightButtonPress, RCTBubblingEventBlock)
-
-@end
diff --git a/React/Views/RCTNavigator.h b/React/Views/RCTNavigator.h
deleted file mode 100644
index b8ad30141..000000000
--- a/React/Views/RCTNavigator.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-#import
-
-#import
-
-@class RCTBridge;
-
-@interface RCTNavigator : UIView
-
-@property (nonatomic, strong) UIView *reactNavSuperviewLink;
-@property (nonatomic, assign) NSInteger requestedTopOfStack;
-@property (nonatomic, assign) BOOL interactivePopGestureEnabled;
-
-- (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER;
-
-/**
- * Schedules a JavaScript navigation and prevents `UIKit` from navigating until
- * JavaScript has sent its scheduled navigation.
- *
- * @returns Whether or not a JavaScript driven navigation could be
- * scheduled/reserved. If returning `NO`, JavaScript should usually just do
- * nothing at all.
- */
-- (BOOL)requestSchedulingJavaScriptNavigation;
-
-- (void)uiManagerDidPerformMounting;
-
-@end
diff --git a/React/Views/RCTNavigator.m b/React/Views/RCTNavigator.m
deleted file mode 100644
index 0a0bfe61c..000000000
--- a/React/Views/RCTNavigator.m
+++ /dev/null
@@ -1,630 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-#import "RCTNavigator.h"
-
-#import "RCTAssert.h"
-#import "RCTBridge.h"
-#import "RCTConvert.h"
-#import "RCTEventDispatcher.h"
-#import "RCTLog.h"
-#import "RCTNavItem.h"
-#import "RCTScrollView.h"
-#import "RCTUtils.h"
-#import "RCTView.h"
-#import "RCTWrapperViewController.h"
-#import "UIView+React.h"
-
-typedef NS_ENUM(NSUInteger, RCTNavigationLock) {
- RCTNavigationLockNone,
- RCTNavigationLockNative,
- RCTNavigationLockJavaScript
-};
-
-// By default the interactive pop gesture will be enabled when the navigation bar is displayed
-// and disabled when hidden
-// RCTPopGestureStateDefault maps to the default behavior (mentioned above). Once popGestureState
-// leaves this value, it can never be returned back to it. This is because, due to a limitation in
-// the iOS APIs, once we override the default behavior of the gesture recognizer, we cannot return
-// back to it.
-// RCTPopGestureStateEnabled will enable the gesture independent of nav bar visibility
-// RCTPopGestureStateDisabled will disable the gesture independent of nav bar visibility
-typedef NS_ENUM(NSUInteger, RCTPopGestureState) {
- RCTPopGestureStateDefault = 0,
- RCTPopGestureStateEnabled,
- RCTPopGestureStateDisabled
-};
-
-NSInteger kNeverRequested = -1;
-NSInteger kNeverProgressed = -10000;
-
-
-@interface UINavigationController ()
-
-// need to declare this since `UINavigationController` doesn't publicly declare the fact that it implements
-// UINavigationBarDelegate :(
-- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;
-
-@end
-
-// http://stackoverflow.com/questions/5115135/uinavigationcontroller-how-to-cancel-the-back-button-event
-// There's no other way to do this unfortunately :(
-@interface RCTNavigationController : UINavigationController
-{
- dispatch_block_t _scrollCallback;
-}
-
-@property (nonatomic, assign) RCTNavigationLock navigationLock;
-
-@end
-
-/**
- * In general, `RCTNavigator` examines `_currentViews` (which are React child
- * views), and compares them to `_navigationController.viewControllers` (which
- * are controlled by UIKit).
- *
- * It is possible for JavaScript (`_currentViews`) to "get ahead" of native
- * (`navigationController.viewControllers`) and vice versa. JavaScript gets
- * ahead by adding/removing React subviews. Native gets ahead by swiping back,
- * or tapping the back button. In both cases, the other system is initially
- * unaware. And in both cases, `RCTNavigator` helps the other side "catch up".
- *
- * If `RCTNavigator` sees the number of React children have changed, it
- * pushes/pops accordingly. If `RCTNavigator` sees a `UIKit` driven push/pop, it
- * notifies JavaScript that this has happened, and expects that JavaScript will
- * eventually render more children to match `UIKit`. There's no rush for
- * JavaScript to catch up. But if it does render anything, it must catch up to
- * UIKit. It cannot deviate.
- *
- * To implement this, we need a lock, which we store on the native thread. This
- * lock allows one of the systems to push/pop views. Whoever wishes to
- * "get ahead" must obtain the lock. Whoever wishes to "catch up" must obtain
- * the lock. One thread may not "get ahead" or "catch up" when the other has
- * the lock. Once a thread has the lock, it can only do the following:
- *
- * 1. If it is behind, it may only catch up.
- * 2. If it is caught up or ahead, it may push or pop.
- *
- *
- * ========= Acquiring The Lock ==========
- *
- * JavaScript asynchronously acquires the lock using a native hook. It might be
- * rejected and receive the return value `false`.
- *
- * We acquire the native lock in `shouldPopItem`, which is called right before
- * native tries to push/pop, but only if JavaScript doesn't already have the
- * lock.
- *
- * ======== While JavaScript Has Lock ====
- *
- * When JavaScript has the lock, we have to block all `UIKit` driven pops:
- *
- * 1. Block back button navigation:
- * - Back button will invoke `shouldPopItem`, from which we return `NO` if
- * JavaScript has the lock.
- * - Back button will respect the return value `NO` and not permit
- * navigation.
- *
- * 2. Block swipe-to-go-back navigation:
- * - Swipe will trigger `shouldPopItem`, but swipe won't respect our `NO`
- * return value so we must disable the gesture recognizer while JavaScript
- * has the lock.
- *
- * ======== While Native Has Lock =======
- *
- * We simply deny JavaScript the right to acquire the lock.
- *
- *
- * ======== Releasing The Lock ===========
- *
- * Recall that the lock represents who has the right to either push/pop (or
- * catch up). As soon as we recognize that the side that has locked has carried
- * out what it scheduled to do, we can release the lock, but only after any
- * possible animations are completed.
- *
- * *IF* a scheduled operation results in a push/pop (not all do), then we can
- * only release the lock after the push/pop animation is complete because
- * UIKit. `didMoveToNavigationController` is invoked when the view is done
- * pushing/popping/animating. Native swipe-to-go-back interactions can be
- * aborted, however, and you'll never see that method invoked. So just to cover
- * that case, we also put an animation complete hook in
- * `animateAlongsideTransition` to make sure we free the lock, in case the
- * scheduled native push/pop never actually happened.
- *
- * For JavaScript:
- * - When we see that JavaScript has "caught up" to `UIKit`, and no pushes/pops
- * were needed, we can release the lock.
- * - When we see that JavaScript requires *some* push/pop, it's not yet done
- * carrying out what it scheduled to do. Just like with `UIKit` push/pops, we
- * still have to wait for it to be done animating
- * (`didMoveToNavigationController` is a suitable hook).
- *
- */
-@implementation RCTNavigationController
-
-/**
- * @param callback Callback that is invoked when a "scroll" interaction begins
- * so that `RCTNavigator` can notify `JavaScript`.
- */
-- (instancetype)initWithScrollCallback:(dispatch_block_t)callback
-{
- if ((self = [super initWithNibName:nil bundle:nil])) {
- _scrollCallback = callback;
- }
- return self;
-}
-
-/**
- * Invoked when either a navigation item has been popped off, or when a
- * swipe-back gesture has began. The swipe-back gesture doesn't respect the
- * return value of this method. The back button does. That's why we have to
- * completely disable the gesture recognizer for swipe-back while JS has the
- * lock.
- */
-- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
-{
-#if !TARGET_OS_TV
- if (self.interactivePopGestureRecognizer.state == UIGestureRecognizerStateBegan) {
- if (self.navigationLock == RCTNavigationLockNone) {
- self.navigationLock = RCTNavigationLockNative;
- if (_scrollCallback) {
- _scrollCallback();
- }
- } else if (self.navigationLock == RCTNavigationLockJavaScript) {
- // This should never happen because we disable/enable the gesture
- // recognizer when we lock the navigation.
- RCTAssert(NO, @"Should never receive gesture start while JS locks navigator");
- }
- } else
-#endif //TARGET_OS_TV
- {
- if (self.navigationLock == RCTNavigationLockNone) {
- // Must be coming from native interaction, lock it - it will be unlocked
- // in `didMoveToNavigationController`
- self.navigationLock = RCTNavigationLockNative;
- if (_scrollCallback) {
- _scrollCallback();
- }
- } else if (self.navigationLock == RCTNavigationLockJavaScript) {
- // This should only occur when JS has the lock, and
- // - JS is driving the pop
- // - Or the back button was pressed
- // TODO: We actually want to disable the backbutton while JS has the
- // lock, but it's not so easy. Even returning `NO` wont' work because it
- // will also block JS driven pops. We simply need to disallow a standard
- // back button, and instead use a custom one that tells JS to pop to
- // length (`currentReactCount` - 1).
- return [super navigationBar:navigationBar shouldPopItem:item];
- }
- }
- return [super navigationBar:navigationBar shouldPopItem:item];
-}
-
-@end
-
-@interface RCTNavigator()
-
-@property (nonatomic, copy) RCTDirectEventBlock onNavigationProgress;
-@property (nonatomic, copy) RCTBubblingEventBlock onNavigationComplete;
-
-@property (nonatomic, assign) NSInteger previousRequestedTopOfStack;
-
-@property (nonatomic, assign) RCTPopGestureState popGestureState;
-
-// Previous views are only mainted in order to detect incorrect
-// addition/removal of views below the `requestedTopOfStack`
-@property (nonatomic, copy, readwrite) NSArray *previousViews;
-@property (nonatomic, readwrite, strong) RCTNavigationController *navigationController;
-/**
- * Display link is used to get high frequency sample rate during
- * interaction/animation of view controller push/pop.
- *
- * - The run loop retains the displayLink.
- * - `displayLink` retains its target.
- * - We use `invalidate` to remove the `RCTNavigator`'s reference to the
- * `displayLink` and remove the `displayLink` from the run loop.
- *
- *
- * `displayLink`:
- * --------------
- *
- * - Even though we could implement the `displayLink` cleanup without the
- * `invalidate` hook by adding and removing it from the run loop at the
- * right times (begin/end animation), we need to account for the possibility
- * that the view itself is destroyed mid-interaction. So we always keep it
- * added to the run loop, but start/stop it with interactions/animations. We
- * remove it from the run loop when the view will be destroyed by React.
- *
- * +----------+ +--------------+
- * | run loop o----strong--->| displayLink |
- * +----------+ +--o-----------+
- * | ^
- * | |
- * strong strong
- * | |
- * v |
- * +---------o---+
- * | RCTNavigator |
- * +-------------+
- *
- * `dummyView`:
- * ------------
- * There's no easy way to get a callback that fires when the position of a
- * navigation item changes. The actual layers that are moved around during the
- * navigation transition are private. Our only hope is to use
- * `animateAlongsideTransition`, to set a dummy view's position to transition
- * anywhere from -1.0 to 1.0. We later set up a `CADisplayLink` to poll the
- * `presentationLayer` of that dummy view and report the value as a "progress"
- * percentage.
- *
- * It was critical that we added the dummy view as a subview of the
- * transitionCoordinator's `containerView`, otherwise the animations would not
- * work correctly when reversing the gesture direction etc. This seems to be
- * undocumented behavior/requirement.
- *
- */
-@property (nonatomic, readonly, assign) CGFloat mostRecentProgress;
-@property (nonatomic, readonly, strong) NSTimer *runTimer;
-@property (nonatomic, readonly, assign) NSInteger currentlyTransitioningFrom;
-@property (nonatomic, readonly, assign) NSInteger currentlyTransitioningTo;
-
-// Dummy view that we make animate with the same curve/interaction as the
-// navigation animation/interaction.
-@property (nonatomic, readonly, strong) UIView *dummyView;
-
-@end
-
-@implementation RCTNavigator
-{
- __weak RCTBridge *_bridge;
- NSInteger _numberOfViewControllerMovesToIgnore;
-}
-
-@synthesize paused = _paused;
-@synthesize pauseCallback = _pauseCallback;
-
-- (instancetype)initWithBridge:(RCTBridge *)bridge
-{
- RCTAssertParam(bridge);
-
- if ((self = [super initWithFrame:CGRectZero])) {
- _paused = YES;
-
- _bridge = bridge;
- _mostRecentProgress = kNeverProgressed;
- _dummyView = [[UIView alloc] initWithFrame:CGRectZero];
- _previousRequestedTopOfStack = kNeverRequested; // So that we initialize with a push.
- _previousViews = @[];
- __weak RCTNavigator *weakSelf = self;
- _navigationController = [[RCTNavigationController alloc] initWithScrollCallback:^{
- [weakSelf dispatchFakeScrollEvent];
- }];
- _navigationController.delegate = self;
- RCTAssert([self requestSchedulingJavaScriptNavigation], @"Could not acquire JS navigation lock on init");
-
- [self addSubview:_navigationController.view];
- [_navigationController.view addSubview:_dummyView];
- }
- return self;
-}
-
-RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
-RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
-
-- (void)didUpdateFrame:(__unused RCTFrameUpdate *)update
-{
- if (_currentlyTransitioningFrom != _currentlyTransitioningTo) {
- UIView *topView = _dummyView;
- id presentationLayer = [topView.layer presentationLayer];
- CGRect frame = [presentationLayer frame];
- CGFloat nextProgress = ABS(frame.origin.x);
- // Don't want to spam the bridge, when the user holds their finger still mid-navigation.
- if (nextProgress == _mostRecentProgress) {
- return;
- }
- _mostRecentProgress = nextProgress;
- if (_onNavigationProgress) {
- _onNavigationProgress(@{
- @"fromIndex": @(_currentlyTransitioningFrom),
- @"toIndex": @(_currentlyTransitioningTo),
- @"progress": @(nextProgress),
- });
- }
- }
-}
-
-- (void)setPaused:(BOOL)paused
-{
- if (_paused != paused) {
- _paused = paused;
- if (_pauseCallback) {
- _pauseCallback();
- }
- }
-}
-
-- (void)setInteractivePopGestureEnabled:(BOOL)interactivePopGestureEnabled
-{
-#if !TARGET_OS_TV
- _interactivePopGestureEnabled = interactivePopGestureEnabled;
-
- _navigationController.interactivePopGestureRecognizer.delegate = self;
- _navigationController.interactivePopGestureRecognizer.enabled = interactivePopGestureEnabled;
-
- _popGestureState = interactivePopGestureEnabled ? RCTPopGestureStateEnabled : RCTPopGestureStateDisabled;
-#endif
-}
-
-- (void)dealloc
-{
-#if !TARGET_OS_TV
- if (_navigationController.interactivePopGestureRecognizer.delegate == self) {
- _navigationController.interactivePopGestureRecognizer.delegate = nil;
- }
-#endif
- _navigationController.delegate = nil;
- [_navigationController removeFromParentViewController];
-}
-
-- (UIViewController *)reactViewController
-{
- return _navigationController;
-}
-
-- (BOOL)gestureRecognizerShouldBegin:(__unused UIGestureRecognizer *)gestureRecognizer
-{
- return _navigationController.viewControllers.count > 1;
-}
-
-/**
- * See documentation about lock lifecycle. This is only here to clean up
- * swipe-back abort interaction, which leaves us *no* other way to clean up
- * locks aside from the animation complete hook.
- */
-- (void)navigationController:(UINavigationController *)navigationController
- willShowViewController:(__unused UIViewController *)viewController
- animated:(__unused BOOL)animated
-{
- id tc =
- navigationController.topViewController.transitionCoordinator;
- __weak RCTNavigator *weakSelf = self;
- [tc.containerView addSubview: _dummyView];
- [tc animateAlongsideTransition: ^(id context) {
- RCTWrapperViewController *fromController =
- (RCTWrapperViewController *)[context viewControllerForKey:UITransitionContextFromViewControllerKey];
- RCTWrapperViewController *toController =
- (RCTWrapperViewController *)[context viewControllerForKey:UITransitionContextToViewControllerKey];
-
- // This may be triggered by a navigation controller unrelated to me: if so, ignore.
- if (fromController.navigationController != self->_navigationController ||
- toController.navigationController != self->_navigationController) {
- return;
- }
-
- NSUInteger indexOfFrom = [self.reactSubviews indexOfObject:fromController.navItem];
- NSUInteger indexOfTo = [self.reactSubviews indexOfObject:toController.navItem];
- CGFloat destination = indexOfFrom < indexOfTo ? 1.0 : -1.0;
- self->_dummyView.frame = (CGRect){{destination, 0}, CGSizeZero};
- self->_currentlyTransitioningFrom = indexOfFrom;
- self->_currentlyTransitioningTo = indexOfTo;
- self.paused = NO;
- }
- completion:^(__unused id context) {
- [weakSelf freeLock];
- self->_currentlyTransitioningFrom = 0;
- self->_currentlyTransitioningTo = 0;
- self->_dummyView.frame = CGRectZero;
- self.paused = YES;
- // Reset the parallel position tracker
- }];
-}
-
-- (BOOL)requestSchedulingJavaScriptNavigation
-{
- if (_navigationController.navigationLock == RCTNavigationLockNone) {
- _navigationController.navigationLock = RCTNavigationLockJavaScript;
-#if !TARGET_OS_TV
- _navigationController.interactivePopGestureRecognizer.enabled = NO;
-#endif
- return YES;
- }
- return NO;
-}
-
-- (void)freeLock
-{
- _navigationController.navigationLock = RCTNavigationLockNone;
-
- // Unless the pop gesture has been explicitly disabled (RCTPopGestureStateDisabled),
- // Set interactivePopGestureRecognizer.enabled to YES
- // If the popGestureState is RCTPopGestureStateDefault the default behavior will be maintained
-#if !TARGET_OS_TV
- _navigationController.interactivePopGestureRecognizer.enabled = self.popGestureState != RCTPopGestureStateDisabled;
-#endif
-}
-
-/**
- * A React subview can be inserted/removed at any time, however if the
- * `requestedTopOfStack` changes, there had better be enough subviews present
- * to satisfy the push/pop.
- */
-- (void)insertReactSubview:(RCTNavItem *)view atIndex:(NSInteger)atIndex
-{
- RCTAssert([view isKindOfClass:[RCTNavItem class]], @"RCTNavigator only accepts RCTNavItem subviews");
- RCTAssert(
- _navigationController.navigationLock == RCTNavigationLockJavaScript,
- @"Cannot change subviews from JS without first locking."
- );
- [super insertReactSubview:view atIndex:atIndex];
-}
-
-- (void)didUpdateReactSubviews
-{
- // Do nothing, as subviews are managed by `uiManagerDidPerformMounting`
-}
-
-- (void)layoutSubviews
-{
- [super layoutSubviews];
- [self reactAddControllerToClosestParent:_navigationController];
- _navigationController.view.frame = self.bounds;
-}
-
-- (void)removeReactSubview:(RCTNavItem *)subview
-{
- if (self.reactSubviews.count <= 0 || subview == self.reactSubviews[0]) {
- RCTLogError(@"Attempting to remove invalid RCT subview of RCTNavigator");
- return;
- }
- [super removeReactSubview:subview];
-}
-
-- (void)handleTopOfStackChanged
-{
- if (_onNavigationComplete) {
- _onNavigationComplete(@{
- @"stackLength":@(_navigationController.viewControllers.count)
- });
- }
-}
-
-- (void)dispatchFakeScrollEvent
-{
- [_bridge.eventDispatcher sendFakeScrollEvent:self.reactTag];
-}
-
-/**
- * Must be overridden because UIKit removes the view's superview when used
- * as a navigator - it's considered outside the view hierarchy.
- */
-- (UIView *)reactSuperview
-{
- RCTAssert(!_bridge.isValid || self.superview != nil, @"put reactNavSuperviewLink back");
- UIView *superview = [super reactSuperview];
- return superview ?: self.reactNavSuperviewLink;
-}
-
-- (void)uiManagerDidPerformMounting
-{
- // we can't hook up the VC hierarchy in 'init' because the subviews aren't
- // hooked up yet, so we do it on demand here
- [self reactAddControllerToClosestParent:_navigationController];
-
- NSUInteger viewControllerCount = _navigationController.viewControllers.count;
- // The "react count" is the count of views that are visible on the navigation
- // stack. There may be more beyond this - that aren't visible, and may be
- // deleted/purged soon.
- NSUInteger previousReactCount =
- _previousRequestedTopOfStack == kNeverRequested ? 0 : _previousRequestedTopOfStack + 1;
- NSUInteger currentReactCount = _requestedTopOfStack + 1;
-
- BOOL jsGettingAhead =
- // ----- previously caught up ------ ------ no longer caught up -------
- viewControllerCount == previousReactCount && currentReactCount != viewControllerCount;
- BOOL jsCatchingUp =
- // --- previously not caught up ---- --------- now caught up ----------
- viewControllerCount != previousReactCount && currentReactCount == viewControllerCount;
- BOOL jsMakingNoProgressButNeedsToCatchUp =
- // --- previously not caught up ---- ------- still the same -----------
- viewControllerCount != previousReactCount && currentReactCount == previousReactCount;
- BOOL jsMakingNoProgressAndDoesntNeedTo =
- // --- previously caught up -------- ------- still caught up ----------
- viewControllerCount == previousReactCount && currentReactCount == previousReactCount;
-
-BOOL jsGettingtooSlow =
- // --- previously not caught up -------- ------- no longer caught up ----------
- viewControllerCount < previousReactCount && currentReactCount < previousReactCount;
-
- BOOL reactPushOne = jsGettingAhead && currentReactCount == previousReactCount + 1;
- BOOL reactPopN = jsGettingAhead && currentReactCount < previousReactCount;
-
- // We can actually recover from this situation, but it would be nice to know
- // when this error happens. This simply means that JS hasn't caught up to a
- // back navigation before progressing. It's likely a bug in the JS code that
- // catches up/schedules navigations.
- if (!(jsGettingAhead ||
- jsCatchingUp ||
- jsMakingNoProgressButNeedsToCatchUp ||
- jsMakingNoProgressAndDoesntNeedTo ||
- jsGettingtooSlow)) {
- RCTLogError(@"JS has only made partial progress to catch up to UIKit");
- }
- if (currentReactCount > self.reactSubviews.count) {
- RCTLogError(@"Cannot adjust current top of stack beyond available views");
- }
-
- // Views before the previous React count must not have changed. Views greater than previousReactCount
- // up to currentReactCount may have changed.
- for (NSUInteger i = 0; i < MIN(self.reactSubviews.count, MIN(_previousViews.count, previousReactCount)); i++) {
- if (self.reactSubviews[i] != _previousViews[i]) {
- RCTLogError(@"current view should equal previous view");
- }
- }
- if (currentReactCount < 1) {
- RCTLogError(@"should be at least one current view");
- }
- if (jsGettingAhead) {
- if (reactPushOne) {
- UIView *lastView = self.reactSubviews.lastObject;
- RCTWrapperViewController *vc = [[RCTWrapperViewController alloc] initWithNavItem:(RCTNavItem *)lastView];
- vc.navigationListener = self;
- _numberOfViewControllerMovesToIgnore = 1;
- [_navigationController pushViewController:vc animated:(currentReactCount > 1)];
- } else if (reactPopN) {
- UIViewController *viewControllerToPopTo = _navigationController.viewControllers[(currentReactCount - 1)];
- _numberOfViewControllerMovesToIgnore = viewControllerCount - currentReactCount;
- [_navigationController popToViewController:viewControllerToPopTo animated:YES];
- } else {
- RCTLogError(@"Pushing or popping more than one view at a time from JS");
- }
- } else if (jsCatchingUp) {
- [self freeLock]; // Nothing to push/pop
- } else {
- // Else, JS making no progress, could have been unrelated to anything nav.
- return;
- }
-
- // Only make a copy of the subviews whose validity we expect to be able to check (in the loop, above),
- // otherwise we would unnecessarily retain a reference to view(s) no longer on the React navigation stack:
- NSUInteger expectedCount = MIN(currentReactCount, self.reactSubviews.count);
- _previousViews = [[self.reactSubviews subarrayWithRange: NSMakeRange(0, expectedCount)] copy];
- _previousRequestedTopOfStack = _requestedTopOfStack;
-}
-
-// TODO: This will likely fail when performing multiple pushes/pops. We must
-// free the lock only after the *last* push/pop.
-- (void)wrapperViewController:(RCTWrapperViewController *)wrapperViewController
-didMoveToNavigationController:(UINavigationController *)navigationController
-{
- if (self.superview == nil) {
- // If superview is nil, then a JS reload (Cmd+R) happened
- // while a push/pop is in progress.
- return;
- }
-
- RCTAssert(
- (navigationController == nil || [_navigationController.viewControllers containsObject:wrapperViewController]),
- @"if navigation controller is not nil, it should contain the wrapper view controller"
- );
- RCTAssert(_navigationController.navigationLock == RCTNavigationLockJavaScript ||
- _numberOfViewControllerMovesToIgnore == 0,
- @"If JS doesn't have the lock there should never be any pending transitions");
- /**
- * When JS has the lock we want to keep track of when the request completes
- * the pending transition count hitting 0 signifies this, and should always
- * remain at 0 when JS does not have the lock
- */
- if (_numberOfViewControllerMovesToIgnore > 0) {
- _numberOfViewControllerMovesToIgnore -= 1;
- }
- if (_numberOfViewControllerMovesToIgnore == 0) {
- [self handleTopOfStackChanged];
- [self freeLock];
- }
-}
-
-@end
diff --git a/React/Views/RCTNavigatorManager.h b/React/Views/RCTNavigatorManager.h
deleted file mode 100644
index 58c40c94e..000000000
--- a/React/Views/RCTNavigatorManager.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-#import
-
-@interface RCTNavigatorManager : RCTViewManager
-
-@end
diff --git a/React/Views/RCTNavigatorManager.m b/React/Views/RCTNavigatorManager.m
deleted file mode 100644
index 99a03cbb3..000000000
--- a/React/Views/RCTNavigatorManager.m
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * Copyright (c) 2015-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-#import "RCTNavigatorManager.h"
-
-#import "RCTBridge.h"
-#import "RCTConvert.h"
-#import "RCTNavigator.h"
-#import "RCTUIManager.h"
-#import "RCTUIManagerObserverCoordinator.h"
-#import "UIView+React.h"
-
-@interface RCTNavigatorManager ()
-
-@end
-
-@implementation RCTNavigatorManager
-{
- // The main thread only.
- NSHashTable *_viewRegistry;
-}
-
-- (void)setBridge:(RCTBridge *)bridge
-{
- [super setBridge:bridge];
-
- [self.bridge.uiManager.observerCoordinator addObserver:self];
-}
-
-- (void)invalidate
-{
- [self.bridge.uiManager.observerCoordinator removeObserver:self];
-}
-
-RCT_EXPORT_MODULE()
-
-- (UIView *)view
-{
- if (!_viewRegistry) {
- _viewRegistry = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
- }
-
- RCTNavigator *view = [[RCTNavigator alloc] initWithBridge:self.bridge];
- [_viewRegistry addObject:view];
- return view;
-}
-
-RCT_EXPORT_VIEW_PROPERTY(requestedTopOfStack, NSInteger)
-RCT_EXPORT_VIEW_PROPERTY(onNavigationProgress, RCTDirectEventBlock)
-RCT_EXPORT_VIEW_PROPERTY(onNavigationComplete, RCTBubblingEventBlock)
-RCT_EXPORT_VIEW_PROPERTY(interactivePopGestureEnabled, BOOL)
-
-RCT_EXPORT_METHOD(requestSchedulingJavaScriptNavigation:(nonnull NSNumber *)reactTag
- callback:(RCTResponseSenderBlock)callback)
-{
- [self.bridge.uiManager addUIBlock:
- ^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry){
- RCTNavigator *navigator = viewRegistry[reactTag];
- if ([navigator isKindOfClass:[RCTNavigator class]]) {
- BOOL wasAcquired = [navigator requestSchedulingJavaScriptNavigation];
- callback(@[@(wasAcquired)]);
- } else {
- RCTLogError(@"Cannot set lock: %@ (tag #%@) is not an RCTNavigator", navigator, reactTag);
- }
- }];
-}
-
-#pragma mark - RCTUIManagerObserver
-
-- (void)uiManagerDidPerformMounting:(__unused RCTUIManager *)manager
-{
- RCTExecuteOnMainQueue(^{
- for (RCTNavigator *view in self->_viewRegistry) {
- [view uiManagerDidPerformMounting];
- }
- });
-}
-
-@end
diff --git a/React/Views/RCTWrapperViewController.h b/React/Views/RCTWrapperViewController.h
index 7baa0c08c..675dc0a04 100644
--- a/React/Views/RCTWrapperViewController.h
+++ b/React/Views/RCTWrapperViewController.h
@@ -7,22 +7,10 @@
#import
-@class RCTNavItem;
@class RCTWrapperViewController;
-@protocol RCTWrapperViewControllerNavigationListener
-
-- (void)wrapperViewController:(RCTWrapperViewController *)wrapperViewController
-didMoveToNavigationController:(UINavigationController *)navigationController;
-
-@end
-
@interface RCTWrapperViewController : UIViewController
- (instancetype)initWithContentView:(UIView *)contentView NS_DESIGNATED_INITIALIZER;
-- (instancetype)initWithNavItem:(RCTNavItem *)navItem;
-
-@property (nonatomic, weak) id navigationListener;
-@property (nonatomic, strong) RCTNavItem *navItem;
@end
diff --git a/React/Views/RCTWrapperViewController.m b/React/Views/RCTWrapperViewController.m
index 30103019e..63df725fb 100644
--- a/React/Views/RCTWrapperViewController.m
+++ b/React/Views/RCTWrapperViewController.m
@@ -10,7 +10,6 @@
#import
#import "RCTEventDispatcher.h"
-#import "RCTNavItem.h"
#import "RCTUtils.h"
#import "UIView+React.h"
#import "RCTAutoInsetsProtocol.h"
@@ -38,14 +37,6 @@
return self;
}
-- (instancetype)initWithNavItem:(RCTNavItem *)navItem
-{
- if ((self = [self initWithContentView:navItem])) {
- _navItem = navItem;
- }
- return self;
-}
-
RCT_NOT_IMPLEMENTED(- (instancetype)initWithNibName:(NSString *)nn bundle:(NSBundle *)nb)
RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
@@ -83,55 +74,6 @@ static BOOL RCTFindScrollViewAndRefreshContentInsetInView(UIView *view)
}
}
-static UIView *RCTFindNavBarShadowViewInView(UIView *view)
-{
- if ([view isKindOfClass:[UIImageView class]] && view.bounds.size.height <= 1) {
- return view;
- }
- for (UIView *subview in view.subviews) {
- UIView *shadowView = RCTFindNavBarShadowViewInView(subview);
- if (shadowView) {
- return shadowView;
- }
- }
- return nil;
-}
-
-- (void)viewWillAppear:(BOOL)animated
-{
- [super viewWillAppear:animated];
-
- // TODO: find a way to make this less-tightly coupled to navigation controller
- if ([self.parentViewController isKindOfClass:[UINavigationController class]])
- {
- [self.navigationController
- setNavigationBarHidden:_navItem.navigationBarHidden
- animated:animated];
-
- UINavigationBar *bar = self.navigationController.navigationBar;
- bar.barTintColor = _navItem.barTintColor;
- bar.tintColor = _navItem.tintColor;
- bar.translucent = _navItem.translucent;
-#if !TARGET_OS_TV
- bar.barStyle = _navItem.barStyle;
-#endif
- bar.titleTextAttributes = _navItem.titleTextColor ? @{
- NSForegroundColorAttributeName: _navItem.titleTextColor
- } : nil;
-
- RCTFindNavBarShadowViewInView(bar).hidden = _navItem.shadowHidden;
-
- UINavigationItem *item = self.navigationItem;
- item.title = _navItem.title;
- item.titleView = _navItem.titleImageView;
-#if !TARGET_OS_TV
- item.backBarButtonItem = _navItem.backButtonItem;
-#endif //TARGET_OS_TV
- item.leftBarButtonItem = _navItem.leftButtonItem;
- item.rightBarButtonItem = _navItem.rightButtonItem;
- }
-}
-
- (void)loadView
{
// Add a wrapper so that the wrapper view managed by the
@@ -142,16 +84,4 @@ static UIView *RCTFindNavBarShadowViewInView(UIView *view)
self.view = _wrapperView;
}
-- (void)didMoveToParentViewController:(UIViewController *)parent
-{
- // There's no clear setter for navigation controllers, but did move to parent
- // view controller provides the desired effect. This is called after a pop
- // finishes, be it a swipe to go back or a standard tap on the back button
- [super didMoveToParentViewController:parent];
- if (parent == nil || [parent isKindOfClass:[UINavigationController class]]) {
- [self.navigationListener wrapperViewController:self
- didMoveToNavigationController:(UINavigationController *)parent];
- }
-}
-
@end