diff --git a/Examples/UIExplorer/UIExplorerApp.ios.js b/Examples/UIExplorer/UIExplorerApp.ios.js index fe643dec50..e5bfd22a37 100644 --- a/Examples/UIExplorer/UIExplorerApp.ios.js +++ b/Examples/UIExplorer/UIExplorerApp.ios.js @@ -43,22 +43,23 @@ var UIExplorerApp = React.createClass({ /> ); } - return ( - { - this.setState({ openExternalExample: example, }); - }, - } - }} - itemWrapperStyle={styles.itemWrapper} - tintColor="#008888" - /> - ); + + return ( + { + this.setState({ openExternalExample: example, }); + }, + } + }} + itemWrapperStyle={styles.itemWrapper} + tintColor="#008888" + /> + ); } }); diff --git a/Examples/UIExplorer/UIExplorerList.js b/Examples/UIExplorer/UIExplorerList.js index 1803c7ebd8..8a7782484a 100644 --- a/Examples/UIExplorer/UIExplorerList.js +++ b/Examples/UIExplorer/UIExplorerList.js @@ -32,6 +32,7 @@ var { var { TestModule } = React.addons; import type { ExampleModule } from 'ExampleTypes'; +import type { NavigationContext } from 'NavigationContext'; var createExamplePage = require('./createExamplePage'); @@ -129,7 +130,10 @@ COMPONENTS.concat(APIS).forEach((Example) => { }); type Props = { - navigator: Array<{title: string, component: ReactClass}>, + navigator: { + navigationContext: NavigationContext, + push: (route: {title: string, component: ReactClass}) => void, + }, onExternalExampleRequested: Function, onSelectExample: Function, isInDrawer: bool, @@ -149,8 +153,25 @@ class UIExplorerList extends React.Component { }; } + componentWillMount() { + this.props.navigator.navigationContext.addListener('didfocus', function(event) { + if (event.data.route.title === 'UIExplorer') { + Settings.set({visibleExample: null}); + } + }); + } + componentDidMount() { this._search(this.state.searchText); + + var visibleExampleTitle = Settings.get('visibleExample'); + if (visibleExampleTitle) { + var predicate = (example) => example.title === visibleExampleTitle; + var foundExample = APIS.find(predicate) || COMPONENTS.find(predicate); + if (foundExample) { + setTimeout(() => this._openExample(foundExample), 100); + } + } } render() { @@ -240,11 +261,12 @@ class UIExplorerList extends React.Component { Settings.set({searchText: text}); } - _onPressRow(example: any) { + _openExample(example: any) { if (example.external) { this.props.onExternalExampleRequested(example); return; } + var Component = makeRenderable(example); if (Platform.OS === 'ios') { this.props.navigator.push({ @@ -258,6 +280,11 @@ class UIExplorerList extends React.Component { }); } } + + _onPressRow(example: any) { + Settings.set({visibleExample: example.title}); + this._openExample(example); + } } var styles = StyleSheet.create({ diff --git a/Libraries/Components/Navigation/NavigatorIOS.ios.js b/Libraries/Components/Navigation/NavigatorIOS.ios.js index 788273ec53..023257b146 100644 --- a/Libraries/Components/Navigation/NavigatorIOS.ios.js +++ b/Libraries/Components/Navigation/NavigatorIOS.ios.js @@ -13,6 +13,7 @@ var EventEmitter = require('EventEmitter'); var Image = require('Image'); +var NavigationContext = require('NavigationContext'); var React = require('React'); var ReactNativeViewAttributes = require('ReactNativeViewAttributes'); var RCTNavigatorManager = require('NativeModules').NavigatorManager; @@ -309,6 +310,7 @@ var NavigatorIOS = React.createClass({ }, navigator: (undefined: ?Object), + navigationContext: new NavigationContext(), componentWillMount: function() { // Precompute a pack of callbacks that's frequently generated and passed to @@ -323,7 +325,18 @@ var NavigatorIOS = React.createClass({ resetTo: this.resetTo, popToRoute: this.popToRoute, popToTop: this.popToTop, + navigationContext: this.navigationContext, }; + this._emitWillFocus(this.state.routeStack[this.state.observedTopOfStack]); + }, + + componentDidMount: function() { + this._emitDidFocus(this.state.routeStack[this.state.observedTopOfStack]); + }, + + componentWillUnmount: function() { + this.navigationContext.dispose(); + this.navigationContext = new NavigationContext(); }, getInitialState: function(): State { @@ -397,6 +410,8 @@ var NavigatorIOS = React.createClass({ _handleNavigatorStackChanged: function(e: Event) { var newObservedTopOfStack = e.nativeEvent.stackLength - 1; + this._emitDidFocus(this.state.routeStack[newObservedTopOfStack]); + invariant( newObservedTopOfStack <= this.state.requestedTopOfStack, 'No navigator item should be pushed without JS knowing about it %s %s', newObservedTopOfStack, this.state.requestedTopOfStack @@ -448,11 +463,21 @@ var NavigatorIOS = React.createClass({ }); }, + _emitDidFocus: function(route: Route) { + this.navigationContext.emit('didfocus', {route: route}); + }, + + _emitWillFocus: function(route: Route) { + this.navigationContext.emit('willfocus', {route: route}); + }, + 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(() => { + this._emitWillFocus(route); + var nextStack = this.state.routeStack.concat([route]); var nextIDStack = this.state.idStack.concat([getuid()]); this.setState({ @@ -476,12 +501,11 @@ var NavigatorIOS = React.createClass({ if (this.state.requestedTopOfStack === this.state.observedTopOfStack) { if (this.state.requestedTopOfStack > 0) { this._tryLockNavigator(() => { - invariant( - this.state.requestedTopOfStack - n >= 0, - 'Cannot pop below 0' - ); + var newRequestedTopOfStack = this.state.requestedTopOfStack - n; + invariant(newRequestedTopOfStack >= 0, 'Cannot pop below 0'); + this._emitWillFocus(this.state.routeStack[newRequestedTopOfStack]); this.setState({ - requestedTopOfStack: this.state.requestedTopOfStack - n, + requestedTopOfStack: newRequestedTopOfStack, makingNavigatorRequest: true, // Not actually updating the indices yet until we get the native // `onNavigationComplete`. @@ -525,6 +549,9 @@ var NavigatorIOS = React.createClass({ makingNavigatorRequest: false, updatingAllIndicesAtOrBeyond: index, }); + + this._emitWillFocus(route); + this._emitDidFocus(route); }, /** @@ -659,7 +686,7 @@ var NavigatorIOS = React.createClass({ {this.renderNavigationStackItems()} ); - } + }, }); var styles = StyleSheet.create({