Skip to content

Fix multiple back buttons are required to navigate back. #2135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
17 changes: 15 additions & 2 deletions src/main/MainScreenWithTabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,35 @@
import React, { PureComponent } from 'react';
import { View } from 'react-native';

import type { Actions } from '../types';
import connectWithActions from '../connectWithActions';
import { ZulipStatusBar } from '../common';
import { getCanGoBack } from '../selectors';
import MainTabs from './MainTabs';

export default class MainScreenWithTabs extends PureComponent<{}> {
type Props = {
actions: Actions,
canGoBack: boolean,
};

class MainScreenWithTabs extends PureComponent<Props> {
static contextTypes = {
styles: () => null,
};

render() {
const { styles } = this.context;
const { canGoBack, actions } = this.props;

return (
<View style={[styles.flexed, styles.backgroundColor]}>
<ZulipStatusBar />
<ZulipStatusBar canGoBack={canGoBack} actions={actions} />
<MainTabs />
</View>
);
}
}

export default connectWithActions(state => ({
canGoBack: getCanGoBack(state),
}))(MainScreenWithTabs);
45 changes: 41 additions & 4 deletions src/main/MainTabs.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/* @flow */
import React from 'react';
import React, { PureComponent } from 'react';
import { BackHandler } from 'react-native';
import { TabNavigator, TabBarBottom } from 'react-navigation';

import type { TabNavigationOptionsPropsType } from '../types';
import type { Actions, NavigationScreenPropsType, TabNavigationOptionsPropsType } from '../types';
import connectWithActions from '../connectWithActions';
import { getCanGoBack } from '../selectors';
import tabsOptions from '../styles/tabs';
import HomeTab from './HomeTab';
import StreamTabs from './StreamTabs';
Expand All @@ -11,7 +14,37 @@ import SettingsCard from '../settings/SettingsCard';
import { IconHome, IconStream, IconSettings } from '../common/Icons';
import IconUnreadConversations from '../nav/IconUnreadConversations';

export default TabNavigator(
type Props = {
actions: Actions,
canGoBack: boolean,
};

class MainTabs extends PureComponent<Props> {
props: Props;

componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonPress);
}

componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButtonPress);
}

handleBackButtonPress = () => {
const { canGoBack, actions } = this.props;
if (canGoBack) {
actions.navigateBack();
return canGoBack;
}
return canGoBack;
};

render() {
return <Tabs />;
}
}

const Tabs = TabNavigator(
{
home: {
screen: HomeTab,
Expand All @@ -23,7 +56,7 @@ export default TabNavigator(
},
},
streams: {
screen: StreamTabs,
screen: (props: NavigationScreenPropsType) => <StreamTabs {...props} />,
navigationOptions: {
tabBarLabel: 'Streams',
tabBarIcon: (props: TabNavigationOptionsPropsType) => (
Expand Down Expand Up @@ -58,3 +91,7 @@ export default TabNavigator(
tabWidth: 0,
}),
);

export default connectWithActions(state => ({
canGoBack: getCanGoBack(state),
}))(MainTabs);
47 changes: 43 additions & 4 deletions src/main/StreamTabs.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/* @flow */
import React from 'react';
import { StyleSheet, Text } from 'react-native';
import React, { PureComponent } from 'react';
import { BackHandler, StyleSheet, Text } from 'react-native';
import { TabNavigator, TabBarTop } from 'react-navigation';
import { FormattedMessage } from 'react-intl';

import type { TabNavigationOptionsPropsType } from '../types';
import type { Actions, TabNavigationOptionsPropsType } from '../types';
import connectWithActions from '../connectWithActions';
import { getCanGoBack } from '../selectors';
import tabsOptions from '../styles/tabs';
import SubscriptionsContainer from '../streams/SubscriptionsContainer';
import StreamListContainer from '../subscriptions/StreamListContainer';
Expand All @@ -16,7 +18,40 @@ const styles = StyleSheet.create({
},
});

export default TabNavigator(
type Props = {
actions: Actions,
canGoBack: boolean,
navigation: Object,
};

class StreamTabs extends PureComponent<Props> {
props: Props;

componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonPress);
}

componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButtonPress);
}

handleBackButtonPress = () => {
const { canGoBack, actions, navigation } = this.props;
if (canGoBack) {
actions.navigateBack();
return canGoBack;
} else if (!navigation.isFocused()) {
navigation.navigate('home');
return false;
}
return false;
};

