From 556543789164e7b303fb3b6f29c1ff0b6785fa54 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Fri, 15 Mar 2024 17:52:07 +0800 Subject: [PATCH 1/3] restructure the profile avatar so the area around the avatar is clickable --- .../BottomTabBar.tsx | 4 +- .../home/sidebar/AvatarWithOptionalStatus.tsx | 25 ++------ src/pages/home/sidebar/BottomTabAvatar.tsx | 27 +++++++-- .../sidebar/PressableAvatarWithIndicator.tsx | 59 ------------------- .../sidebar/ProfileAvatarWithIndicator.tsx | 48 +++++++++++++++ 5 files changed, 75 insertions(+), 88 deletions(-) delete mode 100644 src/pages/home/sidebar/PressableAvatarWithIndicator.tsx create mode 100644 src/pages/home/sidebar/ProfileAvatarWithIndicator.tsx diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx index 3a59e42bcca1..0702b4433041 100644 --- a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx @@ -86,9 +86,7 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps - - - + ); } diff --git a/src/pages/home/sidebar/AvatarWithOptionalStatus.tsx b/src/pages/home/sidebar/AvatarWithOptionalStatus.tsx index 548b0de2fb64..da9f8f52d319 100644 --- a/src/pages/home/sidebar/AvatarWithOptionalStatus.tsx +++ b/src/pages/home/sidebar/AvatarWithOptionalStatus.tsx @@ -1,11 +1,8 @@ import React from 'react'; import {View} from 'react-native'; -import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; import Text from '@components/Text'; -import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import CONST from '@src/CONST'; -import PressableAvatarWithIndicator from './PressableAvatarWithIndicator'; +import ProfileAvatarWithIndicator from './ProfileAvatarWithIndicator'; type AvatarWithOptionalStatusProps = { /** Emoji status */ @@ -13,34 +10,22 @@ type AvatarWithOptionalStatusProps = { /** Whether the avatar is selected */ isSelected?: boolean; - - /** Callback called when the avatar or status icon is pressed */ - onPress?: () => void; }; -function AvatarWithOptionalStatus({emojiStatus = '', isSelected = false, onPress}: AvatarWithOptionalStatusProps) { +function AvatarWithOptionalStatus({emojiStatus = '', isSelected = false}: AvatarWithOptionalStatusProps) { const styles = useThemeStyles(); - const {translate} = useLocalize(); return ( - - + + {emojiStatus} - + ); } diff --git a/src/pages/home/sidebar/BottomTabAvatar.tsx b/src/pages/home/sidebar/BottomTabAvatar.tsx index 15134b762161..40b9ebd28221 100644 --- a/src/pages/home/sidebar/BottomTabAvatar.tsx +++ b/src/pages/home/sidebar/BottomTabAvatar.tsx @@ -1,11 +1,15 @@ /* eslint-disable rulesdir/onyx-props-must-have-default */ import React, {useCallback} from 'react'; +import {PressableWithFeedback} from '@components/Pressable'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; import interceptAnonymousUser from '@libs/interceptAnonymousUser'; import Navigation from '@libs/Navigation/Navigation'; +import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import AvatarWithOptionalStatus from './AvatarWithOptionalStatus'; -import PressableAvatarWithIndicator from './PressableAvatarWithIndicator'; +import ProfileAvatarWithIndicator from './ProfileAvatarWithIndicator'; type BottomTabAvatarProps = { /** Whether the create menu is open or not */ @@ -16,6 +20,8 @@ type BottomTabAvatarProps = { }; function BottomTabAvatar({isCreateMenuOpen = false, isSelected = false}: BottomTabAvatarProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const emojiStatus = currentUserPersonalDetails?.status?.emojiCode ?? ''; @@ -28,20 +34,29 @@ function BottomTabAvatar({isCreateMenuOpen = false, isSelected = false}: BottomT interceptAnonymousUser(() => Navigation.navigate(ROUTES.SETTINGS)); }, [isCreateMenuOpen]); + let children; + if (emojiStatus) { - return ( + children = ( ); + } else { + children = ; } + return ( - + role={CONST.ROLE.BUTTON} + accessibilityLabel={translate('sidebarScreen.buttonMySettings')} + wrapperStyle={styles.flex1} + style={styles.bottomTabBarItem} + > + {children} + ); } diff --git a/src/pages/home/sidebar/PressableAvatarWithIndicator.tsx b/src/pages/home/sidebar/PressableAvatarWithIndicator.tsx deleted file mode 100644 index 53bae3d8a770..000000000000 --- a/src/pages/home/sidebar/PressableAvatarWithIndicator.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import React from 'react'; -import {View} from 'react-native'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; -import AvatarWithIndicator from '@components/AvatarWithIndicator'; -import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; -import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; -import * as UserUtils from '@libs/UserUtils'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; - -type PressableAvatarWithIndicatorOnyxProps = { - /** Indicates whether the app is loading initial data */ - isLoading: OnyxEntry; -}; - -type PressableAvatarWithIndicatorProps = PressableAvatarWithIndicatorOnyxProps & { - /** Whether the avatar is selected */ - isSelected: boolean; - - /** Callback called when the avatar is pressed */ - onPress?: () => void; -}; - -function PressableAvatarWithIndicator({isLoading = true, isSelected = false, onPress}: PressableAvatarWithIndicatorProps) { - const {translate} = useLocalize(); - const styles = useThemeStyles(); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - - return ( - - - - - - - - ); -} - -PressableAvatarWithIndicator.displayName = 'PressableAvatarWithIndicator'; - -export default withOnyx({ - isLoading: { - key: ONYXKEYS.IS_LOADING_APP, - }, -})(PressableAvatarWithIndicator); diff --git a/src/pages/home/sidebar/ProfileAvatarWithIndicator.tsx b/src/pages/home/sidebar/ProfileAvatarWithIndicator.tsx new file mode 100644 index 000000000000..37c17203ac7e --- /dev/null +++ b/src/pages/home/sidebar/ProfileAvatarWithIndicator.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import {View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; +import AvatarWithIndicator from '@components/AvatarWithIndicator'; +import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as UserUtils from '@libs/UserUtils'; +import ONYXKEYS from '@src/ONYXKEYS'; + +type ProfileAvatarWithIndicatorOnyxProps = { + /** Indicates whether the app is loading initial data */ + isLoading: OnyxEntry; +}; + +type ProfileAvatarWithIndicatorProps = ProfileAvatarWithIndicatorOnyxProps & { + /** Whether the avatar is selected */ + isSelected: boolean; +}; + +function ProfileAvatarWithIndicator({isLoading = true, isSelected = false}: ProfileAvatarWithIndicatorProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + + return ( + + + + + + ); +} + +ProfileAvatarWithIndicator.displayName = 'PressableAvatarWithIndicator'; + +export default withOnyx({ + isLoading: { + key: ONYXKEYS.IS_LOADING_APP, + }, +})(ProfileAvatarWithIndicator); From 1e611cb4b4103b58d5f65aa605ac70a01710da8e Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Fri, 15 Mar 2024 19:31:05 +0800 Subject: [PATCH 2/3] rename display name --- src/pages/home/sidebar/ProfileAvatarWithIndicator.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/sidebar/ProfileAvatarWithIndicator.tsx b/src/pages/home/sidebar/ProfileAvatarWithIndicator.tsx index 37c17203ac7e..b91fe79366ad 100644 --- a/src/pages/home/sidebar/ProfileAvatarWithIndicator.tsx +++ b/src/pages/home/sidebar/ProfileAvatarWithIndicator.tsx @@ -39,7 +39,7 @@ function ProfileAvatarWithIndicator({isLoading = true, isSelected = false}: Prof ); } -ProfileAvatarWithIndicator.displayName = 'PressableAvatarWithIndicator'; +ProfileAvatarWithIndicator.displayName = 'ProfileAvatarWithIndicator'; export default withOnyx({ isLoading: { From 19a772d428469cfcf113183c52c65534e9647926 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Mon, 18 Mar 2024 15:27:14 +0800 Subject: [PATCH 3/3] fix unable to close fab and tooltip area --- src/components/FloatingActionButton.tsx | 69 ++++++++----------- .../BottomTabBar.tsx | 24 +++---- src/pages/home/sidebar/BottomTabAvatar.tsx | 21 +++--- .../sidebar/ProfileAvatarWithIndicator.js | 3 - 4 files changed, 53 insertions(+), 64 deletions(-) diff --git a/src/components/FloatingActionButton.tsx b/src/components/FloatingActionButton.tsx index b9c52ad397ec..ee61beda74ae 100644 --- a/src/components/FloatingActionButton.tsx +++ b/src/components/FloatingActionButton.tsx @@ -1,8 +1,8 @@ import type {ForwardedRef} from 'react'; import React, {forwardRef, useEffect, useRef} from 'react'; // eslint-disable-next-line no-restricted-imports -import type {GestureResponderEvent, Role, Text} from 'react-native'; -import {Platform, View} from 'react-native'; +import type {GestureResponderEvent, Role, Text, View} from 'react-native'; +import {Platform} from 'react-native'; import Animated, {createAnimatedPropAdapter, Easing, interpolateColor, processColor, useAnimatedProps, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; import Svg, {Path} from 'react-native-svg'; import useLocalize from '@hooks/useLocalize'; @@ -10,15 +10,11 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import variables from '@styles/variables'; import {PressableWithoutFeedback} from './Pressable'; -import PressableWithFeedback from './Pressable/PressableWithFeedback'; import Tooltip from './Tooltip/PopoverAnchorTooltip'; const AnimatedPath = Animated.createAnimatedComponent(Path); AnimatedPath.displayName = 'AnimatedPath'; -const AnimatedPressable = Animated.createAnimatedComponent(PressableWithFeedback); -AnimatedPressable.displayName = 'AnimatedPressable'; - type AdapterPropsRecord = { type: number; payload?: number | null; @@ -104,41 +100,34 @@ function FloatingActionButton({onPress, isActive, accessibilityLabel, role}: Flo }; return ( - - - - { - fabPressable.current = el ?? null; - if (buttonRef && 'current' in buttonRef) { - buttonRef.current = el ?? null; - } - }} - accessibilityLabel={accessibilityLabel} - role={role} - pressDimmingValue={1} - onPress={toggleFabAction} - onLongPress={() => {}} - shouldUseHapticsOnLongPress={false} - style={[styles.floatingActionButton, animatedStyle]} + + { + fabPressable.current = el ?? null; + if (buttonRef && 'current' in buttonRef) { + buttonRef.current = el ?? null; + } + }} + style={[styles.h100, styles.bottomTabBarItem]} + accessibilityLabel={accessibilityLabel} + onPress={toggleFabAction} + onLongPress={() => {}} + role={role} + shouldUseHapticsOnLongPress={false} + > + + - - - - - - - + + + + + ); } diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx index 0702b4433041..6d20361b75f5 100644 --- a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx @@ -61,16 +61,16 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps return ( - { - Navigation.navigate(ROUTES.HOME); - }} - role={CONST.ROLE.BUTTON} - accessibilityLabel={translate('common.chats')} - wrapperStyle={styles.flex1} - style={styles.bottomTabBarItem} - > - + + { + Navigation.navigate(ROUTES.HOME); + }} + role={CONST.ROLE.BUTTON} + accessibilityLabel={translate('common.chats')} + wrapperStyle={styles.flex1} + style={styles.bottomTabBarItem} + > )} - - + + diff --git a/src/pages/home/sidebar/BottomTabAvatar.tsx b/src/pages/home/sidebar/BottomTabAvatar.tsx index 40b9ebd28221..63abcf063b5f 100644 --- a/src/pages/home/sidebar/BottomTabAvatar.tsx +++ b/src/pages/home/sidebar/BottomTabAvatar.tsx @@ -1,6 +1,7 @@ /* eslint-disable rulesdir/onyx-props-must-have-default */ import React, {useCallback} from 'react'; import {PressableWithFeedback} from '@components/Pressable'; +import Tooltip from '@components/Tooltip'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -48,15 +49,17 @@ function BottomTabAvatar({isCreateMenuOpen = false, isSelected = false}: BottomT } return ( - - {children} - + + + {children} + + ); } diff --git a/src/pages/home/sidebar/ProfileAvatarWithIndicator.js b/src/pages/home/sidebar/ProfileAvatarWithIndicator.js index a24091aa91ed..bd9c01aba001 100644 --- a/src/pages/home/sidebar/ProfileAvatarWithIndicator.js +++ b/src/pages/home/sidebar/ProfileAvatarWithIndicator.js @@ -7,7 +7,6 @@ import {withOnyx} from 'react-native-onyx'; import AvatarWithIndicator from '@components/AvatarWithIndicator'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails'; -import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import compose from '@libs/compose'; import * as UserUtils from '@libs/UserUtils'; @@ -36,7 +35,6 @@ const defaultProps = { }; function ProfileAvatarWithIndicator({currentUserPersonalDetails, isLoading, isSelected}) { - const {translate} = useLocalize(); const styles = useThemeStyles(); return ( @@ -44,7 +42,6 @@ function ProfileAvatarWithIndicator({currentUserPersonalDetails, isLoading, isSe