From 9d11e787fd10d5ef07d7b1d8e02127c922e189c7 Mon Sep 17 00:00:00 2001 From: Nolan Kaplan Date: Sun, 17 Jul 2022 16:19:12 -0400 Subject: [PATCH] nav: Change the streams tab from a tab navigator to a stack navigator. This removes StreamTabsScreen and sets the streams tab in MainTabsScreen to a stack navigator, with SubscriptionsScreen on top, and a button at the bottom of SubscriptionsScreen to navigate to StreamListScreen. I have tested this in an Android emulator but I have not yet run it on iOS. Fixes: #5424 --- src/main/MainTabsScreen.js | 9 ++- src/main/StreamTabsScreen.js | 69 ------------------- src/nav/AppNavigator.js | 3 + src/nav/globalTypes.js | 2 - ...riptionsCard.js => SubscriptionsScreen.js} | 49 +++++++++++-- ...{StreamListCard.js => StreamListScreen.js} | 10 +-- static/translations/messages_en.json | 3 +- 7 files changed, 59 insertions(+), 86 deletions(-) delete mode 100644 src/main/StreamTabsScreen.js rename src/streams/{SubscriptionsCard.js => SubscriptionsScreen.js} (64%) rename src/subscriptions/{StreamListCard.js => StreamListScreen.js} (92%) diff --git a/src/main/MainTabsScreen.js b/src/main/MainTabsScreen.js index cdfa02c66b8..dd9416f5402 100644 --- a/src/main/MainTabsScreen.js +++ b/src/main/MainTabsScreen.js @@ -6,24 +6,23 @@ import { type BottomTabNavigationProp, } from '@react-navigation/bottom-tabs'; import { SafeAreaView } from 'react-native-safe-area-context'; - import type { RouteProp, RouteParamsOf } from '../react-navigation'; import { getUnreadHuddlesTotal, getUnreadPmsTotal } from '../selectors'; import { useSelector } from '../react-redux'; import type { AppNavigationMethods, AppNavigationProp } from '../nav/AppNavigator'; import { bottomTabNavigatorConfig } from '../styles/tabs'; import HomeScreen from './HomeScreen'; -import StreamTabsScreen from './StreamTabsScreen'; import PmConversationsScreen from '../pm-conversations/PmConversationsScreen'; import { IconInbox, IconStream, IconPeople } from '../common/Icons'; import OwnAvatar from '../common/OwnAvatar'; import OfflineNotice from '../common/OfflineNotice'; import ProfileScreen from '../account-info/ProfileScreen'; import styles, { BRAND_COLOR, ThemeContext } from '../styles'; +import SubscriptionsScreen from '../streams/SubscriptionsScreen'; export type MainTabsNavigatorParamList = {| +home: RouteParamsOf, - +'stream-tabs': RouteParamsOf, + +subscribed: RouteParamsOf, +'pm-conversations': RouteParamsOf, +profile: RouteParamsOf, |}; @@ -66,8 +65,8 @@ export default function MainTabsScreen(props: Props): Node { }} /> , diff --git a/src/main/StreamTabsScreen.js b/src/main/StreamTabsScreen.js deleted file mode 100644 index 5e72b58ca22..00000000000 --- a/src/main/StreamTabsScreen.js +++ /dev/null @@ -1,69 +0,0 @@ -/* @flow strict-local */ -import React from 'react'; -import type { Node } from 'react'; -import { - createMaterialTopTabNavigator, - type MaterialTopTabNavigationProp, -} from '@react-navigation/material-top-tabs'; - -import ZulipTextIntl from '../common/ZulipTextIntl'; -import { createStyleSheet } from '../styles'; -import type { RouteProp, RouteParamsOf } from '../react-navigation'; -import type { MainTabsNavigationProp } from './MainTabsScreen'; -import { materialTopTabNavigatorConfig } from '../styles/tabs'; -import SubscriptionsCard from '../streams/SubscriptionsCard'; -import StreamListCard from '../subscriptions/StreamListCard'; -import type { AppNavigationMethods } from '../nav/AppNavigator'; - -export type StreamTabsNavigatorParamList = {| - +subscribed: RouteParamsOf, - +allStreams: RouteParamsOf, -|}; - -export type StreamTabsNavigationProp< - +RouteName: $Keys = $Keys, -> = - // Screens on this navigator will get a `navigation` prop that reflects - // this navigator itself… - MaterialTopTabNavigationProp & - // … plus the methods it gets from its parent navigator. - AppNavigationMethods; - -const Tab = createMaterialTopTabNavigator(); - -const styles = createStyleSheet({ - tab: { - padding: 8, - fontSize: 16, - }, -}); - -type Props = $ReadOnly<{| - navigation: MainTabsNavigationProp<'stream-tabs'>, - route: RouteProp<'stream-tabs', void>, -|}>; - -export default function StreamTabsScreen(props: Props): Node { - return ( - - ( - - ), - }} - /> - ( - - ), - }} - /> - - ); -} diff --git a/src/nav/AppNavigator.js b/src/nav/AppNavigator.js index d2a64e6a661..eccdd617498 100644 --- a/src/nav/AppNavigator.js +++ b/src/nav/AppNavigator.js @@ -52,6 +52,7 @@ import SettingsScreen from '../settings/SettingsScreen'; import UserStatusScreen from '../user-statuses/UserStatusScreen'; import SharingScreen from '../sharing/SharingScreen'; import SelectableOptionsScreen from '../common/SelectableOptionsScreen'; +import StreamListScreen from '../subscriptions/StreamListScreen'; import { useHaveServerDataGate } from '../withHaveServerDataGate'; export type AppNavigatorParamList = {| @@ -63,6 +64,7 @@ export type AppNavigatorParamList = {| +'dev-auth': RouteParamsOf, +'emoji-picker': RouteParamsOf, +'main-tabs': RouteParamsOf, + +'all-streams': RouteParamsOf, +'message-reactions': RouteParamsOf, +'password-auth': RouteParamsOf, +'realm-input': RouteParamsOf, @@ -165,6 +167,7 @@ export default function AppNavigator(props: Props): Node { + , + navigation: AppNavigationProp<'subscribed'>, route: RouteProp<'subscribed', void>, |}>; -export default function SubscriptionsCard(props: Props): Node { +type FooterProps = $ReadOnly<{||}>; + +function AllStreamsButton(props: FooterProps): Node { + const navigation = useNavigation(); + const themeContext = useContext(ThemeContext); + const handlePressAllScreens = useCallback(() => { + navigation.push('all-streams'); + }, [navigation]); + + return ( + + + + + + + ); +} + +export default function SubscriptionsScreen(props: Props): Node { const dispatch = useDispatch(); const subscriptions = useSelector(getSubscriptions); const unreadByStream = useSelector(getUnreadByStream); @@ -57,6 +94,7 @@ export default function SubscriptionsCard(props: Props): Node { return ( + {subscriptions.length === 0 ? ( @@ -84,6 +122,7 @@ export default function SubscriptionsCard(props: Props): Node { /> )} SectionSeparatorComponent={SectionSeparatorBetween} + ListFooterComponent={AllStreamsButton} /> )} diff --git a/src/subscriptions/StreamListCard.js b/src/subscriptions/StreamListScreen.js similarity index 92% rename from src/subscriptions/StreamListCard.js rename to src/subscriptions/StreamListScreen.js index 2c654809baf..1194ddf1db7 100644 --- a/src/subscriptions/StreamListCard.js +++ b/src/subscriptions/StreamListScreen.js @@ -5,7 +5,7 @@ import type { Node } from 'react'; import { View, FlatList } from 'react-native'; import type { RouteProp } from '../react-navigation'; -import type { StreamTabsNavigationProp } from '../main/StreamTabsScreen'; +import type { AppNavigationProp } from '../nav/AppNavigator'; import { createStyleSheet } from '../styles'; import { useDispatch, useSelector } from '../react-redux'; import ZulipButton from '../common/ZulipButton'; @@ -19,6 +19,7 @@ import { doNarrow } from '../actions'; import { caseInsensitiveCompareFunc } from '../utils/misc'; import StreamItem from '../streams/StreamItem'; import { getSubscriptionsById } from './subscriptionSelectors'; +import ModalNavBar from '../nav/ModalNavBar'; const styles = createStyleSheet({ wrapper: { @@ -34,11 +35,11 @@ const styles = createStyleSheet({ }); type Props = $ReadOnly<{| - navigation: StreamTabsNavigationProp<'allStreams'>, - route: RouteProp<'allStreams', void>, + navigation: AppNavigationProp<'all-streams'>, + route: RouteProp<'all-streams', void>, |}>; -export default function StreamListCard(props: Props): Node { +export default function StreamListScreen(props: Props): Node { const { navigation } = props; const dispatch = useDispatch(); const auth = useSelector(getAuth); @@ -71,6 +72,7 @@ export default function StreamListCard(props: Props): Node { return ( + {canCreateStreams && (