import React, {ComponentProps} from 'react' import {GestureResponderEvent, TouchableOpacity, View} from 'react-native' import Animated from 'react-native-reanimated' import {useQueryClient} from '@tanstack/react-query' import {StackActions} from '@react-navigation/native' import {BottomTabBarProps} from '@react-navigation/bottom-tabs' import {useSafeAreaInsets} from 'react-native-safe-area-context' import {Text} from 'view/com/util/text/Text' import {useAnalytics} from 'lib/analytics/analytics' import {clamp} from 'lib/numbers' import { HomeIcon, HomeIconSolid, MagnifyingGlassIcon2, MagnifyingGlassIcon2Solid, HashtagIcon, BellIcon, BellIconSolid, } from 'lib/icons' import {usePalette} from 'lib/hooks/usePalette' import {getTabState, TabState} from 'lib/routes/helpers' import {styles} from './BottomBarStyles' import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode' import {useNavigationTabState} from 'lib/hooks/useNavigationTabState' import {UserAvatar} from 'view/com/util/UserAvatar' import {useLingui} from '@lingui/react' import {msg} from '@lingui/macro' import {useModalControls} from '#/state/modals' import {useShellLayout} from '#/state/shell/shell-layout' import {useUnreadNotifications} from '#/state/queries/notifications/unread' import {emitSoftReset} from '#/state/events' import {useSession} from '#/state/session' import {useProfileQuery} from '#/state/queries/profile' import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed' type TabOptions = 'Home' | 'Search' | 'Notifications' | 'MyProfile' | 'Feeds' export function BottomBar({navigation}: BottomTabBarProps) { const {openModal} = useModalControls() const {hasSession, currentAccount} = useSession() const pal = usePalette('default') const {_} = useLingui() const queryClient = useQueryClient() const safeAreaInsets = useSafeAreaInsets() const {track} = useAnalytics() const {footerHeight} = useShellLayout() const {isAtHome, isAtSearch, isAtFeeds, isAtNotifications, isAtMyProfile} = useNavigationTabState() const numUnreadNotifications = useUnreadNotifications() const {footerMinimalShellTransform} = useMinimalShellMode() const {data: profile} = useProfileQuery({did: currentAccount?.did}) const onPressTab = React.useCallback( (tab: TabOptions) => { track(`MobileShell:${tab}ButtonPressed`) const state = navigation.getState() const tabState = getTabState(state, tab) if (tabState === TabState.InsideAtRoot) { emitSoftReset() } else if (tabState === TabState.Inside) { navigation.dispatch(StackActions.popToTop()) } else { if (tab === 'Notifications') { // fetch new notifs on view queryClient.resetQueries({ queryKey: NOTIFS_RQKEY(), }) } navigation.navigate(`${tab}Tab`) } }, [track, navigation, queryClient], ) const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab]) const onPressSearch = React.useCallback( () => onPressTab('Search'), [onPressTab], ) const onPressFeeds = React.useCallback( () => onPressTab('Feeds'), [onPressTab], ) const onPressNotifications = React.useCallback( () => onPressTab('Notifications'), [onPressTab], ) const onPressProfile = React.useCallback(() => { onPressTab('MyProfile') }, [onPressTab]) const onLongPressProfile = React.useCallback(() => { openModal({name: 'switch-account'}) }, [openModal]) return ( { footerHeight.value = e.nativeEvent.layout.height }}> ) : ( ) } onPress={onPressHome} accessibilityRole="tab" accessibilityLabel={_(msg`Home`)} accessibilityHint="" /> ) : ( ) } onPress={onPressSearch} accessibilityRole="search" accessibilityLabel={_(msg`Search`)} accessibilityHint="" /> ) : ( ) } onPress={onPressFeeds} accessibilityRole="tab" accessibilityLabel={_(msg`Feeds`)} accessibilityHint="" /> {hasSession && ( <> ) : ( ) } onPress={onPressNotifications} notificationCount={numUnreadNotifications} accessible={true} accessibilityRole="tab" accessibilityLabel={_(msg`Notifications`)} accessibilityHint={ numUnreadNotifications === '' ? '' : `${numUnreadNotifications} unread` } /> {isAtMyProfile ? ( ) : ( )} } onPress={onPressProfile} onLongPress={onLongPressProfile} accessibilityRole="tab" accessibilityLabel={_(msg`Profile`)} accessibilityHint="" /> )} ) } interface BtnProps extends Pick< ComponentProps, | 'accessible' | 'accessibilityRole' | 'accessibilityHint' | 'accessibilityLabel' > { testID?: string icon: JSX.Element notificationCount?: string onPress?: (event: GestureResponderEvent) => void onLongPress?: (event: GestureResponderEvent) => void } function Btn({ testID, icon, notificationCount, onPress, onLongPress, accessible, accessibilityHint, accessibilityLabel, }: BtnProps) { return ( {notificationCount ? ( {notificationCount} ) : undefined} {icon} ) }