diff --git a/native/navigation/tab-navigator.react.js b/native/navigation/tab-navigator.react.js index ed5ccafd2..109630a8a 100644 --- a/native/navigation/tab-navigator.react.js +++ b/native/navigation/tab-navigator.react.js @@ -1,165 +1,231 @@ // @flow +import { BottomTabView } from '@react-navigation/bottom-tabs'; +import { + createNavigatorFactory, + useNavigationBuilder, +} from '@react-navigation/native'; import type { + BottomTabNavigationEventMap, + BottomTabOptions, + CreateNavigator, + TabNavigationState, + ParamListBase, BottomTabNavigationHelpers, BottomTabNavigationProp, -} from '@react-navigation/bottom-tabs'; -import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; + ExtraBottomTabNavigatorProps, + BottomTabNavigatorProps, +} from '@react-navigation/native'; import * as React from 'react'; import { unreadCount } from 'lib/selectors/thread-selectors.js'; import CommunityDrawerButton from './community-drawer-button.react.js'; import type { CommunityDrawerNavigationProp } from './community-drawer-navigator.react.js'; import { CalendarRouteName, ChatRouteName, ProfileRouteName, AppsRouteName, type ScreenParamList, type TabParamList, type NavigationRoute, } from './route-names.js'; import { tabBar } from './tab-bar.react.js'; +import TabRouter from './tab-router.js'; import AppsDirectory from '../apps/apps-directory.react.js'; import Calendar from '../calendar/calendar.react.js'; import Chat from '../chat/chat.react.js'; import SWMansionIcon from '../components/swmansion-icon.react.js'; import Profile from '../profile/profile.react.js'; import { useSelector } from '../redux/redux-utils.js'; import { useColors } from '../themes/colors.js'; const calendarTabOptions = { tabBarLabel: 'Calendar', // eslint-disable-next-line react/display-name tabBarIcon: ({ color }) => ( ), }; const getChatTabOptions = (badge: number) => ({ tabBarLabel: 'Inbox', // eslint-disable-next-line react/display-name tabBarIcon: ({ color }) => ( ), tabBarBadge: badge ? badge : undefined, }); const profileTabOptions = { tabBarLabel: 'Profile', // eslint-disable-next-line react/display-name tabBarIcon: ({ color }) => ( ), }; const appsTabOptions = { tabBarLabel: 'Apps', // eslint-disable-next-line react/display-name tabBarIcon: ({ color }) => ( ), }; +export type CustomBottomTabNavigationHelpers< + ParamList: ParamListBase = ParamListBase, +> = { + ...$Exact>, + ... +}; + export type TabNavigationProp< RouteName: $Keys = $Keys, > = BottomTabNavigationProp; -const Tab = createBottomTabNavigator< +type TabNavigatorProps = BottomTabNavigatorProps< + CustomBottomTabNavigationHelpers<>, +>; + +const TabNavigator = React.memo(function TabNavigator({ + id, + initialRouteName, + backBehavior, + children, + screenListeners, + screenOptions, + defaultScreenOptions, + ...rest +}: TabNavigatorProps) { + const { state, descriptors, navigation } = useNavigationBuilder(TabRouter, { + id, + initialRouteName, + backBehavior, + children, + screenListeners, + screenOptions, + defaultScreenOptions, + }); + + return ( + + ); +}); + +const createTabNavigator: CreateNavigator< + TabNavigationState, + BottomTabOptions, + BottomTabNavigationEventMap, + ExtraBottomTabNavigatorProps, +> = createNavigatorFactory< + TabNavigationState, + BottomTabOptions, + BottomTabNavigationEventMap, + BottomTabNavigationHelpers<>, + ExtraBottomTabNavigatorProps, +>(TabNavigator); + +const Tab = createTabNavigator< ScreenParamList, TabParamList, BottomTabNavigationHelpers, >(); type Props = { +navigation: CommunityDrawerNavigationProp<'TabNavigator'>, +route: NavigationRoute<'TabNavigator'>, }; -function TabNavigator(props: Props): React.Node { +function TabComponent(props: Props): React.Node { const colors = useColors(); const chatBadge = useSelector(unreadCount); const isCalendarEnabled = useSelector(state => state.enabledApps.calendar); const headerLeft = React.useCallback( () => , [props.navigation], ); const headerCommonOptions = React.useMemo( () => ({ headerShown: true, headerLeft, headerStyle: { backgroundColor: colors.tabBarBackground, }, headerShadowVisible: false, }), [colors.tabBarBackground, headerLeft], ); const calendarOptions = React.useMemo( () => ({ ...calendarTabOptions, ...headerCommonOptions }), [headerCommonOptions], ); let calendarTab; if (isCalendarEnabled) { calendarTab = ( ); } const appsOptions = React.useMemo( () => ({ ...appsTabOptions, ...headerCommonOptions }), [headerCommonOptions], ); const tabBarScreenOptions = React.useMemo( () => ({ headerShown: false, tabBarHideOnKeyboard: false, tabBarActiveTintColor: colors.tabBarActiveTintColor, tabBarStyle: { backgroundColor: colors.tabBarBackground, borderTopWidth: 1, }, lazy: false, }), [colors.tabBarActiveTintColor, colors.tabBarBackground], ); return ( {calendarTab} ); } const styles = { icon: { fontSize: 28, }, }; -export default TabNavigator; +export default TabComponent; diff --git a/native/navigation/tab-router.js b/native/navigation/tab-router.js new file mode 100644 index 000000000..bbcae1093 --- /dev/null +++ b/native/navigation/tab-router.js @@ -0,0 +1,32 @@ +// @flow + +import type { + Router, + RouterConfigOptions, + TabRouterOptions, + TabNavigationState, +} from '@react-navigation/native'; +import { TabRouter } from '@react-navigation/native'; + +type TabRouterNavigationAction = empty; + +export type TabRouterExtraNavigationHelpers = {}; + +function CustomTabRouter( + routerOptions: TabRouterOptions, +): Router { + const { getStateForAction: baseGetStateForAction, ...rest } = + TabRouter(routerOptions); + return { + ...rest, + getStateForAction: ( + lastState: TabNavigationState, + action: TabRouterNavigationAction, + options: RouterConfigOptions, + ) => { + return baseGetStateForAction(lastState, action, options); + }, + }; +} + +export default CustomTabRouter;