diff --git a/native/user-profile/user-profile-constants.js b/native/user-profile/user-profile-constants.js new file mode 100644 index 000000000..8b351122c --- /dev/null +++ b/native/user-profile/user-profile-constants.js @@ -0,0 +1,9 @@ +// @flow + +export const userProfileUserInfoContainerHeight = 90; + +export const userProfileBottomPadding = 40; + +export const userProfileMenuButtonHeight = 24; + +export const userProfileActionButtonHeight = 54; diff --git a/native/user-profile/user-profile-relationship-button.react.js b/native/user-profile/user-profile-relationship-button.react.js index d43c0060b..d1cf975b9 100644 --- a/native/user-profile/user-profile-relationship-button.react.js +++ b/native/user-profile/user-profile-relationship-button.react.js @@ -1,150 +1,149 @@ // @flow import * as React from 'react'; import { View, Text } from 'react-native'; import { useRelationshipPrompt } from 'lib/hooks/relationship-prompt.js'; import type { SetState } from 'lib/types/hook-types.js'; import { userRelationshipStatus } from 'lib/types/relationship-types.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; import type { UserInfo } from 'lib/types/user-types'; +import { userProfileActionButtonHeight } from './user-profile-constants.js'; import RelationshipButton from '../components/relationship-button.react.js'; import { useStyles } from '../themes/colors.js'; import Alert from '../utils/alert.js'; const onErrorCallback = () => { Alert.alert('Unknown error', 'Uhh... try again?', [{ text: 'OK' }]); }; type Props = { +threadInfo: ThreadInfo, +pendingPersonalThreadUserInfo?: UserInfo, +setUserProfileRelationshipButtonHeight: SetState, }; function UserProfileRelationshipButton(props: Props): React.Node { const { threadInfo, pendingPersonalThreadUserInfo, setUserProfileRelationshipButtonHeight, } = props; const { otherUserInfo, callbacks: { friendUser, unfriendUser }, } = useRelationshipPrompt( threadInfo, onErrorCallback, pendingPersonalThreadUserInfo, ); React.useLayoutEffect(() => { if (otherUserInfo?.relationshipStatus === userRelationshipStatus.FRIEND) { setUserProfileRelationshipButtonHeight(0); } else if ( otherUserInfo?.relationshipStatus === userRelationshipStatus.REQUEST_RECEIVED ) { const incomingFriendRequestButtonsContainerHeight = 88; setUserProfileRelationshipButtonHeight( incomingFriendRequestButtonsContainerHeight, ); } else { - const relationshipButtonHeight = 54; - - setUserProfileRelationshipButtonHeight(relationshipButtonHeight); + setUserProfileRelationshipButtonHeight(userProfileActionButtonHeight); } }, [ otherUserInfo?.relationshipStatus, setUserProfileRelationshipButtonHeight, ]); const styles = useStyles(unboundStyles); const userProfileRelationshipButton = React.useMemo(() => { if ( !otherUserInfo || !otherUserInfo.username || otherUserInfo.relationshipStatus === userRelationshipStatus.FRIEND ) { return null; } if ( otherUserInfo.relationshipStatus === userRelationshipStatus.REQUEST_RECEIVED ) { return ( Incoming friend request ); } if ( otherUserInfo.relationshipStatus === userRelationshipStatus.REQUEST_SENT ) { return ( ); } return ( ); }, [ friendUser, otherUserInfo, styles.acceptFriendRequestButtonContainer, styles.incomingFriendRequestButtonsContainer, styles.incomingFriendRequestContainer, styles.incomingFriendRequestLabel, styles.rejectFriendRequestButtonContainer, styles.singleButtonContainer, unfriendUser, ]); return userProfileRelationshipButton; } const unboundStyles = { singleButtonContainer: { marginTop: 16, }, incomingFriendRequestContainer: { marginTop: 24, }, incomingFriendRequestLabel: { color: 'modalForegroundLabel', }, incomingFriendRequestButtonsContainer: { flexDirection: 'row', marginTop: 8, }, acceptFriendRequestButtonContainer: { flex: 1, marginRight: 4, }, rejectFriendRequestButtonContainer: { flex: 1, marginLeft: 4, }, }; export default UserProfileRelationshipButton; diff --git a/native/user-profile/user-profile.react.js b/native/user-profile/user-profile.react.js index 6b87bd94a..e40476f5c 100644 --- a/native/user-profile/user-profile.react.js +++ b/native/user-profile/user-profile.react.js @@ -1,222 +1,228 @@ // @flow import Clipboard from '@react-native-clipboard/clipboard'; import invariant from 'invariant'; import * as React from 'react'; import { View, Text, TouchableOpacity } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { relationshipBlockedInEitherDirection } from 'lib/shared/relationship-utils.js'; import { useUserProfileThreadInfo } from 'lib/shared/thread-utils.js'; import { stringForUserExplicit } from 'lib/shared/user-utils.js'; import type { UserInfo } from 'lib/types/user-types'; import sleep from 'lib/utils/sleep.js'; +import { + userProfileUserInfoContainerHeight, + userProfileBottomPadding, + userProfileMenuButtonHeight, + userProfileActionButtonHeight, +} from './user-profile-constants.js'; import UserProfileMessageButton from './user-profile-message-button.react.js'; import UserProfileRelationshipButton from './user-profile-relationship-button.react.js'; import UserAvatar from '../avatars/user-avatar.react.js'; import { BottomSheetContext } from '../bottom-sheet/bottom-sheet-provider.react.js'; import SingleLine from '../components/single-line.react.js'; import SWMansionIcon from '../components/swmansion-icon.react.js'; import { useStyles } from '../themes/colors.js'; type Props = { +userInfo: ?UserInfo, }; function UserProfile(props: Props): React.Node { const { userInfo } = props; const userProfileThreadInfo = useUserProfileThreadInfo(userInfo); const usernameText = stringForUserExplicit(userInfo); const [usernameCopied, setUsernameCopied] = React.useState(false); const [ userProfileRelationshipButtonHeight, setUserProfileRelationshipButtonHeight, ] = React.useState(0); const bottomSheetContext = React.useContext(BottomSheetContext); invariant(bottomSheetContext, 'bottomSheetContext should be set'); const { setContentHeight } = bottomSheetContext; const insets = useSafeAreaInsets(); React.useLayoutEffect(() => { - const userInfoContainerHeight = 90; - const bottomPadding = 40; - - let height = insets.bottom + userInfoContainerHeight + bottomPadding; + let height = + insets.bottom + + userProfileUserInfoContainerHeight + + userProfileBottomPadding; if (userProfileThreadInfo) { - const menuButtonHeight = 24; - height += menuButtonHeight; + height += userProfileMenuButtonHeight; } if ( userProfileThreadInfo && !relationshipBlockedInEitherDirection(userInfo?.relationshipStatus) ) { - const messageButtonHeight = 54; - height += messageButtonHeight + userProfileRelationshipButtonHeight; + // message button height + relationship button height + height += + userProfileActionButtonHeight + userProfileRelationshipButtonHeight; } setContentHeight(height); }, [ insets.bottom, setContentHeight, userInfo?.relationshipStatus, userProfileRelationshipButtonHeight, userProfileThreadInfo, ]); const styles = useStyles(unboundStyles); const onPressCopyUsername = React.useCallback(async () => { Clipboard.setString(usernameText); setUsernameCopied(true); await sleep(3000); setUsernameCopied(false); }, [usernameText]); const copyUsernameButton = React.useMemo(() => { if (usernameCopied) { return ( Username copied! ); } return ( Copy username ); }, [ onPressCopyUsername, styles.copyUsernameContainer, styles.copyUsernameIcon, styles.copyUsernameText, usernameCopied, ]); const messageButton = React.useMemo(() => { if ( !userProfileThreadInfo || relationshipBlockedInEitherDirection(userInfo?.relationshipStatus) ) { return null; } const { threadInfo, pendingPersonalThreadUserInfo } = userProfileThreadInfo; return ( ); }, [userInfo?.relationshipStatus, userProfileThreadInfo]); const relationshipButton = React.useMemo(() => { if ( !userProfileThreadInfo || relationshipBlockedInEitherDirection(userInfo?.relationshipStatus) ) { return null; } const { threadInfo, pendingPersonalThreadUserInfo } = userProfileThreadInfo; return ( ); }, [userInfo?.relationshipStatus, userProfileThreadInfo]); return ( {usernameText} {copyUsernameButton} {messageButton} {relationshipButton} ); } const unboundStyles = { container: { paddingHorizontal: 16, }, moreIcon: { color: 'modalButtonLabel', alignSelf: 'flex-end', }, userInfoContainer: { flexDirection: 'row', }, usernameContainer: { flex: 1, justifyContent: 'center', alignItems: 'flex-start', paddingLeft: 16, }, usernameText: { color: 'modalForegroundLabel', fontSize: 18, fontWeight: '500', }, copyUsernameContainer: { flexDirection: 'row', justifyContent: 'center', paddingTop: 8, }, copyUsernameIcon: { color: 'purpleLink', marginRight: 4, }, copyUsernameText: { color: 'purpleLink', fontSize: 12, }, messageButtonContainer: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: 'purpleButton', paddingVertical: 8, marginTop: 16, borderRadius: 8, }, messageButtonIcon: { color: 'floatingButtonLabel', paddingRight: 8, }, messageButtonText: { color: 'floatingButtonLabel', }, }; export default UserProfile;