memoize bottom bar
This commit is contained in:
@@ -121,6 +121,107 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
accountSwitchControl.open()
|
accountSwitchControl.open()
|
||||||
}, [accountSwitchControl, playHaptic])
|
}, [accountSwitchControl, playHaptic])
|
||||||
|
|
||||||
|
const renderHomeIcon = React.useCallback(
|
||||||
|
() =>
|
||||||
|
isAtHome ? (
|
||||||
|
<HomeFilled
|
||||||
|
width={iconWidth + 1}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Home
|
||||||
|
width={iconWidth + 1}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[isAtHome, pal.text],
|
||||||
|
)
|
||||||
|
|
||||||
|
const renderSearchIcon = React.useCallback(
|
||||||
|
() =>
|
||||||
|
isAtSearch ? (
|
||||||
|
<MagnifyingGlassFilled
|
||||||
|
width={iconWidth + 2}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<MagnifyingGlass
|
||||||
|
testID="bottomBarSearchBtn"
|
||||||
|
width={iconWidth + 2}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[isAtSearch, pal.text],
|
||||||
|
)
|
||||||
|
|
||||||
|
const renderMessagesIcon = React.useCallback(
|
||||||
|
() =>
|
||||||
|
isAtMessages ? (
|
||||||
|
<MessageFilled
|
||||||
|
width={iconWidth - 1}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Message
|
||||||
|
width={iconWidth - 1}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[isAtMessages, pal.text],
|
||||||
|
)
|
||||||
|
|
||||||
|
const renderNotificationsIcon = React.useCallback(
|
||||||
|
() =>
|
||||||
|
isAtNotifications ? (
|
||||||
|
<BellFilled
|
||||||
|
width={iconWidth}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Bell
|
||||||
|
width={iconWidth}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[isAtNotifications, pal.text],
|
||||||
|
)
|
||||||
|
|
||||||
|
const renderProfileIcon = React.useCallback(
|
||||||
|
() => (
|
||||||
|
<View style={styles.ctrlIconSizingWrapper}>
|
||||||
|
{isAtMyProfile ? (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.ctrlIcon,
|
||||||
|
pal.text,
|
||||||
|
styles.profileIcon,
|
||||||
|
styles.onProfile,
|
||||||
|
{borderColor: pal.text.color},
|
||||||
|
]}>
|
||||||
|
<UserAvatar
|
||||||
|
avatar={profile?.avatar}
|
||||||
|
size={iconWidth - 3}
|
||||||
|
// See https://github.com/bluesky-social/social-app/pull/1801:
|
||||||
|
usePlainRNImage={true}
|
||||||
|
type={profile?.associated?.labeler ? 'labeler' : 'user'}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<View style={[styles.ctrlIcon, pal.text, styles.profileIcon]}>
|
||||||
|
<UserAvatar
|
||||||
|
avatar={profile?.avatar}
|
||||||
|
size={iconWidth - 3}
|
||||||
|
// See https://github.com/bluesky-social/social-app/pull/1801:
|
||||||
|
usePlainRNImage={true}
|
||||||
|
type={profile?.associated?.labeler ? 'labeler' : 'user'}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
),
|
||||||
|
[isAtMyProfile, profile?.avatar, profile?.associated?.labeler, pal.text],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SwitchAccountDialog control={accountSwitchControl} />
|
<SwitchAccountDialog control={accountSwitchControl} />
|
||||||
@@ -140,39 +241,15 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
<>
|
<>
|
||||||
<Btn
|
<Btn
|
||||||
testID="bottomBarHomeBtn"
|
testID="bottomBarHomeBtn"
|
||||||
icon={
|
renderIcon={renderHomeIcon}
|
||||||
isAtHome ? (
|
|
||||||
<HomeFilled
|
|
||||||
width={iconWidth + 1}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<Home
|
|
||||||
width={iconWidth + 1}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onPress={onPressHome}
|
onPress={onPressHome}
|
||||||
accessibilityRole="tab"
|
accessibilityRole="tab"
|
||||||
accessibilityLabel={_(msg`Home`)}
|
accessibilityLabel={_(msg`Home`)}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
/>
|
/>
|
||||||
<Btn
|
<Btn
|
||||||
icon={
|
testID="bottomBarSearchBtn"
|
||||||
isAtSearch ? (
|
renderIcon={renderSearchIcon}
|
||||||
<MagnifyingGlassFilled
|
|
||||||
width={iconWidth + 2}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<MagnifyingGlass
|
|
||||||
testID="bottomBarSearchBtn"
|
|
||||||
width={iconWidth + 2}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onPress={onPressSearch}
|
onPress={onPressSearch}
|
||||||
accessibilityRole="search"
|
accessibilityRole="search"
|
||||||
accessibilityLabel={_(msg`Search`)}
|
accessibilityLabel={_(msg`Search`)}
|
||||||
@@ -180,19 +257,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
/>
|
/>
|
||||||
<Btn
|
<Btn
|
||||||
testID="bottomBarMessagesBtn"
|
testID="bottomBarMessagesBtn"
|
||||||
icon={
|
renderIcon={renderMessagesIcon}
|
||||||
isAtMessages ? (
|
|
||||||
<MessageFilled
|
|
||||||
width={iconWidth - 1}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<Message
|
|
||||||
width={iconWidth - 1}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onPress={onPressMessages}
|
onPress={onPressMessages}
|
||||||
notificationCount={numUnreadMessages.numUnread}
|
notificationCount={numUnreadMessages.numUnread}
|
||||||
accessible={true}
|
accessible={true}
|
||||||
@@ -206,19 +271,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
/>
|
/>
|
||||||
<Btn
|
<Btn
|
||||||
testID="bottomBarNotificationsBtn"
|
testID="bottomBarNotificationsBtn"
|
||||||
icon={
|
renderIcon={renderNotificationsIcon}
|
||||||
isAtNotifications ? (
|
|
||||||
<BellFilled
|
|
||||||
width={iconWidth}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<Bell
|
|
||||||
width={iconWidth}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onPress={onPressNotifications}
|
onPress={onPressNotifications}
|
||||||
notificationCount={numUnreadNotifications}
|
notificationCount={numUnreadNotifications}
|
||||||
accessible={true}
|
accessible={true}
|
||||||
@@ -232,39 +285,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
/>
|
/>
|
||||||
<Btn
|
<Btn
|
||||||
testID="bottomBarProfileBtn"
|
testID="bottomBarProfileBtn"
|
||||||
icon={
|
renderIcon={renderProfileIcon}
|
||||||
<View style={styles.ctrlIconSizingWrapper}>
|
|
||||||
{isAtMyProfile ? (
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
styles.ctrlIcon,
|
|
||||||
pal.text,
|
|
||||||
styles.profileIcon,
|
|
||||||
styles.onProfile,
|
|
||||||
{borderColor: pal.text.color},
|
|
||||||
]}>
|
|
||||||
<UserAvatar
|
|
||||||
avatar={profile?.avatar}
|
|
||||||
size={iconWidth - 3}
|
|
||||||
// See https://github.com/bluesky-social/social-app/pull/1801:
|
|
||||||
usePlainRNImage={true}
|
|
||||||
type={profile?.associated?.labeler ? 'labeler' : 'user'}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
) : (
|
|
||||||
<View
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.profileIcon]}>
|
|
||||||
<UserAvatar
|
|
||||||
avatar={profile?.avatar}
|
|
||||||
size={iconWidth - 3}
|
|
||||||
// See https://github.com/bluesky-social/social-app/pull/1801:
|
|
||||||
usePlainRNImage={true}
|
|
||||||
type={profile?.associated?.labeler ? 'labeler' : 'user'}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
}
|
|
||||||
onPress={onPressProfile}
|
onPress={onPressProfile}
|
||||||
onLongPress={onLongPressProfile}
|
onLongPress={onLongPressProfile}
|
||||||
accessibilityRole="tab"
|
accessibilityRole="tab"
|
||||||
@@ -332,22 +353,22 @@ interface BtnProps
|
|||||||
| 'accessibilityLabel'
|
| 'accessibilityLabel'
|
||||||
> {
|
> {
|
||||||
testID?: string
|
testID?: string
|
||||||
icon: JSX.Element
|
renderIcon: () => React.ReactNode
|
||||||
notificationCount?: string
|
notificationCount?: string
|
||||||
onPress?: (event: GestureResponderEvent) => void
|
onPress?: (event: GestureResponderEvent) => void
|
||||||
onLongPress?: (event: GestureResponderEvent) => void
|
onLongPress?: (event: GestureResponderEvent) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
function Btn({
|
let Btn = ({
|
||||||
testID,
|
testID,
|
||||||
icon,
|
renderIcon,
|
||||||
notificationCount,
|
notificationCount,
|
||||||
onPress,
|
onPress,
|
||||||
onLongPress,
|
onLongPress,
|
||||||
accessible,
|
accessible,
|
||||||
accessibilityHint,
|
accessibilityHint,
|
||||||
accessibilityLabel,
|
accessibilityLabel,
|
||||||
}: BtnProps) {
|
}: BtnProps): React.ReactNode => {
|
||||||
return (
|
return (
|
||||||
<PressableScale
|
<PressableScale
|
||||||
testID={testID}
|
testID={testID}
|
||||||
@@ -358,7 +379,7 @@ function Btn({
|
|||||||
accessibilityLabel={accessibilityLabel}
|
accessibilityLabel={accessibilityLabel}
|
||||||
accessibilityHint={accessibilityHint}
|
accessibilityHint={accessibilityHint}
|
||||||
targetScale={0.8}>
|
targetScale={0.8}>
|
||||||
{icon}
|
{renderIcon()}
|
||||||
{notificationCount ? (
|
{notificationCount ? (
|
||||||
<View style={[styles.notificationCount, a.rounded_full]}>
|
<View style={[styles.notificationCount, a.rounded_full]}>
|
||||||
<Text style={styles.notificationCountLabel}>{notificationCount}</Text>
|
<Text style={styles.notificationCountLabel}>{notificationCount}</Text>
|
||||||
@@ -367,3 +388,4 @@ function Btn({
|
|||||||
</PressableScale>
|
</PressableScale>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Btn = React.memo(Btn)
|
||||||
|
|||||||
Reference in New Issue
Block a user