import React, {ComponentProps} from 'react' import { Linking, SafeAreaView, StyleProp, StyleSheet, TouchableOpacity, View, ViewStyle, } from 'react-native' import {useNavigation, StackActions} from '@react-navigation/native' import {observer} from 'mobx-react-lite' import { FontAwesomeIcon, FontAwesomeIconStyle, } from '@fortawesome/react-native-fontawesome' import {s, colors} from 'lib/styles' import {FEEDBACK_FORM_URL} from 'lib/constants' import {useStores} from 'state/index' import { HomeIcon, HomeIconSolid, BellIcon, BellIconSolid, UserIcon, CogIcon, MagnifyingGlassIcon2, MagnifyingGlassIcon2Solid, MoonIcon, UserIconSolid, } from 'lib/icons' import {UserAvatar} from 'view/com/util/UserAvatar' import {Text} from 'view/com/util/text/Text' import {useTheme} from 'lib/ThemeContext' import {usePalette} from 'lib/hooks/usePalette' import {useAnalytics} from 'lib/analytics' import {pluralize} from 'lib/strings/helpers' import {getTabState, TabState} from 'lib/routes/helpers' import {NavigationProp} from 'lib/routes/types' import {useNavigationTabState} from 'lib/hooks/useNavigationTabState' import {isWeb} from 'platform/detection' import {formatCount} from 'view/com/util/numeric/format' export const DrawerContent = observer(() => { const theme = useTheme() const pal = usePalette('default') const store = useStores() const navigation = useNavigation() const {track} = useAnalytics() const {isAtHome, isAtSearch, isAtNotifications, isAtMyProfile} = useNavigationTabState() const {notifications} = store.me // events // = const onPressTab = React.useCallback( (tab: string) => { track('Menu:ItemClicked', {url: tab}) const state = navigation.getState() store.shell.closeDrawer() if (isWeb) { // @ts-ignore must be Home, Search, Notifications, or MyProfile navigation.navigate(tab) } else { const tabState = getTabState(state, tab) if (tabState === TabState.InsideAtRoot) { store.emitScreenSoftReset() } else if (tabState === TabState.Inside) { navigation.dispatch(StackActions.popToTop()) } else { // @ts-ignore must be Home, Search, Notifications, or MyProfile navigation.navigate(`${tab}Tab`) } } }, [store, track, navigation], ) const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab]) const onPressSearch = React.useCallback( () => onPressTab('Search'), [onPressTab], ) const onPressNotifications = React.useCallback( () => onPressTab('Notifications'), [onPressTab], ) const onPressProfile = React.useCallback(() => { onPressTab('MyProfile') }, [onPressTab]) const onPressSettings = React.useCallback(() => { track('Menu:ItemClicked', {url: 'Settings'}) navigation.navigate('Settings') store.shell.closeDrawer() }, [navigation, track, store.shell]) const onPressFeedback = React.useCallback(() => { track('Menu:FeedbackClicked') Linking.openURL(FEEDBACK_FORM_URL) }, [track]) const onDarkmodePress = React.useCallback(() => { track('Menu:ItemClicked', {url: '#darkmode'}) store.shell.setDarkMode(!store.shell.darkMode) }, [track, store]) // rendering // = return ( {store.me.displayName || store.me.handle} @{store.me.handle} {formatCount(store.me.followersCount ?? 0)} {' '} {pluralize(store.me.followersCount || 0, 'follower')} ·{' '} {formatCount(store.me.followsCount ?? 0)} {' '} following } size={24} strokeWidth={1.7} /> ) : ( } size={24} strokeWidth={1.7} /> ) } label="Search" accessibilityLabel="Search" accessibilityHint="" bold={isAtSearch} onPress={onPressSearch} /> } size="24" strokeWidth={3.25} /> ) : ( } size="24" strokeWidth={3.25} /> ) } label="Home" accessibilityLabel="Home" accessibilityHint="" bold={isAtHome} onPress={onPressHome} /> } size="24" strokeWidth={1.7} /> ) : ( } size="24" strokeWidth={1.7} /> ) } label="Notifications" accessibilityLabel="Notifications" accessibilityHint={`${store.me.notifications.unreadCountLabel} unread`} count={notifications.unreadCountLabel} bold={isAtNotifications} onPress={onPressNotifications} /> } size="26" strokeWidth={1.5} /> ) : ( } size="26" strokeWidth={1.5} /> ) } label="Profile" accessibilityLabel="Profile" accessibilityHint="" onPress={onPressProfile} /> } size="26" strokeWidth={1.75} /> } label="Settings" accessibilityLabel="Settings" accessibilityHint="" onPress={onPressSettings} /> {!isWeb && ( } strokeWidth={2} /> )} Feedback ) }) interface MenuItemProps extends ComponentProps { icon: JSX.Element label: string count?: string bold?: boolean } function MenuItem({ icon, label, accessibilityLabel, count, bold, onPress, }: MenuItemProps) { const pal = usePalette('default') return ( {icon} {count ? ( 2 ? styles.menuItemCountHundreds : count.length > 1 ? styles.menuItemCountTens : undefined, ]}> {count} ) : undefined} {label} ) } const InviteCodes = observer(() => { const {track} = useAnalytics() const store = useStores() const pal = usePalette('default') const {invitesAvailable} = store.me const onPress = React.useCallback(() => { track('Menu:ItemClicked', {url: '#invite-codes'}) store.shell.closeDrawer() store.shell.openModal({name: 'invite-codes'}) }, [store, track]) return ( 0 ? pal.link : pal.textLight, ]} size={18} /> 0 ? pal.link : pal.textLight}> {formatCount(store.me.invitesAvailable)} invite{' '} {pluralize(store.me.invitesAvailable, 'code')} ) }) const styles = StyleSheet.create({ view: { flex: 1, paddingTop: 20, paddingBottom: 50, }, viewDarkMode: { backgroundColor: '#1B1919', }, main: { paddingLeft: 20, }, profileCardDisplayName: { marginTop: 20, paddingRight: 30, }, profileCardHandle: { marginTop: 4, paddingRight: 30, }, profileCardFollowers: { marginTop: 16, paddingRight: 10, }, menuItem: { flexDirection: 'row', alignItems: 'center', paddingVertical: 16, paddingRight: 10, }, menuItemIconWrapper: { width: 24, height: 24, alignItems: 'center', justifyContent: 'center', marginRight: 12, }, menuItemCount: { position: 'absolute', width: 'auto', right: -6, top: -4, backgroundColor: colors.blue3, paddingHorizontal: 4, paddingBottom: 1, borderRadius: 6, }, menuItemCountTens: { width: 25, }, menuItemCountHundreds: { right: -12, width: 34, }, menuItemCountLabel: { fontSize: 12, fontWeight: 'bold', fontVariant: ['tabular-nums'], color: colors.white, }, inviteCodes: { paddingLeft: 22, paddingVertical: 8, flexDirection: 'row', alignItems: 'center', }, inviteCodesIcon: { marginRight: 6, }, footer: { flexDirection: 'row', justifyContent: 'space-between', paddingRight: 30, paddingTop: 20, paddingLeft: 20, }, footerBtn: { flexDirection: 'row', alignItems: 'center', padding: 10, borderRadius: 25, }, footerBtnDarkMode: { backgroundColor: colors.black, }, footerBtnFeedback: { paddingHorizontal: 24, }, footerBtnFeedbackLight: { backgroundColor: '#DDEFFF', }, footerBtnFeedbackDark: { backgroundColor: colors.blue6, }, })