Merge remote-tracking branch 'origin/nav-client-events' into claude/fix-leftnav-type-placement-SyWtu
This commit is contained in:
@@ -60,6 +60,20 @@ export type Events = {
|
|||||||
'router:navigate': {
|
'router:navigate': {
|
||||||
from?: string
|
from?: string
|
||||||
}
|
}
|
||||||
|
'nav:click': {
|
||||||
|
item:
|
||||||
|
| 'home'
|
||||||
|
| 'search'
|
||||||
|
| 'chat'
|
||||||
|
| 'notifications'
|
||||||
|
| 'profile'
|
||||||
|
| 'feeds'
|
||||||
|
| 'lists'
|
||||||
|
| 'saved'
|
||||||
|
| 'settings'
|
||||||
|
| 'menu'
|
||||||
|
surface: 'bottomBar' | 'drawer' | 'drawerHeader' | 'topBar' | 'leftNav'
|
||||||
|
}
|
||||||
'deepLink:referrerReceived': {
|
'deepLink:referrerReceived': {
|
||||||
to: string
|
to: string
|
||||||
referrer: string
|
referrer: string
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import {
|
|||||||
} from '#/components/Layout/const'
|
} from '#/components/Layout/const'
|
||||||
import {ScrollbarOffsetContext} from '#/components/Layout/context'
|
import {ScrollbarOffsetContext} from '#/components/Layout/context'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
import {IS_IOS} from '#/env'
|
import {IS_IOS} from '#/env'
|
||||||
|
|
||||||
export function Outer({
|
export function Outer({
|
||||||
@@ -154,13 +155,15 @@ export function BackButton({onPress, style, ...props}: Partial<ButtonProps>) {
|
|||||||
|
|
||||||
export function MenuButton() {
|
export function MenuButton() {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const ax = useAnalytics()
|
||||||
const setDrawerOpen = useSetDrawerOpen()
|
const setDrawerOpen = useSetDrawerOpen()
|
||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
|
|
||||||
const onPress = useCallback(() => {
|
const onPress = useCallback(() => {
|
||||||
|
ax.metric('nav:click', {item: 'menu', surface: 'topBar'})
|
||||||
Keyboard.dismiss()
|
Keyboard.dismiss()
|
||||||
setDrawerOpen(true)
|
setDrawerOpen(true)
|
||||||
}, [setDrawerOpen])
|
}, [setDrawerOpen, ax])
|
||||||
|
|
||||||
return gtMobile ? null : (
|
return gtMobile ? null : (
|
||||||
<Slot>
|
<Slot>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {ButtonIcon} from '#/components/Button'
|
|||||||
import {Hashtag_Stroke2_Corner0_Rounded as FeedsIcon} from '#/components/icons/Hashtag'
|
import {Hashtag_Stroke2_Corner0_Rounded as FeedsIcon} from '#/components/icons/Hashtag'
|
||||||
import * as Layout from '#/components/Layout'
|
import * as Layout from '#/components/Layout'
|
||||||
import {Link} from '#/components/Link'
|
import {Link} from '#/components/Link'
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
|
|
||||||
export function HomeHeaderLayout(props: {
|
export function HomeHeaderLayout(props: {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
@@ -38,6 +39,7 @@ function HomeHeaderLayoutDesktopAndTablet({
|
|||||||
const {headerHeight} = useShellLayout()
|
const {headerHeight} = useShellLayout()
|
||||||
const {hasSession} = useSession()
|
const {hasSession} = useSession()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const ax = useAnalytics()
|
||||||
const kawaii = useKawaiiMode()
|
const kawaii = useKawaiiMode()
|
||||||
const gutters = useGutters([0, 'base'])
|
const gutters = useGutters([0, 'base'])
|
||||||
|
|
||||||
@@ -59,6 +61,9 @@ function HomeHeaderLayoutDesktopAndTablet({
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
shape="square"
|
shape="square"
|
||||||
|
onPress={() => {
|
||||||
|
ax.metric('nav:click', {item: 'feeds', surface: 'topBar'})
|
||||||
|
}}
|
||||||
style={[a.justify_center]}>
|
style={[a.justify_center]}>
|
||||||
<ButtonIcon icon={FeedsIcon} size="lg" />
|
<ButtonIcon icon={FeedsIcon} size="lg" />
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {ButtonIcon} from '#/components/Button'
|
|||||||
import {Hashtag_Stroke2_Corner0_Rounded as FeedsIcon} from '#/components/icons/Hashtag'
|
import {Hashtag_Stroke2_Corner0_Rounded as FeedsIcon} from '#/components/icons/Hashtag'
|
||||||
import * as Layout from '#/components/Layout'
|
import * as Layout from '#/components/Layout'
|
||||||
import {Link} from '#/components/Link'
|
import {Link} from '#/components/Link'
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
import {IS_DEV, IS_LIQUID_GLASS} from '#/env'
|
import {IS_DEV, IS_LIQUID_GLASS} from '#/env'
|
||||||
|
|
||||||
export function HomeHeaderLayoutMobile({
|
export function HomeHeaderLayoutMobile({
|
||||||
@@ -29,6 +30,7 @@ export function HomeHeaderLayoutMobile({
|
|||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const ax = useAnalytics()
|
||||||
const {headerHeight} = useShellLayout()
|
const {headerHeight} = useShellLayout()
|
||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
const headerMinimalShellTransform = useHomeHeaderTransform()
|
const headerMinimalShellTransform = useHomeHeaderTransform()
|
||||||
@@ -84,6 +86,9 @@ export function HomeHeaderLayoutMobile({
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
shape="square"
|
shape="square"
|
||||||
|
onPress={() => {
|
||||||
|
ax.metric('nav:click', {item: 'feeds', surface: 'topBar'})
|
||||||
|
}}
|
||||||
style={[
|
style={[
|
||||||
a.justify_center,
|
a.justify_center,
|
||||||
{marginRight: -Layout.BUTTON_VISUAL_ALIGNMENT_OFFSET},
|
{marginRight: -Layout.BUTTON_VISUAL_ALIGNMENT_OFFSET},
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ import {
|
|||||||
import {InlineLinkText} from '#/components/Link'
|
import {InlineLinkText} from '#/components/Link'
|
||||||
import {ProfileBadges} from '#/components/ProfileBadges'
|
import {ProfileBadges} from '#/components/ProfileBadges'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
import {IS_WEB} from '#/env'
|
import {IS_WEB} from '#/env'
|
||||||
import {useActorStatus} from '#/features/liveNow'
|
import {useActorStatus} from '#/features/liveNow'
|
||||||
|
|
||||||
@@ -133,11 +134,30 @@ let DrawerProfileCard = ({
|
|||||||
DrawerProfileCard = memo(DrawerProfileCard)
|
DrawerProfileCard = memo(DrawerProfileCard)
|
||||||
export {DrawerProfileCard}
|
export {DrawerProfileCard}
|
||||||
|
|
||||||
|
type DrawerTabOption =
|
||||||
|
| 'Home'
|
||||||
|
| 'Search'
|
||||||
|
| 'Messages'
|
||||||
|
| 'Notifications'
|
||||||
|
| 'MyProfile'
|
||||||
|
|
||||||
|
const DRAWER_TAB_TO_NAV_ITEM: Record<
|
||||||
|
DrawerTabOption,
|
||||||
|
'home' | 'search' | 'chat' | 'notifications' | 'profile'
|
||||||
|
> = {
|
||||||
|
Home: 'home',
|
||||||
|
Search: 'search',
|
||||||
|
Messages: 'chat',
|
||||||
|
Notifications: 'notifications',
|
||||||
|
MyProfile: 'profile',
|
||||||
|
}
|
||||||
|
|
||||||
let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
const setDrawerOpen = useSetDrawerOpen()
|
const setDrawerOpen = useSetDrawerOpen()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
const ax = useAnalytics()
|
||||||
const {
|
const {
|
||||||
isAtHome,
|
isAtHome,
|
||||||
isAtSearch,
|
isAtSearch,
|
||||||
@@ -153,7 +173,11 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
|||||||
// =
|
// =
|
||||||
|
|
||||||
const onPressTab = useCallback(
|
const onPressTab = useCallback(
|
||||||
(tab: 'Home' | 'Search' | 'Messages' | 'Notifications' | 'MyProfile') => {
|
(tab: DrawerTabOption, surface: 'drawer' | 'drawerHeader' = 'drawer') => {
|
||||||
|
ax.metric('nav:click', {
|
||||||
|
item: DRAWER_TAB_TO_NAV_ITEM[tab],
|
||||||
|
surface,
|
||||||
|
})
|
||||||
const state = navigation.getState()
|
const state = navigation.getState()
|
||||||
setDrawerOpen(false)
|
setDrawerOpen(false)
|
||||||
if (IS_WEB) {
|
if (IS_WEB) {
|
||||||
@@ -190,7 +214,7 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[navigation, setDrawerOpen, currentAccount],
|
[navigation, setDrawerOpen, currentAccount, ax],
|
||||||
)
|
)
|
||||||
|
|
||||||
const onPressHome = useCallback(() => onPressTab('Home'), [onPressTab])
|
const onPressHome = useCallback(() => onPressTab('Home'), [onPressTab])
|
||||||
@@ -211,25 +235,33 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
|||||||
onPressTab('MyProfile')
|
onPressTab('MyProfile')
|
||||||
}, [onPressTab])
|
}, [onPressTab])
|
||||||
|
|
||||||
|
const onPressDrawerHeaderProfile = useCallback(() => {
|
||||||
|
onPressTab('MyProfile', 'drawerHeader')
|
||||||
|
}, [onPressTab])
|
||||||
|
|
||||||
const onPressMyFeeds = useCallback(() => {
|
const onPressMyFeeds = useCallback(() => {
|
||||||
|
ax.metric('nav:click', {item: 'feeds', surface: 'drawer'})
|
||||||
navigation.navigate('Feeds')
|
navigation.navigate('Feeds')
|
||||||
setDrawerOpen(false)
|
setDrawerOpen(false)
|
||||||
}, [navigation, setDrawerOpen])
|
}, [navigation, setDrawerOpen, ax])
|
||||||
|
|
||||||
const onPressLists = useCallback(() => {
|
const onPressLists = useCallback(() => {
|
||||||
|
ax.metric('nav:click', {item: 'lists', surface: 'drawer'})
|
||||||
navigation.navigate('Lists')
|
navigation.navigate('Lists')
|
||||||
setDrawerOpen(false)
|
setDrawerOpen(false)
|
||||||
}, [navigation, setDrawerOpen])
|
}, [navigation, setDrawerOpen, ax])
|
||||||
|
|
||||||
const onPressBookmarks = useCallback(() => {
|
const onPressBookmarks = useCallback(() => {
|
||||||
|
ax.metric('nav:click', {item: 'saved', surface: 'drawer'})
|
||||||
navigation.navigate('Bookmarks')
|
navigation.navigate('Bookmarks')
|
||||||
setDrawerOpen(false)
|
setDrawerOpen(false)
|
||||||
}, [navigation, setDrawerOpen])
|
}, [navigation, setDrawerOpen, ax])
|
||||||
|
|
||||||
const onPressSettings = useCallback(() => {
|
const onPressSettings = useCallback(() => {
|
||||||
|
ax.metric('nav:click', {item: 'settings', surface: 'drawer'})
|
||||||
navigation.navigate('Settings')
|
navigation.navigate('Settings')
|
||||||
setDrawerOpen(false)
|
setDrawerOpen(false)
|
||||||
}, [navigation, setDrawerOpen])
|
}, [navigation, setDrawerOpen, ax])
|
||||||
|
|
||||||
const onPressFeedback = useCallback(() => {
|
const onPressFeedback = useCallback(() => {
|
||||||
Linking.openURL(
|
Linking.openURL(
|
||||||
@@ -265,7 +297,7 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
|||||||
{hasSession && currentAccount ? (
|
{hasSession && currentAccount ? (
|
||||||
<DrawerProfileCard
|
<DrawerProfileCard
|
||||||
account={currentAccount}
|
account={currentAccount}
|
||||||
onPressProfile={onPressProfile}
|
onPressProfile={onPressDrawerHeaderProfile}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<View style={[a.pr_xl]}>
|
<View style={[a.pr_xl]}>
|
||||||
|
|||||||
@@ -50,16 +50,29 @@ import {
|
|||||||
} from '#/components/icons/Message'
|
} from '#/components/icons/Message'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {useAgeAssurance} from '#/ageAssurance'
|
import {useAgeAssurance} from '#/ageAssurance'
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
import {useActorStatus} from '#/features/liveNow'
|
import {useActorStatus} from '#/features/liveNow'
|
||||||
import {useDemoMode} from '#/storage/hooks/demo-mode'
|
import {useDemoMode} from '#/storage/hooks/demo-mode'
|
||||||
import {styles} from './BottomBarStyles'
|
import {styles} from './BottomBarStyles'
|
||||||
|
|
||||||
type TabOptions = 'Home' | 'Search' | 'Messages' | 'Notifications' | 'MyProfile'
|
type TabOptions = 'Home' | 'Search' | 'Messages' | 'Notifications' | 'MyProfile'
|
||||||
|
|
||||||
|
const TAB_TO_NAV_ITEM: Record<
|
||||||
|
TabOptions,
|
||||||
|
'home' | 'search' | 'chat' | 'notifications' | 'profile'
|
||||||
|
> = {
|
||||||
|
Home: 'home',
|
||||||
|
Search: 'search',
|
||||||
|
Messages: 'chat',
|
||||||
|
Notifications: 'notifications',
|
||||||
|
MyProfile: 'profile',
|
||||||
|
}
|
||||||
|
|
||||||
export function BottomBar({navigation}: BottomTabBarProps) {
|
export function BottomBar({navigation}: BottomTabBarProps) {
|
||||||
const {hasSession, currentAccount} = useSession()
|
const {hasSession, currentAccount} = useSession()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const ax = useAnalytics()
|
||||||
const safeAreaInsets = useSafeAreaInsets()
|
const safeAreaInsets = useSafeAreaInsets()
|
||||||
const {footerHeight} = useShellLayout()
|
const {footerHeight} = useShellLayout()
|
||||||
const {isAtHome, isAtSearch, isAtNotifications, isAtMyProfile, isAtMessages} =
|
const {isAtHome, isAtSearch, isAtNotifications, isAtMyProfile, isAtMessages} =
|
||||||
@@ -90,6 +103,10 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
|
|
||||||
const onPressTab = useCallback(
|
const onPressTab = useCallback(
|
||||||
(tab: TabOptions) => {
|
(tab: TabOptions) => {
|
||||||
|
ax.metric('nav:click', {
|
||||||
|
item: TAB_TO_NAV_ITEM[tab],
|
||||||
|
surface: 'bottomBar',
|
||||||
|
})
|
||||||
const state = navigation.getState()
|
const state = navigation.getState()
|
||||||
const tabState = getTabState(state, tab)
|
const tabState = getTabState(state, tab)
|
||||||
if (tabState === TabState.InsideAtRoot) {
|
if (tabState === TabState.InsideAtRoot) {
|
||||||
@@ -117,7 +134,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
dedupe(() => navigation.navigate(`${tab}Tab`))
|
dedupe(() => navigation.navigate(`${tab}Tab`))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[navigation, dedupe],
|
[navigation, dedupe, ax],
|
||||||
)
|
)
|
||||||
const onPressHome = useCallback(() => onPressTab('Home'), [onPressTab])
|
const onPressHome = useCallback(() => onPressTab('Home'), [onPressTab])
|
||||||
const onPressSearch = useCallback(() => onPressTab('Search'), [onPressTab])
|
const onPressSearch = useCallback(() => onPressTab('Search'), [onPressTab])
|
||||||
|
|||||||
@@ -44,8 +44,11 @@ import {
|
|||||||
} from '#/components/icons/Message'
|
} from '#/components/icons/Message'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {useAgeAssurance} from '#/ageAssurance'
|
import {useAgeAssurance} from '#/ageAssurance'
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
import {styles} from './BottomBarStyles'
|
import {styles} from './BottomBarStyles'
|
||||||
|
|
||||||
|
type NavItemValue = 'home' | 'search' | 'chat' | 'notifications' | 'profile'
|
||||||
|
|
||||||
export function BottomBarWeb() {
|
export function BottomBarWeb() {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const {hasSession, currentAccount} = useSession()
|
const {hasSession, currentAccount} = useSession()
|
||||||
@@ -96,7 +99,7 @@ export function BottomBarWeb() {
|
|||||||
onLayout={event => footerHeight.set(event.nativeEvent.layout.height)}>
|
onLayout={event => footerHeight.set(event.nativeEvent.layout.height)}>
|
||||||
{hasSession ? (
|
{hasSession ? (
|
||||||
<>
|
<>
|
||||||
<NavItem routeName="Home" href="/">
|
<NavItem routeName="Home" href="/" navItem="home">
|
||||||
{({isActive}) => {
|
{({isActive}) => {
|
||||||
const Icon = isActive ? HomeFilled : Home
|
const Icon = isActive ? HomeFilled : Home
|
||||||
return (
|
return (
|
||||||
@@ -108,7 +111,7 @@ export function BottomBarWeb() {
|
|||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</NavItem>
|
</NavItem>
|
||||||
<NavItem routeName="Search" href="/search">
|
<NavItem routeName="Search" href="/search" navItem="search">
|
||||||
{({isActive}) => {
|
{({isActive}) => {
|
||||||
const Icon = isActive ? MagnifyingGlassFilled : MagnifyingGlass
|
const Icon = isActive ? MagnifyingGlassFilled : MagnifyingGlass
|
||||||
return (
|
return (
|
||||||
@@ -126,6 +129,7 @@ export function BottomBarWeb() {
|
|||||||
<NavItem
|
<NavItem
|
||||||
routeName="Messages"
|
routeName="Messages"
|
||||||
href="/messages"
|
href="/messages"
|
||||||
|
navItem="chat"
|
||||||
notificationCount={
|
notificationCount={
|
||||||
aa.flags.chatDisabled
|
aa.flags.chatDisabled
|
||||||
? undefined
|
? undefined
|
||||||
@@ -152,6 +156,7 @@ export function BottomBarWeb() {
|
|||||||
<NavItem
|
<NavItem
|
||||||
routeName="Notifications"
|
routeName="Notifications"
|
||||||
href="/notifications"
|
href="/notifications"
|
||||||
|
navItem="notifications"
|
||||||
notificationCount={notificationCountStr}>
|
notificationCount={notificationCountStr}>
|
||||||
{({isActive}) => {
|
{({isActive}) => {
|
||||||
const Icon = isActive ? BellFilled : Bell
|
const Icon = isActive ? BellFilled : Bell
|
||||||
@@ -174,6 +179,7 @@ export function BottomBarWeb() {
|
|||||||
})
|
})
|
||||||
: '/'
|
: '/'
|
||||||
}
|
}
|
||||||
|
navItem="profile"
|
||||||
onLongPress={onLongPressProfile}>
|
onLongPress={onLongPressProfile}>
|
||||||
{({isActive}) => (
|
{({isActive}) => (
|
||||||
<View style={styles.ctrlIconSizingWrapper}>
|
<View style={styles.ctrlIconSizingWrapper}>
|
||||||
@@ -257,12 +263,22 @@ const NavItem: React.FC<{
|
|||||||
children: (props: {isActive: boolean}) => React.ReactNode
|
children: (props: {isActive: boolean}) => React.ReactNode
|
||||||
href: string
|
href: string
|
||||||
routeName: string
|
routeName: string
|
||||||
|
navItem: NavItemValue
|
||||||
hasNew?: boolean
|
hasNew?: boolean
|
||||||
notificationCount?: string
|
notificationCount?: string
|
||||||
onLongPress?: () => void
|
onLongPress?: () => void
|
||||||
}> = ({children, href, routeName, hasNew, notificationCount, onLongPress}) => {
|
}> = ({
|
||||||
|
children,
|
||||||
|
href,
|
||||||
|
routeName,
|
||||||
|
navItem,
|
||||||
|
hasNew,
|
||||||
|
notificationCount,
|
||||||
|
onLongPress,
|
||||||
|
}) => {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const ax = useAnalytics()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const currentRoute = useNavigationState(state => {
|
const currentRoute = useNavigationState(state => {
|
||||||
if (!state) {
|
if (!state) {
|
||||||
@@ -271,6 +287,10 @@ const NavItem: React.FC<{
|
|||||||
return getCurrentRoute(state)
|
return getCurrentRoute(state)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const onBeforePress = useCallback(() => {
|
||||||
|
ax.metric('nav:click', {item: navItem, surface: 'bottomBar'})
|
||||||
|
}, [ax, navItem])
|
||||||
|
|
||||||
// Checks whether we're on someone else's profile
|
// Checks whether we're on someone else's profile
|
||||||
const isOnDifferentProfile =
|
const isOnDifferentProfile =
|
||||||
currentRoute.name === 'Profile' &&
|
currentRoute.name === 'Profile' &&
|
||||||
@@ -295,6 +315,7 @@ const NavItem: React.FC<{
|
|||||||
aria-role="link"
|
aria-role="link"
|
||||||
aria-label={routeName}
|
aria-label={routeName}
|
||||||
accessible={true}
|
accessible={true}
|
||||||
|
onBeforePress={onBeforePress}
|
||||||
onLongPress={onLongPress}>
|
onLongPress={onLongPress}>
|
||||||
{children({isActive})}
|
{children({isActive})}
|
||||||
{notificationCount ? (
|
{notificationCount ? (
|
||||||
|
|||||||
@@ -80,8 +80,20 @@ import * as Menu from '#/components/Menu'
|
|||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {useAgeAssurance} from '#/ageAssurance'
|
import {useAgeAssurance} from '#/ageAssurance'
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
import {useActorStatus} from '#/features/liveNow'
|
import {useActorStatus} from '#/features/liveNow'
|
||||||
import {router} from '#/routes'
|
import {router} from '#/routes'
|
||||||
|
|
||||||
|
type LeftNavItem =
|
||||||
|
| 'home'
|
||||||
|
| 'search'
|
||||||
|
| 'chat'
|
||||||
|
| 'notifications'
|
||||||
|
| 'feeds'
|
||||||
|
| 'lists'
|
||||||
|
| 'saved'
|
||||||
|
| 'profile'
|
||||||
|
| 'settings'
|
||||||
import {PlatformInfo} from '../../../../modules/expo-bluesky-swiss-army'
|
import {PlatformInfo} from '../../../../modules/expo-bluesky-swiss-army'
|
||||||
|
|
||||||
const NAV_ICON_WIDTH = 28
|
const NAV_ICON_WIDTH = 28
|
||||||
@@ -385,6 +397,7 @@ interface NavItemProps {
|
|||||||
iconFilled: JSX.Element
|
iconFilled: JSX.Element
|
||||||
label: string
|
label: string
|
||||||
minimal: boolean
|
minimal: boolean
|
||||||
|
navItem: LeftNavItem
|
||||||
}
|
}
|
||||||
function NavItem({
|
function NavItem({
|
||||||
count,
|
count,
|
||||||
@@ -394,9 +407,11 @@ function NavItem({
|
|||||||
iconFilled,
|
iconFilled,
|
||||||
label,
|
label,
|
||||||
minimal,
|
minimal,
|
||||||
|
navItem,
|
||||||
}: NavItemProps) {
|
}: NavItemProps) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const ax = useAnalytics()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
|
|
||||||
const [pathName] = useMemo(() => router.matchPath(href), [href])
|
const [pathName] = useMemo(() => router.matchPath(href), [href])
|
||||||
@@ -416,6 +431,7 @@ function NavItem({
|
|||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const onPressWrapped = useCallback(
|
const onPressWrapped = useCallback(
|
||||||
(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
||||||
|
ax.metric('nav:click', {item: navItem, surface: 'leftNav'})
|
||||||
if (e.ctrlKey || e.metaKey || e.altKey) {
|
if (e.ctrlKey || e.metaKey || e.altKey) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -428,7 +444,7 @@ function NavItem({
|
|||||||
navigation.navigate(screen, params, {pop: true})
|
navigation.navigate(screen, params, {pop: true})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[navigation, href, isCurrent],
|
[navigation, href, isCurrent, ax, navItem],
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -598,6 +614,7 @@ function ChatNavItem({minimal}: {minimal: boolean}) {
|
|||||||
return (
|
return (
|
||||||
<NavItem
|
<NavItem
|
||||||
href="/messages"
|
href="/messages"
|
||||||
|
navItem="chat"
|
||||||
minimal={minimal}
|
minimal={minimal}
|
||||||
count={aa.flags.chatDisabled ? undefined : numUnreadMessages.numUnread}
|
count={aa.flags.chatDisabled ? undefined : numUnreadMessages.numUnread}
|
||||||
hasNew={aa.flags.chatDisabled ? false : numUnreadMessages.hasNew}
|
hasNew={aa.flags.chatDisabled ? false : numUnreadMessages.hasNew}
|
||||||
@@ -676,6 +693,7 @@ export function DesktopLeftNav({routeName}: {routeName: string}) {
|
|||||||
<>
|
<>
|
||||||
<NavItem
|
<NavItem
|
||||||
href="/"
|
href="/"
|
||||||
|
navItem="home"
|
||||||
minimal={leftNavMinimal}
|
minimal={leftNavMinimal}
|
||||||
icon={
|
icon={
|
||||||
<Home
|
<Home
|
||||||
@@ -695,6 +713,7 @@ export function DesktopLeftNav({routeName}: {routeName: string}) {
|
|||||||
/>
|
/>
|
||||||
<NavItem
|
<NavItem
|
||||||
href="/search"
|
href="/search"
|
||||||
|
navItem="search"
|
||||||
minimal={leftNavMinimal}
|
minimal={leftNavMinimal}
|
||||||
icon={
|
icon={
|
||||||
<MagnifyingGlass
|
<MagnifyingGlass
|
||||||
@@ -714,6 +733,7 @@ export function DesktopLeftNav({routeName}: {routeName: string}) {
|
|||||||
/>
|
/>
|
||||||
<NavItem
|
<NavItem
|
||||||
href="/notifications"
|
href="/notifications"
|
||||||
|
navItem="notifications"
|
||||||
minimal={leftNavMinimal}
|
minimal={leftNavMinimal}
|
||||||
count={numUnreadNotifications}
|
count={numUnreadNotifications}
|
||||||
icon={
|
icon={
|
||||||
@@ -735,6 +755,7 @@ export function DesktopLeftNav({routeName}: {routeName: string}) {
|
|||||||
<ChatNavItem minimal={leftNavMinimal} />
|
<ChatNavItem minimal={leftNavMinimal} />
|
||||||
<NavItem
|
<NavItem
|
||||||
href="/feeds"
|
href="/feeds"
|
||||||
|
navItem="feeds"
|
||||||
minimal={leftNavMinimal}
|
minimal={leftNavMinimal}
|
||||||
icon={
|
icon={
|
||||||
<Hashtag
|
<Hashtag
|
||||||
@@ -754,6 +775,7 @@ export function DesktopLeftNav({routeName}: {routeName: string}) {
|
|||||||
/>
|
/>
|
||||||
<NavItem
|
<NavItem
|
||||||
href="/lists"
|
href="/lists"
|
||||||
|
navItem="lists"
|
||||||
minimal={leftNavMinimal}
|
minimal={leftNavMinimal}
|
||||||
icon={
|
icon={
|
||||||
<List
|
<List
|
||||||
@@ -773,6 +795,7 @@ export function DesktopLeftNav({routeName}: {routeName: string}) {
|
|||||||
/>
|
/>
|
||||||
<NavItem
|
<NavItem
|
||||||
href="/saved"
|
href="/saved"
|
||||||
|
navItem="saved"
|
||||||
minimal={leftNavMinimal}
|
minimal={leftNavMinimal}
|
||||||
icon={
|
icon={
|
||||||
<Bookmark
|
<Bookmark
|
||||||
@@ -797,6 +820,7 @@ export function DesktopLeftNav({routeName}: {routeName: string}) {
|
|||||||
/>
|
/>
|
||||||
<NavItem
|
<NavItem
|
||||||
href={currentAccount ? makeProfileLink(currentAccount) : '/'}
|
href={currentAccount ? makeProfileLink(currentAccount) : '/'}
|
||||||
|
navItem="profile"
|
||||||
minimal={leftNavMinimal}
|
minimal={leftNavMinimal}
|
||||||
icon={
|
icon={
|
||||||
<UserCircle
|
<UserCircle
|
||||||
@@ -816,6 +840,7 @@ export function DesktopLeftNav({routeName}: {routeName: string}) {
|
|||||||
/>
|
/>
|
||||||
<NavItem
|
<NavItem
|
||||||
href="/settings"
|
href="/settings"
|
||||||
|
navItem="settings"
|
||||||
minimal={leftNavMinimal}
|
minimal={leftNavMinimal}
|
||||||
icon={
|
icon={
|
||||||
<Settings
|
<Settings
|
||||||
|
|||||||
Reference in New Issue
Block a user