diff --git a/lib/shared/user-utils.js b/lib/shared/user-utils.js index f4389918c..05c245c8f 100644 --- a/lib/shared/user-utils.js +++ b/lib/shared/user-utils.js @@ -1,46 +1,48 @@ // @flow import { memberHasAdminPowers } from './thread-utils.js'; import { useENSNames } from '../hooks/ens-cache.js'; import type { RawThreadInfo, ServerThreadInfo, ThreadInfo, } from '../types/thread-types.js'; import type { UserInfo } from '../types/user-types.js'; import { useSelector } from '../utils/redux-utils.js'; -function stringForUser(user: { - +username?: ?string, - +isViewer?: ?boolean, - ... -}): string { - if (user.isViewer) { +function stringForUser( + user: ?{ + +username?: ?string, + +isViewer?: ?boolean, + ... + }, +): string { + if (user?.isViewer) { return 'you'; } return stringForUserExplicit(user); } -function stringForUserExplicit(user: { +username: ?string, ... }): string { - if (user.username) { +function stringForUserExplicit(user: ?{ +username: ?string, ... }): string { + if (user?.username) { return user.username; - } else { - return 'anonymous'; } + + return 'anonymous'; } function useKeyserverAdmin( community: ThreadInfo | RawThreadInfo | ServerThreadInfo, ): ?UserInfo { const userInfos = useSelector(state => state.userStore.userInfos); // This hack only works as long as there is only one admin // Linear task to revert this: // https://linear.app/comm/issue/ENG-1707/revert-fix-getting-the-keyserver-admin-info const admin = community.members.find(memberHasAdminPowers); const adminUserInfo = admin ? userInfos[admin.id] : undefined; const [adminUserInfoWithENSName] = useENSNames([adminUserInfo]); return adminUserInfoWithENSName; } export { stringForUser, stringForUserExplicit, useKeyserverAdmin }; diff --git a/native/bottom-sheets/user-profile-bottom-sheet.react.js b/native/bottom-sheets/user-profile-bottom-sheet.react.js index bde5e361a..97eb3e515 100644 --- a/native/bottom-sheets/user-profile-bottom-sheet.react.js +++ b/native/bottom-sheets/user-profile-bottom-sheet.react.js @@ -1,52 +1,57 @@ // @flow import * as React from 'react'; -import type { AccountUserInfo } from 'lib/types/user-types.js'; +import type { UserInfo } from 'lib/types/user-types'; import BottomSheet from './bottom-sheet.react.js'; import UserProfile from '../components/user-profile.react.js'; import type { RootNavigationProp } from '../navigation/root-navigator.react.js'; import type { NavigationRoute } from '../navigation/route-names.js'; +import { useSelector } from '../redux/redux-utils.js'; export type UserProfileBottomSheetParams = { - +userInfo: AccountUserInfo, + +userID: string, }; type Props = { +navigation: RootNavigationProp<'UserProfileBottomSheet'>, +route: NavigationRoute<'UserProfileBottomSheet'>, }; function UserProfileBottomSheet(props: Props): React.Node { const { navigation, route: { - params: { userInfo }, + params: { userID }, }, } = props; const { goBackOnce } = navigation; + const userInfo: ?UserInfo = useSelector( + state => state.userStore.userInfos[userID], + ); + const bottomSheetRef = React.useRef(); React.useEffect(() => { if (!bottomSheetRef.current) { return; } bottomSheetRef.current.present(); }, []); const onClosed = React.useCallback(() => { goBackOnce(); }, [goBackOnce]); return ( ); } export default UserProfileBottomSheet; diff --git a/native/components/user-profile.react.js b/native/components/user-profile.react.js index 3822029a8..4ce19b26f 100644 --- a/native/components/user-profile.react.js +++ b/native/components/user-profile.react.js @@ -1,118 +1,118 @@ // @flow import Clipboard from '@react-native-clipboard/clipboard'; import * as React from 'react'; import { View, Text, TouchableOpacity } from 'react-native'; import { stringForUserExplicit } from 'lib/shared/user-utils.js'; import type { UserInfo } from 'lib/types/user-types'; import sleep from 'lib/utils/sleep.js'; import SWMansionIcon from './swmansion-icon.react.js'; import UserAvatar from '../avatars/user-avatar.react.js'; import SingleLine from '../components/single-line.react.js'; import { useStyles } from '../themes/colors.js'; type Props = { - +userInfo: UserInfo, + +userInfo: ?UserInfo, }; function UserProfile(props: Props): React.Node { const { userInfo } = props; const usernameText = stringForUserExplicit(userInfo); const [usernameCopied, setUsernameCopied] = React.useState(false); 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, ]); return ( - + {usernameText} {copyUsernameButton} ); } 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, }, }; export default UserProfile;