diff --git a/app/navigation/navigation_modal.js b/app/navigation/navigation_modal.js index 4a68aa1c2..22429679c 100644 --- a/app/navigation/navigation_modal.js +++ b/app/navigation/navigation_modal.js @@ -24,33 +24,41 @@ export default class NavigationModal extends PureComponent { } componentWillReceiveProps(nextProps) { - if (this.props.show === nextProps.show) { - return; - } + if (nextProps.show) { + let currentRouteKeys; + const nextRouteKeys = nextProps.children.props.navigationState.routes.map((r) => r.key).join(''); + if (this.state.children) { + currentRouteKeys = this.state.children.props.navigationState.routes.map((r) => r.key).join(''); + } - // In order for the scene to be shown throughout the - // animated slide down we have to hang on to it by - // storing it in state - if (!this.state.children) { - this.setState({ - children: nextProps.children - }); - } + const routesDidChange = currentRouteKeys !== nextRouteKeys; - const animateValue = nextProps.show ? 0 : deviceHeight; - - Animated.timing(this.state.top, { - toValue: animateValue, - duration: 400 - }).start(() => { - // Once the scene has finished sliding down we can release the child scene - // which will unmount the scene correctly. - if (!this.props.show && !nextProps.show) { + // In order for the scene to be shown throughout the + // animated slide down we have to hang on to it by + // storing it in state + if (routesDidChange) { this.setState({ - children: null + children: nextProps.children }); } - }); + } + + if (nextProps.show !== this.props.show) { + const animateValue = nextProps.show ? 0 : deviceHeight; + + Animated.timing(this.state.top, { + toValue: animateValue, + duration: 400 + }).start(() => { + // Once the scene has finished sliding down we can release the child scene + // which will unmount the scene correctly. + if (!this.props.show && !nextProps.show) { + this.setState({ + children: null + }); + } + }); + } } render() { diff --git a/app/navigation/router.js b/app/navigation/router.js index e46d81e5d..56eb5966d 100644 --- a/app/navigation/router.js +++ b/app/navigation/router.js @@ -30,26 +30,26 @@ class Router extends React.Component { headerEventSubscriptions = {}; - emitHeaderEvent = (event) => { - const subscription = this.headerEventSubscriptions[event]; + emitHeaderEvent = (key) => (event) => { + const subscription = this.headerEventSubscriptions[`${key}-${event}`]; if (subscription) { subscription(); } } - subscribeToHeaderEvent = (event, callback) => { - this.headerEventSubscriptions[event] = callback; + subscribeToHeaderEvent = (key) => (event, callback) => { + this.headerEventSubscriptions[`${key}-${event}`] = callback; } - unsubscribeFromHeaderEvent = (event) => { + unsubscribeFromHeaderEvent = (key) => (event) => { if (this.headerEventSubscriptions[event]) { - Reflect.deleteProperty(this.headerEventSubscriptions, event); + Reflect.deleteProperty(this.headerEventSubscriptions, `${key}-${event}`); } } - wrapHeaderComponent = (fx) => (props) => { + wrapHeaderComponent = (fx, emitter) => (props) => { if (fx && props.scene.isActive) { - return fx(props, this.emitHeaderEvent, this.props.theme); + return fx(props, emitter, this.props.theme); } return null; @@ -63,9 +63,10 @@ class Router extends React.Component { const navigationProps = this.extractNavigationProps(transitionProps.scene.route); let navBar = null; if (!navigationProps.hideNavBar) { - const renderLeftComponent = transitionProps.navigationState.index > 0 ? this.wrapHeaderComponent(navigationProps.renderBackButton) : this.wrapHeaderComponent(navigationProps.renderLeftComponent); - const renderTitleComponent = navigationProps.renderTitleComponent ? this.wrapHeaderComponent(navigationProps.renderTitleComponent) : this.renderTitle; - const renderRightComponent = this.wrapHeaderComponent(navigationProps.renderRightComponent); + const emitter = this.emitHeaderEvent(transitionProps.scene.route.key); + const renderLeftComponent = transitionProps.navigationState.index > 0 ? this.wrapHeaderComponent(navigationProps.renderBackButton, emitter) : this.wrapHeaderComponent(navigationProps.renderLeftComponent, emitter); + const renderTitleComponent = navigationProps.renderTitleComponent ? this.wrapHeaderComponent(navigationProps.renderTitleComponent, emitter) : this.renderTitle; + const renderRightComponent = this.wrapHeaderComponent(navigationProps.renderRightComponent, emitter); navBar = ( { const SceneComponent = route.component; + const emitterSubscriber = this.subscribeToHeaderEvent(route.key); + const emitterUnsubscriber = this.unsubscribeFromHeaderEvent(route.key); + return ( ); diff --git a/app/reducers/navigation/index.js b/app/reducers/navigation/index.js index 9a281a44c..df2819e25 100644 --- a/app/reducers/navigation/index.js +++ b/app/reducers/navigation/index.js @@ -47,13 +47,18 @@ export default function(state = initialState, action) { } if (state.isModal) { + const nextModalState = state.modal.routes.length > 1 ? + NavigationExperimental.StateUtils.pop(state.modal) : + { + index: 0, + routes: [] + }; + + const isModal = nextModalState.routes.length > 0; return { ...state, - modal: { - index: 0, - routes: [] - }, - isModal: false + modal: nextModalState, + isModal }; }