render() {
return <Tabs />;
}
}
const Tabs = TabNavigator(
{
subscribed: {
screen: SubscriptionsContainer,
Expand Down Expand Up @@ -47,3 +82,7 @@ export default TabNavigator(
tabWidth: 100,
}),
);

export default connectWithActions(state => ({
canGoBack: getCanGoBack(state),
}))(StreamTabs);
7 changes: 4 additions & 3 deletions src/nav/AppWithNavigationState.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import AppNavigator from './AppNavigator';
import type { Actions } from '../types';

type Props = {
canGoBack: boolean,
actions: Actions,
canGoBack: boolean,
};

class AppWithNavigation extends PureComponent<Props> {
Expand All @@ -27,8 +27,9 @@ class AppWithNavigation extends PureComponent<Props> {
const { canGoBack, actions } = this.props;
if (canGoBack) {
actions.navigateBack();
return true;
}
return canGoBack;
return false;
};

render() {
Expand All @@ -48,6 +49,6 @@ class AppWithNavigation extends PureComponent<Props> {
}

export default connectWithActions(state => ({
nav: getNav(state),
canGoBack: getCanGoBack(state),
nav: getNav(state),
}))(AppWithNavigation);
10 changes: 5 additions & 5 deletions src/nav/MainNavBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import NavButton from './NavButton';
import TitleNavButtons from '../title-buttons/TitleNavButtons';
import {
getSession,
getCanGoBack,
getShowBackArrow,
getUnreadPmsTotal,
getUnreadHuddlesTotal,
getUnreadMentionsTotal,
Expand All @@ -21,8 +21,8 @@ import {
type Props = {
actions: Actions,
backgroundColor: string,
canGoBack: boolean,
narrow: Narrow,
showBackArrow: boolean,
textColor: string,
};

Expand All @@ -35,11 +35,11 @@ class MainNavBar extends PureComponent<Props> {

render() {
const { styles } = this.context;
const { actions, backgroundColor, canGoBack, narrow, textColor } = this.props;
const { actions, backgroundColor, narrow, showBackArrow, textColor } = this.props;

return (
<View style={[styles.navBar, { backgroundColor }]}>
{canGoBack && (
{showBackArrow && (
<NavButton name="arrow-left" color={textColor} onPress={actions.navigateBack} />
)}
<ViewPlaceholder width={8} />
Expand All @@ -52,7 +52,7 @@ class MainNavBar extends PureComponent<Props> {

export default connectWithActions((state, props) => ({
backgroundColor: getTitleBackgroundColor(props.narrow)(state),
canGoBack: getCanGoBack(state),
showBackArrow: getShowBackArrow(state),
textColor: getTitleTextColor(props.narrow)(state),
unreadHuddlesTotal: getUnreadHuddlesTotal(state),
unreadMentionsTotal: getUnreadMentionsTotal(state),
Expand Down
14 changes: 7 additions & 7 deletions src/nav/ModalNavBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ import type { Actions, LocalizableText, StyleObj } from '../types';
import connectWithActions from '../connectWithActions';
import { NAVBAR_SIZE } from '../styles';
import { Label, ViewPlaceholder } from '../common';
import { getCanGoBack } from '../selectors';
import { getShowBackArrow } from '../selectors';
import NavButton from './NavButton';

type Props = {
actions: Actions,
canGoBack: boolean,
showBackArrow: boolean,
style: StyleObj,
title?: LocalizableText,
titleColor?: string,
itemsColor: string,
rightItem?: Object,
style: StyleObj,
children?: ChildrenArray<*>,
childrenStyle?: StyleObj,
};
Expand All @@ -33,7 +33,7 @@ class ModalNavBar extends PureComponent<Props> {
const { styles } = this.context;
const {
actions,
canGoBack,
showBackArrow,
title,
titleColor,
itemsColor,
Expand All @@ -43,7 +43,7 @@ class ModalNavBar extends PureComponent<Props> {
} = this.props;
const textStyle = [
styles.navTitle,
canGoBack && { marginRight: NAVBAR_SIZE },
showBackArrow && { marginRight: NAVBAR_SIZE },
rightItem ? { marginLeft: NAVBAR_SIZE } : {},
titleColor ? { color: titleColor } : {},
];
Expand All @@ -56,7 +56,7 @@ class ModalNavBar extends PureComponent<Props> {

return (
<View style={[styles.navBar, style]}>
{canGoBack && (
{showBackArrow && (
<NavButton name="arrow-left" color={itemsColor} onPress={actions.navigateBack} />
)}
<ViewPlaceholder width={8} />
Expand All @@ -68,5 +68,5 @@ class ModalNavBar extends PureComponent<Props> {
}

export default connectWithActions(state => ({
canGoBack: getCanGoBack(state),
getShowBackArrow: getShowBackArrow(state),
}))(ModalNavBar);
13 changes: 11 additions & 2 deletions src/nav/navSelectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,17 @@ import { getAuth } from '../account/accountSelectors';
import AppNavigator from './AppNavigator';
import { getNarrowFromNotificationData } from '../utils/notificationsCommon';

export const getCanGoBack = (state: GlobalState) =>
state.nav.index > 0 && state.nav.routes[state.nav.index].routeName !== 'lightbox';
export const getCanGoBack = (state: GlobalState) => state.nav.index > 0;

export const isCurrentRouteIsLightBox = (state: GlobalState) =>
state.nav.routes[state.nav.index].routeName === 'lightbox';

export const getShowBackArrow = (state: GlobalState) =>
createSelector(
getCanGoBack,
isCurrentRouteIsLightBox,
(canGoBack, currentRouteIsLightBox) => canGoBack && !currentRouteIsLightBox,
);

export const getSameRoutesCount = createSelector(getNav, nav => {
let i = nav.routes.length - 1;
Expand Down
8 changes: 8 additions & 0 deletions src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -540,3 +540,11 @@ export type TabNavigationOptionsPropsType = {
isFocussed: boolean,
tintColor: string,
};

export type NavigationScreenPropsType = {
screenProps: Object,
navigation: {
isFocused: () => boolean,
state: Object,
},
};