diff --git a/lib/components/connected-wallet-info.react.js b/lib/components/connected-wallet-info.react.js --- a/lib/components/connected-wallet-info.react.js +++ b/lib/components/connected-wallet-info.react.js @@ -6,7 +6,7 @@ import css from './connected-wallet-info.css'; import SWMansionIcon from './swmansion-icon.react.js'; -import { useENSName } from '../hooks/ens-cache.js'; +import { useENSName } from '../hooks/names-cache.js'; function shortenAddressToFitWidth(address: string): string { if (address.length < 22) { diff --git a/lib/hooks/ens-cache.js b/lib/hooks/names-cache.js rename from lib/hooks/ens-cache.js rename to lib/hooks/names-cache.js --- a/lib/hooks/ens-cache.js +++ b/lib/hooks/names-cache.js @@ -3,10 +3,52 @@ import invariant from 'invariant'; import * as React from 'react'; +import { useFCNames } from './fc-cache.js'; import { ENSCacheContext } from '../components/ens-cache-provider.react.js'; import { getETHAddressForUserInfo } from '../shared/account-utils.js'; -import { stringForUser } from '../shared/user-utils.js'; +import { extractFIDFromUserID } from '../shared/id-utils.js'; +import { stringForUser, stringForUserExplicit } from '../shared/user-utils.js'; import { getENSNames } from '../utils/ens-helpers.js'; +import { useSelector } from '../utils/redux-utils.js'; + +type BaseResolvableUserInfo = { + +id?: ?string, + +fid?: ?string, + +username?: ?string, + +farcasterUsername?: ?string, + ... +}; +type UseResolvableNamesOptions = { + +allAtOnce?: ?boolean, +}; +function useResolvableNames( + users: $ReadOnlyArray, + options?: ?UseResolvableNamesOptions, +): T[] { + const auxUserInfos = useSelector(state => state.auxUserStore.auxUserInfos); + + const usersWithFIDs = React.useMemo( + () => + users.map(user => { + if (!user?.id || user?.fid) { + return user; + } + + const userID = user.id; + const fid = extractFIDFromUserID(userID) ?? auxUserInfos[userID]?.fid; + return { ...user, fid }; + }), + [users, auxUserInfos], + ); + + // We resolve both FC and ENS names to handle Ethereum wallet users with + // connected Farcaster account - they have both `username` (ETH address) + // and `farcasterUsername` present. + const resolvedFCNames = useFCNames(usersWithFIDs, options); + const resolvedFCAndESNNames = useENSNames(resolvedFCNames, options); + + return resolvedFCAndESNNames; +} type BaseUserInfo = { +username?: ?string, ... }; type UseENSNamesOptions = { @@ -136,17 +178,33 @@ return potentiallyENSUser.username; } +function useResolvedUsername( + userInfo: ?BaseResolvableUserInfo, + preferFarcaster?: boolean, +): string { + const [result] = useResolvableNames([userInfo]); + return stringForUserExplicit(result, preferFarcaster); +} + function useStringForUser( - user: ?{ +username?: ?string, +isViewer?: ?boolean, ... }, + user: ?{ + +id?: ?string, + +fid?: ?string, + +username?: ?string, + +farcasterUsername?: ?string, + +isViewer?: boolean, + ... + }, ): ?string { // stringForUser ignores username is isViewer, so we skip the ENS fetch const toFetch = user?.isViewer ? null : user; const usersObjArr = React.useMemo(() => [toFetch], [toFetch]); - const [result] = useENSNames(usersObjArr); + + const [result] = useResolvableNames(usersObjArr); if (user?.isViewer) { return stringForUser(user); } else if (result) { - return stringForUser(result); + return stringForUser({ ...result, isViewer: false }); } else { invariant( !user, @@ -204,7 +262,12 @@ }, [ethAddress, cachedAvatar, ensAvatars]); } -type BaseENSResolvedUser = { +username?: ?string, +isViewer?: ?boolean, ... }; +type BaseENSResolvedUser = { + +username?: ?string, + +farcasterUsername?: ?string, + +isViewer?: ?boolean, + ... +}; function useSortedENSResolvedUsers( userInfos: $ReadOnlyArray, ): $ReadOnlyArray { @@ -225,4 +288,6 @@ useStringForUser, useENSAvatar, useSortedENSResolvedUsers, + useResolvableNames, + useResolvedUsername, }; diff --git a/lib/selectors/nav-selectors.js b/lib/selectors/nav-selectors.js --- a/lib/selectors/nav-selectors.js +++ b/lib/selectors/nav-selectors.js @@ -3,7 +3,7 @@ import * as React from 'react'; import { createSelector } from 'reselect'; -import { useENSNames } from '../hooks/ens-cache.js'; +import { useResolvableNames } from '../hooks/names-cache.js'; import SearchIndex from '../shared/search-index.js'; import { threadTypeIsPrivate } from '../shared/threads/thread-specs.js'; import type { Platform } from '../types/device-types.js'; @@ -76,15 +76,18 @@ ); // Without allAtOnce, useThreadSearchIndex and useUserSearchIndex are very -// expensive. useENSNames would trigger their recalculation for each ENS name -// as it streams in, but we would prefer to trigger their recaculation just -// once for every update of the underlying Redux data. -const useENSNamesOptions = { allAtOnce: true }; +// expensive. useResolvableNames would trigger their recalculation for each +// ENS name as it streams in, but we would prefer to trigger their +// recaculation just once for every update of the underlying Redux data. +const useResolvableNamesOptions = { allAtOnce: true }; function useUserSearchIndex( userInfos: $ReadOnlyArray, ): SearchIndex { - const membersWithENSNames = useENSNames(userInfos, useENSNamesOptions); + const membersWithENSNames = useResolvableNames( + userInfos, + useResolvableNamesOptions, + ); const memberMap = React.useMemo(() => { const result = new Map(); @@ -144,9 +147,9 @@ return [...allMembersOfAllThreads.values()]; }, [threadInfos, userInfos, viewerID]); - const nonViewerMembersWithENSNames = useENSNames( + const nonViewerMembersWithENSNames = useResolvableNames( nonViewerMembers, - useENSNamesOptions, + useResolvableNamesOptions, ); const memberMap = React.useMemo(() => { diff --git a/lib/shared/avatar-utils.js b/lib/shared/avatar-utils.js --- a/lib/shared/avatar-utils.js +++ b/lib/shared/avatar-utils.js @@ -12,11 +12,11 @@ threadTypeIsPrivate, } from './threads/thread-specs.js'; import genesis from '../facts/genesis.js'; -import { useENSAvatar } from '../hooks/ens-cache.js'; import { useFarcasterUserAvatarURL, useFarcasterChannelAvatarURL, } from '../hooks/fc-cache.js'; +import { useENSAvatar } from '../hooks/names-cache.js'; import type { ClientAvatar, ClientEmojiAvatar, diff --git a/lib/shared/markdown.js b/lib/shared/markdown.js --- a/lib/shared/markdown.js +++ b/lib/shared/markdown.js @@ -7,7 +7,7 @@ markdownUserMentionRegex, decodeChatMentionText, } from './mention-utils.js'; -import { useENSNames } from '../hooks/ens-cache.js'; +import { useResolvableNames } from '../hooks/names-cache.js'; import type { RelativeMemberInfo, ResolvedThreadInfo, @@ -199,7 +199,7 @@ }; } -const useENSNamesOptions = { allAtOnce: true }; +const useResolvableNamesOptions = { allAtOnce: true }; function useMemberMapForUserMentions( members: $ReadOnlyArray, ): $ReadOnlyMap { @@ -208,7 +208,10 @@ [members], ); - const resolvedMembers = useENSNames(membersWithRole, useENSNamesOptions); + const resolvedMembers = useResolvableNames( + membersWithRole, + useResolvableNamesOptions, + ); const resolvedMembersMap: $ReadOnlyMap = React.useMemo( () => new Map(resolvedMembers.map(member => [member.id, member])), diff --git a/lib/shared/mention-utils.js b/lib/shared/mention-utils.js --- a/lib/shared/mention-utils.js +++ b/lib/shared/mention-utils.js @@ -6,7 +6,7 @@ import SentencePrefixSearchIndex from './sentence-prefix-search-index.js'; import { threadTypeIsSidebar } from './threads/thread-specs.js'; import { stringForUserExplicit } from './user-utils.js'; -import { useENSNames } from '../hooks/ens-cache.js'; +import { useResolvableNames } from '../hooks/names-cache.js'; import { useUserSearchIndex } from '../selectors/nav-selectors.js'; import type { RelativeMemberInfo, @@ -103,13 +103,16 @@ return null; } -const useENSNamesOptions = { allAtOnce: true }; +const useResolvableNamesOptions = { allAtOnce: true }; function useMentionTypeaheadUserSuggestions( threadMembers: $ReadOnlyArray, typeaheadMatchedStrings: ?TypeaheadMatchedStrings, ): $ReadOnlyArray { const userSearchIndex = useUserSearchIndex(threadMembers); - const resolvedThreadMembers = useENSNames(threadMembers, useENSNamesOptions); + const resolvedThreadMembers = useResolvableNames( + threadMembers, + useResolvableNamesOptions, + ); const usernamePrefix: ?string = typeaheadMatchedStrings?.query; return React.useMemo(() => { diff --git a/lib/shared/message-utils.js b/lib/shared/message-utils.js --- a/lib/shared/message-utils.js +++ b/lib/shared/message-utils.js @@ -13,12 +13,12 @@ fetchMessagesBeforeCursorActionTypes, fetchMostRecentMessagesActionTypes, } from '../actions/message-actions.js'; -import { useStringForUser } from '../hooks/ens-cache.js'; import { useFetchMessagesBeforeCursor, useFetchMostRecentMessages, useOldestMessageServerID, } from '../hooks/message-hooks.js'; +import { useStringForUser } from '../hooks/names-cache.js'; import { extractKeyserverIDFromIDOptional } from '../keyserver-conn/keyserver-call-utils.js'; import { contentStringForMediaArray } from '../media/media-utils.js'; import { registerFetchKey } from '../reducers/loading-reducer.js'; diff --git a/lib/shared/reaction-utils.js b/lib/shared/reaction-utils.js --- a/lib/shared/reaction-utils.js +++ b/lib/shared/reaction-utils.js @@ -9,8 +9,8 @@ import { useThreadHasPermission } from './thread-utils.js'; import { threadSpecs } from './threads/thread-specs.js'; import { stringForUserExplicit } from './user-utils.js'; -import { useENSNames } from '../hooks/ens-cache.js'; import { useSendReactionMessage } from '../hooks/message-hooks.js'; +import { useResolvableNames } from '../hooks/names-cache.js'; import type { ReactionInfo } from '../selectors/chat-selectors.js'; import type { ComposableMessageInfo, @@ -75,7 +75,7 @@ >), )(result); }, [reactions]); - return useENSNames(withoutENSNames); + return useResolvableNames(withoutENSNames); } function useCanCreateReactionFromMessage( diff --git a/lib/shared/user-utils.js b/lib/shared/user-utils.js --- a/lib/shared/user-utils.js +++ b/lib/shared/user-utils.js @@ -3,7 +3,7 @@ import * as React from 'react'; import { roleIsAdminRole } from './thread-utils.js'; -import { useENSNames } from '../hooks/ens-cache.js'; +import { useResolvableNames } from '../hooks/names-cache.js'; import type { ThreadInfo, RawThreadInfo, @@ -18,6 +18,7 @@ function stringForUser( user: ?{ +username?: ?string, + +farcasterUsername?: ?string, +isViewer?: ?boolean, ... }, @@ -29,9 +30,21 @@ return stringForUserExplicit(user); } -function stringForUserExplicit(user: ?{ +username: ?string, ... }): string { +function stringForUserExplicit( + user: ?{ +username: ?string, +farcasterUsername?: ?string, ... }, + preferFarcaster?: boolean, +): string { + const commUsername = user?.username && user.username !== 'anonymous'; + const farcasterUsername = user?.farcasterUsername; + + if ((preferFarcaster || !commUsername) && farcasterUsername) { + return ensNameForFarcasterUsername(farcasterUsername); + } + if (user?.username) { return user.username; + } else if (farcasterUsername) { + return ensNameForFarcasterUsername(farcasterUsername); } return 'anonymous'; @@ -48,7 +61,7 @@ ); const adminUserInfo = admin ? userInfos[admin.id] : undefined; const adminUserInfos = React.useMemo(() => [adminUserInfo], [adminUserInfo]); - const [adminUserInfoWithENSName] = useENSNames(adminUserInfos); + const [adminUserInfoWithENSName] = useResolvableNames(adminUserInfos); return adminUserInfoWithENSName; } diff --git a/lib/utils/entity-text.js b/lib/utils/entity-text.js --- a/lib/utils/entity-text.js +++ b/lib/utils/entity-text.js @@ -7,8 +7,8 @@ import type { GetENSNames } from './ens-helpers.js'; import type { GetFCNames } from './farcaster-helpers.js'; import { tID, tShape, tString, tUserID } from './validation-utils.js'; -import { useENSNames } from '../hooks/ens-cache.js'; import { useFCNames } from '../hooks/fc-cache.js'; +import { useResolvableNames } from '../hooks/names-cache.js'; import { threadNoun } from '../shared/thread-utils.js'; import { stringForUser } from '../shared/user-utils.js'; import type { @@ -589,7 +589,7 @@ () => (entityText ? entityTextToObjects(entityText) : []), [entityText], ); - const objectsWithENSNames = useENSNames(allObjects, options); + const objectsWithENSNames = useResolvableNames(allObjects, options); const objectsWithFCNames = useFCNames(allObjects, options); return React.useMemo(() => { if (!entityText) { diff --git a/lib/utils/role-utils.js b/lib/utils/role-utils.js --- a/lib/utils/role-utils.js +++ b/lib/utils/role-utils.js @@ -5,7 +5,7 @@ import * as React from 'react'; import { useSelector } from './redux-utils.js'; -import { useSortedENSResolvedUsers } from '../hooks/ens-cache.js'; +import { useSortedENSResolvedUsers } from '../hooks/names-cache.js'; import { threadInfoSelector } from '../selectors/thread-selectors.js'; import type { RelativeMemberInfo, diff --git a/native/account/registration/existing-ethereum-account.react.js b/native/account/registration/existing-ethereum-account.react.js --- a/native/account/registration/existing-ethereum-account.react.js +++ b/native/account/registration/existing-ethereum-account.react.js @@ -9,8 +9,8 @@ import * as React from 'react'; import { Text, View } from 'react-native'; -import { useENSName } from 'lib/hooks/ens-cache.js'; import { useWalletLogIn } from 'lib/hooks/login-hooks.js'; +import { useENSName } from 'lib/hooks/names-cache.js'; import type { SIWEBackupData } from 'lib/types/backup-types.js'; import type { SIWEResult } from 'lib/types/siwe-types.js'; import { getMessageForException } from 'lib/utils/errors.js'; diff --git a/native/avatars/edit-user-avatar.react.js b/native/avatars/edit-user-avatar.react.js --- a/native/avatars/edit-user-avatar.react.js +++ b/native/avatars/edit-user-avatar.react.js @@ -6,8 +6,8 @@ import { ActivityIndicator, TouchableOpacity, View } from 'react-native'; import { EditUserAvatarContext } from 'lib/components/edit-user-avatar-provider.react.js'; -import { useENSAvatar } from 'lib/hooks/ens-cache.js'; import { useFarcasterUserAvatarURL } from 'lib/hooks/fc-cache.js'; +import { useENSAvatar } from 'lib/hooks/names-cache.js'; import { getETHAddressForUserInfo } from 'lib/shared/account-utils.js'; import type { GenericUserInfoWithAvatar } from 'lib/types/avatar-types.js'; diff --git a/native/chat/compose-subchannel.react.js b/native/chat/compose-subchannel.react.js --- a/native/chat/compose-subchannel.react.js +++ b/native/chat/compose-subchannel.react.js @@ -8,7 +8,7 @@ import { Text, View } from 'react-native'; import { newThreadActionTypes } from 'lib/actions/thread-action-types.js'; -import { useENSNames } from 'lib/hooks/ens-cache.js'; +import { useResolvableNames } from 'lib/hooks/names-cache.js'; import { useNewThinThread } from 'lib/hooks/thread-hooks.js'; import { threadInfoSelector } from 'lib/selectors/thread-selectors.js'; import { userInfoSelectorForPotentialMembers } from 'lib/selectors/user-selectors.js'; @@ -280,8 +280,8 @@ }), [onPressCreateThread], ); - const userSearchResultWithENSNames = useENSNames(userSearchResults); - const userInfoInputArrayWithENSNames = useENSNames(userInfoInputArray); + const userSearchResultWithENSNames = useResolvableNames(userSearchResults); + const userInfoInputArrayWithENSNames = useResolvableNames(userInfoInputArray); return ( @@ -118,7 +118,8 @@ userSelectionAdditionalStyles = null; } - const userInfoInputArrayWithENSNames = useENSNames(userInfoInputArray); + const userInfoInputArrayWithENSNames = + useResolvableNames(userInfoInputArray); return ( <> diff --git a/native/chat/settings/add-users-modal.react.js b/native/chat/settings/add-users-modal.react.js --- a/native/chat/settings/add-users-modal.react.js +++ b/native/chat/settings/add-users-modal.react.js @@ -4,7 +4,7 @@ import { ActivityIndicator, Text, View } from 'react-native'; import { changeThreadSettingsActionTypes } from 'lib/actions/thread-action-types.js'; -import { useENSNames } from 'lib/hooks/ens-cache.js'; +import { useResolvableNames } from 'lib/hooks/names-cache.js'; import { useChangeThreadSettings } from 'lib/hooks/thread-hooks.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import { threadInfoSelector } from 'lib/selectors/thread-selectors.js'; @@ -229,8 +229,8 @@ }), [onPressAdd], ); - const userSearchResultWithENSNames = useENSNames(userSearchResults); - const userInfoInputArrayWithENSNames = useENSNames(userInfoInputArray); + const userSearchResultWithENSNames = useResolvableNames(userSearchResults); + const userInfoInputArrayWithENSNames = useResolvableNames(userInfoInputArray); return ( [otherUserInfoFromRedux], [otherUserInfoFromRedux], ); - const [otherUserInfo] = useENSNames(ensNames); + const [otherUserInfo] = useResolvableNames(ensNames); const updateRelationships = useUpdateRelationships(); const updateRelationship = React.useCallback( diff --git a/native/chat/settings/thread-settings-member.react.js b/native/chat/settings/thread-settings-member.react.js --- a/native/chat/settings/thread-settings-member.react.js +++ b/native/chat/settings/thread-settings-member.react.js @@ -14,7 +14,7 @@ changeThreadMemberRolesActionTypes, removeUsersFromThreadActionTypes, } from 'lib/actions/thread-action-types.js'; -import { useENSNames } from 'lib/hooks/ens-cache.js'; +import { useResolvableNames } from 'lib/hooks/names-cache.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import { useAvailableThreadMemberActions } from 'lib/shared/thread-utils.js'; import { stringForUser } from 'lib/shared/user-utils.js'; @@ -257,7 +257,7 @@ )(state), ); - const [memberInfo] = useENSNames([props.memberInfo]); + const [memberInfo] = useResolvableNames([props.memberInfo]); const colors = useColors(); const styles = useStyles(unboundStyles); diff --git a/native/profile/profile-screen.react.js b/native/profile/profile-screen.react.js --- a/native/profile/profile-screen.react.js +++ b/native/profile/profile-screen.react.js @@ -11,7 +11,7 @@ usePrimaryDeviceLogOut, useSecondaryDeviceLogOut, } from 'lib/actions/user-actions.js'; -import { useStringForUser } from 'lib/hooks/ens-cache.js'; +import { useStringForUser } from 'lib/hooks/names-cache.js'; import { useCheckIfPrimaryDevice } from 'lib/hooks/primary-device-hooks.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import { accountHasPassword } from 'lib/shared/account-utils.js'; diff --git a/native/profile/relationship-list.react.js b/native/profile/relationship-list.react.js --- a/native/profile/relationship-list.react.js +++ b/native/profile/relationship-list.react.js @@ -6,7 +6,7 @@ import { FlatList } from 'react-native-gesture-handler'; import { updateRelationshipsActionTypes } from 'lib/actions/relationship-actions.js'; -import { useENSNames } from 'lib/hooks/ens-cache.js'; +import { useResolvableNames } from 'lib/hooks/names-cache.js'; import { useUpdateRelationships } from 'lib/hooks/relationship-hooks.js'; import { registerFetchKey } from 'lib/reducers/loading-reducer.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; @@ -389,7 +389,7 @@ userInfos, ]); - const displayUsers = useENSNames(usersWithoutENSNames); + const displayUsers = useResolvableNames(usersWithoutENSNames); const listData = React.useMemo(() => { let emptyItem; if (displayUsers.length === 0 && searchInputText === '') { @@ -413,7 +413,7 @@ }, [displayUsers, verticalBounds, searchInputText]); const indicatorStyle = useIndicatorStyle(); - const currentTagsWithENSNames = useENSNames(currentTags); + const currentTagsWithENSNames = useResolvableNames(currentTags); return ( diff --git a/native/user-profile/user-profile.react.js b/native/user-profile/user-profile.react.js --- a/native/user-profile/user-profile.react.js +++ b/native/user-profile/user-profile.react.js @@ -6,10 +6,9 @@ import { View, Text, TouchableOpacity } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; -import { useENSName } from 'lib/hooks/ens-cache.js'; +import { useResolvedUsername } from 'lib/hooks/names-cache.js'; 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'; @@ -36,8 +35,7 @@ const userProfileThreadInfo = useUserProfileThreadInfo(userInfo); - const usernameText = stringForUserExplicit(userInfo); - const resolvedUsernameText = useENSName(usernameText); + const resolvedUsernameText = useResolvedUsername(userInfo); const [usernameCopied, setUsernameCopied] = React.useState(false); diff --git a/web/avatars/edit-user-avatar-menu.react.js b/web/avatars/edit-user-avatar-menu.react.js --- a/web/avatars/edit-user-avatar-menu.react.js +++ b/web/avatars/edit-user-avatar-menu.react.js @@ -6,8 +6,8 @@ import { EditUserAvatarContext } from 'lib/components/edit-user-avatar-provider.react.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/swmansion-icon.react.js'; -import { useENSAvatar } from 'lib/hooks/ens-cache.js'; import { useFarcasterUserAvatarURL } from 'lib/hooks/fc-cache.js'; +import { useENSAvatar } from 'lib/hooks/names-cache.js'; import { getETHAddressForUserInfo } from 'lib/shared/account-utils.js'; import { useCurrentUserFID } from 'lib/utils/farcaster-utils.js'; diff --git a/web/chat/chat-thread-composer.react.js b/web/chat/chat-thread-composer.react.js --- a/web/chat/chat-thread-composer.react.js +++ b/web/chat/chat-thread-composer.react.js @@ -8,7 +8,7 @@ import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/swmansion-icon.react.js'; import { useLoggedInUserInfo } from 'lib/hooks/account-hooks.js'; -import { useENSNames } from 'lib/hooks/ens-cache.js'; +import { useResolvableNames } from 'lib/hooks/names-cache.js'; import { useUsersSupportFarcasterDCs, useUsersSupportThickThreads, @@ -83,7 +83,7 @@ includeServerSearchUsers: searchResults, }); - const userListItemsWithENSNames = useENSNames(userListItems); + const userListItemsWithENSNames = useResolvableNames(userListItems); const { pushModal } = useModalContext(); @@ -242,7 +242,7 @@ hideSearch('reset-active-thread-if-pending'); }, [hideSearch]); - const userInfoInputArrayWithENSNames = useENSNames(userInfoInputArray); + const userInfoInputArrayWithENSNames = useResolvableNames(userInfoInputArray); const tagsList = React.useMemo(() => { if (!userInfoInputArrayWithENSNames?.length) { return null; diff --git a/web/chat/composed-message.react.js b/web/chat/composed-message.react.js --- a/web/chat/composed-message.react.js +++ b/web/chat/composed-message.react.js @@ -8,7 +8,7 @@ XCircle as XCircleIcon, } from 'react-feather'; -import { useStringForUser } from 'lib/hooks/ens-cache.js'; +import { useStringForUser } from 'lib/hooks/names-cache.js'; import { type ComposableChatMessageInfoItem } from 'lib/selectors/chat-selectors.js'; import { chatMessageItemHasEngagement } from 'lib/shared/chat-message-item-utils.js'; import { getMessageLabel } from 'lib/shared/edit-messages-utils.js'; diff --git a/web/components/message-result.react.js b/web/components/message-result.react.js --- a/web/components/message-result.react.js +++ b/web/components/message-result.react.js @@ -4,7 +4,7 @@ import * as React from 'react'; import { useThreadChatMentionCandidates } from 'lib/hooks/chat-mention-hooks.js'; -import { useStringForUser } from 'lib/hooks/ens-cache.js'; +import { useStringForUser } from 'lib/hooks/names-cache.js'; import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js'; import { chatMessageInfoItemTimestamp } from 'lib/shared/chat-message-item-utils.js'; import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; diff --git a/web/modals/history/history-entry.react.js b/web/modals/history/history-entry.react.js --- a/web/modals/history/history-entry.react.js +++ b/web/modals/history/history-entry.react.js @@ -8,7 +8,7 @@ restoreEntryActionTypes, useRestoreEntry, } from 'lib/actions/entry-actions.js'; -import { useENSNames } from 'lib/hooks/ens-cache.js'; +import { useResolvableNames } from 'lib/hooks/names-cache.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import { threadInfoSelector } from 'lib/selectors/thread-selectors.js'; import { colorIsDark } from 'lib/shared/color-utils.js'; @@ -169,7 +169,7 @@ const dispatchActionPromise = useDispatchActionPromise(); const { creator } = props.entryInfo; - const [creatorWithENSName] = useENSNames([creator]); + const [creatorWithENSName] = useResolvableNames([creator]); return ( [authorUserInfo], [authorUserInfo], ); - const [authorWithENSName] = useENSNames(authorUserInfos); + const [authorWithENSName] = useResolvableNames(authorUserInfos); const author = authorWithENSName?.username ? ( {authorWithENSName.username} diff --git a/web/modals/threads/members/members-list.react.js b/web/modals/threads/members/members-list.react.js --- a/web/modals/threads/members/members-list.react.js +++ b/web/modals/threads/members/members-list.react.js @@ -5,7 +5,7 @@ import _toPairs from 'lodash/fp/toPairs.js'; import * as React from 'react'; -import { useENSNames } from 'lib/hooks/ens-cache.js'; +import { useResolvableNames } from 'lib/hooks/names-cache.js'; import { stringForUser } from 'lib/shared/user-utils.js'; import type { RelativeMemberInfo, @@ -25,7 +25,7 @@ const [openMenu, setOpenMenu] = React.useState(null); const hasMembers = threadMembers.length > 0; - const threadMembersWithENSNames = useENSNames(threadMembers); + const threadMembersWithENSNames = useResolvableNames(threadMembers); const groupedByFirstLetterMembers = React.useMemo( () => diff --git a/web/modals/threads/settings/thread-settings-relationship-tab.react.js b/web/modals/threads/settings/thread-settings-relationship-tab.react.js --- a/web/modals/threads/settings/thread-settings-relationship-tab.react.js +++ b/web/modals/threads/settings/thread-settings-relationship-tab.react.js @@ -2,7 +2,7 @@ import * as React from 'react'; -import { useENSNames } from 'lib/hooks/ens-cache.js'; +import { useResolvableNames } from 'lib/hooks/names-cache.js'; import { type SetState } from 'lib/types/hook-types.js'; import { type RelationshipButton } from 'lib/types/relationship-types.js'; import type { UserInfo } from 'lib/types/user-types.js'; @@ -19,7 +19,7 @@ function ThreadSettingsRelationshipTab(props: Props): React.Node { const { relationshipButtons, otherUserInfo, setErrorMessage } = props; const userInfos = React.useMemo(() => [otherUserInfo], [otherUserInfo]); - const [otherUserInfoWithENSName] = useENSNames(userInfos); + const [otherUserInfoWithENSName] = useResolvableNames(userInfos); const buttons = React.useMemo( () => relationshipButtons.map(action => ( diff --git a/web/modals/user-profile/user-profile.react.js b/web/modals/user-profile/user-profile.react.js --- a/web/modals/user-profile/user-profile.react.js +++ b/web/modals/user-profile/user-profile.react.js @@ -4,9 +4,8 @@ import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/swmansion-icon.react.js'; -import { useENSName } from 'lib/hooks/ens-cache.js'; +import { useResolvedUsername } from 'lib/hooks/names-cache.js'; import { relationshipBlockedInEitherDirection } from 'lib/shared/relationship-utils.js'; -import { stringForUserExplicit } from 'lib/shared/user-utils.js'; import type { UserProfileThreadInfo } from 'lib/types/thread-types'; import type { UserInfo } from 'lib/types/user-types'; import sleep from 'lib/utils/sleep.js'; @@ -27,8 +26,7 @@ const { pushModal } = useModalContext(); - const usernameText = stringForUserExplicit(userInfo); - const resolvedUsernameText = useENSName(usernameText); + const resolvedUsernameText = useResolvedUsername(userInfo); const [usernameCopied, setUsernameCopied] = React.useState(false); diff --git a/web/settings/account-settings.react.js b/web/settings/account-settings.react.js --- a/web/settings/account-settings.react.js +++ b/web/settings/account-settings.react.js @@ -11,7 +11,7 @@ } from 'lib/actions/user-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/swmansion-icon.react.js'; -import { useStringForUser } from 'lib/hooks/ens-cache.js'; +import { useStringForUser } from 'lib/hooks/names-cache.js'; import { useCheckIfPrimaryDevice } from 'lib/hooks/primary-device-hooks.js'; import { dmOperationSpecificationTypes, diff --git a/web/settings/relationship/add-users-list-item.react.js b/web/settings/relationship/add-users-list-item.react.js --- a/web/settings/relationship/add-users-list-item.react.js +++ b/web/settings/relationship/add-users-list-item.react.js @@ -10,6 +10,7 @@ export type BaseAddUserInfo = { +id: string, +username?: ?string, + +farcasterUsername?: ?string, +isViewer?: ?boolean, ... }; diff --git a/web/settings/relationship/add-users-list.react.js b/web/settings/relationship/add-users-list.react.js --- a/web/settings/relationship/add-users-list.react.js +++ b/web/settings/relationship/add-users-list.react.js @@ -2,7 +2,7 @@ import * as React from 'react'; -import { useSortedENSResolvedUsers } from 'lib/hooks/ens-cache.js'; +import { useSortedENSResolvedUsers } from 'lib/hooks/names-cache.js'; import { stringForUser } from 'lib/shared/user-utils.js'; import AddUsersListItem, { diff --git a/web/settings/relationship/add-users-utils.js b/web/settings/relationship/add-users-utils.js --- a/web/settings/relationship/add-users-utils.js +++ b/web/settings/relationship/add-users-utils.js @@ -3,7 +3,7 @@ import _keyBy from 'lodash/fp/keyBy.js'; import * as React from 'react'; -import { useSortedENSResolvedUsers } from 'lib/hooks/ens-cache.js'; +import { useSortedENSResolvedUsers } from 'lib/hooks/names-cache.js'; import { useUserSearchIndex } from 'lib/selectors/nav-selectors.js'; import { threadInfoSelector } from 'lib/selectors/thread-selectors.js'; import { userInfoSelectorForPotentialMembers } from 'lib/selectors/user-selectors.js'; diff --git a/web/settings/relationship/user-list.react.js b/web/settings/relationship/user-list.react.js --- a/web/settings/relationship/user-list.react.js +++ b/web/settings/relationship/user-list.react.js @@ -3,7 +3,7 @@ import classNames from 'classnames'; import * as React from 'react'; -import { useENSNames } from 'lib/hooks/ens-cache.js'; +import { useResolvableNames } from 'lib/hooks/names-cache.js'; import { useUserSearchIndex } from 'lib/selectors/nav-selectors.js'; import type { AccountUserInfo, UserInfo } from 'lib/types/user-types.js'; import { values } from 'lib/utils/objects.js'; @@ -59,7 +59,7 @@ } return matchedUserInfos.sort(usersComparator); }, [userInfosArray, searchResult, searchText, userInfos, usersComparator]); - const usersWithENSNames = useENSNames(users); + const usersWithENSNames = useResolvableNames(users); const userRows = React.useMemo(() => { const UserRow = userRowComponent; diff --git a/web/tooltips/tooltip-action-utils.js b/web/tooltips/tooltip-action-utils.js --- a/web/tooltips/tooltip-action-utils.js +++ b/web/tooltips/tooltip-action-utils.js @@ -6,7 +6,7 @@ import * as React from 'react'; import { useModalContext } from 'lib/components/modal-provider.react.js'; -import { useENSNames } from 'lib/hooks/ens-cache.js'; +import { useResolvableNames } from 'lib/hooks/names-cache.js'; import { useResettingState } from 'lib/hooks/use-resetting-state.js'; import type { ChatMessageInfoItem, @@ -515,7 +515,7 @@ }; } -const useENSNamesOptions = { allAtOnce: true }; +const useResolvableNamesOptions = { allAtOnce: true }; type UseReactionTooltipArgs = { +reaction: string, @@ -530,7 +530,7 @@ }: UseReactionTooltipArgs): UseTooltipResult { const { users } = reactions[reaction]; - const resolvedUsers = useENSNames(users, useENSNamesOptions); + const resolvedUsers = useResolvableNames(users, useResolvableNamesOptions); const showSeeMoreText = resolvedUsers.length > 5;