diff options
Diffstat (limited to 'src/view/shell/bottom-bar/BottomBar.tsx')
-rw-r--r-- | src/view/shell/bottom-bar/BottomBar.tsx | 186 |
1 files changed, 104 insertions, 82 deletions
diff --git a/src/view/shell/bottom-bar/BottomBar.tsx b/src/view/shell/bottom-bar/BottomBar.tsx index d360ceead..746b4d123 100644 --- a/src/view/shell/bottom-bar/BottomBar.tsx +++ b/src/view/shell/bottom-bar/BottomBar.tsx @@ -1,12 +1,11 @@ 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 {observer} from 'mobx-react-lite' import {Text} from 'view/com/util/text/Text' -import {useStores} from 'state/index' import {useAnalytics} from 'lib/analytics/analytics' import {clamp} from 'lib/numbers' import { @@ -24,21 +23,33 @@ 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' +import {truncateAndInvalidate} from '#/state/queries/util' type TabOptions = 'Home' | 'Search' | 'Notifications' | 'MyProfile' | 'Feeds' -export const BottomBar = observer(function BottomBarImpl({ - navigation, -}: BottomTabBarProps) { - const store = useStores() +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 {minimalShellMode, footerMinimalShellTransform} = useMinimalShellMode() - const {notifications} = store.me + const numUnreadNotifications = useUnreadNotifications() + const {footerMinimalShellTransform} = useMinimalShellMode() + const {data: profile} = useProfileQuery({did: currentAccount?.did}) const onPressTab = React.useCallback( (tab: TabOptions) => { @@ -46,14 +57,18 @@ export const BottomBar = observer(function BottomBarImpl({ const state = navigation.getState() const tabState = getTabState(state, tab) if (tabState === TabState.InsideAtRoot) { - store.emitScreenSoftReset() + emitSoftReset() } else if (tabState === TabState.Inside) { navigation.dispatch(StackActions.popToTop()) } else { + if (tab === 'Notifications') { + // fetch new notifs on view + truncateAndInvalidate(queryClient, NOTIFS_RQKEY()) + } navigation.navigate(`${tab}Tab`) } }, - [store, track, navigation], + [track, navigation, queryClient], ) const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab]) const onPressSearch = React.useCallback( @@ -72,8 +87,8 @@ export const BottomBar = observer(function BottomBarImpl({ onPressTab('MyProfile') }, [onPressTab]) const onLongPressProfile = React.useCallback(() => { - store.shell.openModal({name: 'switch-account'}) - }, [store]) + openModal({name: 'switch-account'}) + }, [openModal]) return ( <Animated.View @@ -83,8 +98,10 @@ export const BottomBar = observer(function BottomBarImpl({ pal.border, {paddingBottom: clamp(safeAreaInsets.bottom, 15, 30)}, footerMinimalShellTransform, - minimalShellMode && styles.disabled, - ]}> + ]} + onLayout={e => { + footerHeight.value = e.nativeEvent.layout.height + }}> <Btn testID="bottomBarHomeBtn" icon={ @@ -104,7 +121,7 @@ export const BottomBar = observer(function BottomBarImpl({ } onPress={onPressHome} accessibilityRole="tab" - accessibilityLabel="Home" + accessibilityLabel={_(msg`Home`)} accessibilityHint="" /> <Btn @@ -126,7 +143,7 @@ export const BottomBar = observer(function BottomBarImpl({ } onPress={onPressSearch} accessibilityRole="search" - accessibilityLabel="Search" + accessibilityLabel={_(msg`Search`)} accessibilityHint="" /> <Btn @@ -148,78 +165,83 @@ export const BottomBar = observer(function BottomBarImpl({ } onPress={onPressFeeds} accessibilityRole="tab" - accessibilityLabel="Feeds" + accessibilityLabel={_(msg`Feeds`)} accessibilityHint="" /> - <Btn - testID="bottomBarNotificationsBtn" - icon={ - isAtNotifications ? ( - <BellIconSolid - size={24} - strokeWidth={1.9} - style={[styles.ctrlIcon, pal.text, styles.bellIcon]} - /> - ) : ( - <BellIcon - size={24} - strokeWidth={1.9} - style={[styles.ctrlIcon, pal.text, styles.bellIcon]} - /> - ) - } - onPress={onPressNotifications} - notificationCount={notifications.unreadCountLabel} - accessible={true} - accessibilityRole="tab" - accessibilityLabel="Notifications" - accessibilityHint={ - notifications.unreadCountLabel === '' - ? '' - : `${notifications.unreadCountLabel} unread` - } - /> - <Btn - testID="bottomBarProfileBtn" - icon={ - <View style={styles.ctrlIconSizingWrapper}> - {isAtMyProfile ? ( - <View - style={[ - styles.ctrlIcon, - pal.text, - styles.profileIcon, - styles.onProfile, - {borderColor: pal.text.color}, - ]}> - <UserAvatar - avatar={store.me.avatar} - size={27} - // See https://github.com/bluesky-social/social-app/pull/1801: - usePlainRNImage={true} + + {hasSession && ( + <> + <Btn + testID="bottomBarNotificationsBtn" + icon={ + isAtNotifications ? ( + <BellIconSolid + size={24} + strokeWidth={1.9} + style={[styles.ctrlIcon, pal.text, styles.bellIcon]} /> - </View> - ) : ( - <View style={[styles.ctrlIcon, pal.text, styles.profileIcon]}> - <UserAvatar - avatar={store.me.avatar} - size={28} - // See https://github.com/bluesky-social/social-app/pull/1801: - usePlainRNImage={true} + ) : ( + <BellIcon + size={24} + strokeWidth={1.9} + style={[styles.ctrlIcon, pal.text, styles.bellIcon]} /> + ) + } + onPress={onPressNotifications} + notificationCount={numUnreadNotifications} + accessible={true} + accessibilityRole="tab" + accessibilityLabel={_(msg`Notifications`)} + accessibilityHint={ + numUnreadNotifications === '' + ? '' + : `${numUnreadNotifications} unread` + } + /> + <Btn + testID="bottomBarProfileBtn" + icon={ + <View style={styles.ctrlIconSizingWrapper}> + {isAtMyProfile ? ( + <View + style={[ + styles.ctrlIcon, + pal.text, + styles.profileIcon, + styles.onProfile, + {borderColor: pal.text.color}, + ]}> + <UserAvatar + avatar={profile?.avatar} + size={27} + // See https://github.com/bluesky-social/social-app/pull/1801: + usePlainRNImage={true} + /> + </View> + ) : ( + <View style={[styles.ctrlIcon, pal.text, styles.profileIcon]}> + <UserAvatar + avatar={profile?.avatar} + size={28} + // See https://github.com/bluesky-social/social-app/pull/1801: + usePlainRNImage={true} + /> + </View> + )} </View> - )} - </View> - } - onPress={onPressProfile} - onLongPress={onLongPressProfile} - accessibilityRole="tab" - accessibilityLabel="Profile" - accessibilityHint="" - /> + } + onPress={onPressProfile} + onLongPress={onLongPressProfile} + accessibilityRole="tab" + accessibilityLabel={_(msg`Profile`)} + accessibilityHint="" + /> + </> + )} </Animated.View> ) -}) +} interface BtnProps extends Pick< |