APP-70 give profile its own tab mobile (#469)
* add prebuild command to package.json * add ProfileTab navigator and screen * add prop to remove back button from profile * fix MyProfileTabNavigatorParams type * fix dep array for rendering ProfileHeader * just added ts-ignore * enable opening drawer in profile tab * clean up useNavigationTabState * clean up code * fix hideBackButton code flow
This commit is contained in:
parent
2509290fdd
commit
10621e86e4
10 changed files with 128 additions and 51 deletions
|
@ -36,8 +36,14 @@ import {FollowState} from 'state/models/cache/my-follows'
|
|||
|
||||
const BACK_HITSLOP = {left: 30, top: 30, right: 30, bottom: 30}
|
||||
|
||||
interface Props {
|
||||
view: ProfileModel
|
||||
onRefreshAll: () => void
|
||||
hideBackButton?: boolean
|
||||
}
|
||||
|
||||
export const ProfileHeader = observer(
|
||||
({view, onRefreshAll}: {view: ProfileModel; onRefreshAll: () => void}) => {
|
||||
({view, onRefreshAll, hideBackButton = false}: Props) => {
|
||||
const pal = usePalette('default')
|
||||
|
||||
// loading
|
||||
|
@ -80,17 +86,21 @@ export const ProfileHeader = observer(
|
|||
|
||||
// loaded
|
||||
// =
|
||||
return <ProfileHeaderLoaded view={view} onRefreshAll={onRefreshAll} />
|
||||
return (
|
||||
<ProfileHeaderLoaded
|
||||
view={view}
|
||||
onRefreshAll={onRefreshAll}
|
||||
hideBackButton={hideBackButton}
|
||||
/>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
const ProfileHeaderLoaded = observer(function ProfileHeaderLoaded({
|
||||
view,
|
||||
onRefreshAll,
|
||||
}: {
|
||||
view: ProfileModel
|
||||
onRefreshAll: () => void
|
||||
}) {
|
||||
hideBackButton = false,
|
||||
}: Props) {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
|
@ -336,7 +346,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoaded({
|
|||
</View>
|
||||
) : undefined}
|
||||
</View>
|
||||
{!isDesktopWeb && (
|
||||
{!isDesktopWeb && !hideBackButton && (
|
||||
<TouchableWithoutFeedback onPress={onPressBack} hitSlop={BACK_HITSLOP}>
|
||||
<View style={styles.backBtnWrapper}>
|
||||
<BlurView style={styles.backBtn} blurType="dark">
|
||||
|
|
|
@ -96,8 +96,14 @@ export const ProfileScreen = withAuthRequired(
|
|||
if (!uiState) {
|
||||
return <View />
|
||||
}
|
||||
return <ProfileHeader view={uiState.profile} onRefreshAll={onRefresh} />
|
||||
}, [uiState, onRefresh])
|
||||
return (
|
||||
<ProfileHeader
|
||||
view={uiState.profile}
|
||||
onRefreshAll={onRefresh}
|
||||
hideBackButton={route.params.hideBackButton}
|
||||
/>
|
||||
)
|
||||
}, [uiState, onRefresh, route.params.hideBackButton])
|
||||
const Footer = React.useMemo(() => {
|
||||
return uiState.showLoadingMoreFooter ? LoadingMoreFooter : undefined
|
||||
}, [uiState.showLoadingMoreFooter])
|
||||
|
|
|
@ -27,6 +27,7 @@ import {
|
|||
MagnifyingGlassIcon2,
|
||||
MagnifyingGlassIcon2Solid,
|
||||
MoonIcon,
|
||||
UserIconSolid,
|
||||
} from 'lib/icons'
|
||||
import {UserAvatar} from 'view/com/util/UserAvatar'
|
||||
import {Text} from 'view/com/util/text/Text'
|
||||
|
@ -45,7 +46,8 @@ export const DrawerContent = observer(() => {
|
|||
const store = useStores()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {track} = useAnalytics()
|
||||
const {isAtHome, isAtSearch, isAtNotifications} = useNavigationTabState()
|
||||
const {isAtHome, isAtSearch, isAtNotifications, isAtMyProfile} =
|
||||
useNavigationTabState()
|
||||
|
||||
// events
|
||||
// =
|
||||
|
@ -56,7 +58,7 @@ export const DrawerContent = observer(() => {
|
|||
const state = navigation.getState()
|
||||
store.shell.closeDrawer()
|
||||
if (isWeb) {
|
||||
// @ts-ignore must be Home, Search, or Notifications
|
||||
// @ts-ignore must be Home, Search, Notifications, or MyProfile
|
||||
navigation.navigate(tab)
|
||||
} else {
|
||||
const tabState = getTabState(state, tab)
|
||||
|
@ -65,7 +67,7 @@ export const DrawerContent = observer(() => {
|
|||
} else if (tabState === TabState.Inside) {
|
||||
navigation.dispatch(StackActions.popToTop())
|
||||
} else {
|
||||
// @ts-ignore must be Home, Search, or Notifications
|
||||
// @ts-ignore must be Home, Search, Notifications, or MyProfile
|
||||
navigation.navigate(`${tab}Tab`)
|
||||
}
|
||||
}
|
||||
|
@ -86,10 +88,8 @@ export const DrawerContent = observer(() => {
|
|||
)
|
||||
|
||||
const onPressProfile = React.useCallback(() => {
|
||||
track('Menu:ItemClicked', {url: 'Profile'})
|
||||
navigation.navigate('Profile', {name: store.me.handle})
|
||||
store.shell.closeDrawer()
|
||||
}, [navigation, track, store.me.handle, store.shell])
|
||||
onPressTab('MyProfile')
|
||||
}, [onPressTab])
|
||||
|
||||
const onPressSettings = React.useCallback(() => {
|
||||
track('Menu:ItemClicked', {url: 'Settings'})
|
||||
|
@ -211,11 +211,19 @@ export const DrawerContent = observer(() => {
|
|||
/>
|
||||
<MenuItem
|
||||
icon={
|
||||
<UserIcon
|
||||
style={pal.text as StyleProp<ViewStyle>}
|
||||
size="26"
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
isAtMyProfile ? (
|
||||
<UserIconSolid
|
||||
style={pal.text as StyleProp<ViewStyle>}
|
||||
size="26"
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
) : (
|
||||
<UserIcon
|
||||
style={pal.text as StyleProp<ViewStyle>}
|
||||
size="26"
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
)
|
||||
}
|
||||
label="Profile"
|
||||
onPress={onPressProfile}
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {StackActions, useNavigationState} from '@react-navigation/native'
|
||||
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'
|
||||
|
@ -21,34 +21,21 @@ import {
|
|||
BellIcon,
|
||||
BellIconSolid,
|
||||
UserIcon,
|
||||
UserIconSolid,
|
||||
} 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'
|
||||
|
||||
export const BottomBar = observer(({navigation}: BottomTabBarProps) => {
|
||||
const store = useStores()
|
||||
const pal = usePalette('default')
|
||||
const safeAreaInsets = useSafeAreaInsets()
|
||||
const {track} = useAnalytics()
|
||||
const {isAtHome, isAtSearch, isAtNotifications} = useNavigationState(
|
||||
state => {
|
||||
const res = {
|
||||
isAtHome: getTabState(state, 'Home') !== TabState.Outside,
|
||||
isAtSearch: getTabState(state, 'Search') !== TabState.Outside,
|
||||
isAtNotifications:
|
||||
getTabState(state, 'Notifications') !== TabState.Outside,
|
||||
}
|
||||
if (!res.isAtHome && !res.isAtNotifications && !res.isAtSearch) {
|
||||
// HACK for some reason useNavigationState will give us pre-hydration results
|
||||
// and not update after, so we force isAtHome if all came back false
|
||||
// -prf
|
||||
res.isAtHome = true
|
||||
}
|
||||
return res
|
||||
},
|
||||
)
|
||||
const {isAtHome, isAtSearch, isAtNotifications, isAtMyProfile} =
|
||||
useNavigationTabState()
|
||||
|
||||
const {footerMinimalShellTransform} = useMinimalShellMode()
|
||||
|
||||
|
@ -77,9 +64,8 @@ export const BottomBar = observer(({navigation}: BottomTabBarProps) => {
|
|||
[onPressTab],
|
||||
)
|
||||
const onPressProfile = React.useCallback(() => {
|
||||
track('MobileShell:ProfileButtonPressed')
|
||||
navigation.navigate('Profile', {name: store.me.handle})
|
||||
}, [navigation, track, store.me.handle])
|
||||
onPressTab('MyProfile')
|
||||
}, [onPressTab])
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
|
@ -154,11 +140,19 @@ export const BottomBar = observer(({navigation}: BottomTabBarProps) => {
|
|||
testID="bottomBarProfileBtn"
|
||||
icon={
|
||||
<View style={styles.ctrlIconSizingWrapper}>
|
||||
<UserIcon
|
||||
size={28}
|
||||
strokeWidth={1.5}
|
||||
style={[styles.ctrlIcon, pal.text, styles.profileIcon]}
|
||||
/>
|
||||
{isAtMyProfile ? (
|
||||
<UserIconSolid
|
||||
size={28}
|
||||
strokeWidth={1.5}
|
||||
style={[styles.ctrlIcon, pal.text, styles.profileIcon]}
|
||||
/>
|
||||
) : (
|
||||
<UserIcon
|
||||
size={28}
|
||||
strokeWidth={1.5}
|
||||
style={[styles.ctrlIcon, pal.text, styles.profileIcon]}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
}
|
||||
onPress={onPressProfile}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue