diff --git a/lib/shared/search-utils.js b/lib/shared/search-utils.js --- a/lib/shared/search-utils.js +++ b/lib/shared/search-utils.js @@ -19,6 +19,7 @@ } from '../actions/user-actions.js'; import { ENSCacheContext } from '../components/ens-cache-provider.react.js'; import genesis from '../facts/genesis.js'; +import { useIdentitySearch } from '../identity-search/identity-search-context.js'; import type { ChatMessageInfoItem, MessageListData, @@ -40,6 +41,7 @@ import { values } from '../utils/objects.js'; import { useDispatchActionPromise } from '../utils/redux-promise-utils.js'; import { useSelector } from '../utils/redux-utils.js'; +import { usingCommServicesAccessToken } from '../utils/services-utils.js'; const notFriendNotice = 'not friend'; @@ -377,36 +379,61 @@ ); const forwardLookupSearchText = useForwardLookupSearchText(usernameInputText); - const [serverSearchResults, setServerSearchResults] = React.useState< + const [searchResults, setSearchResults] = React.useState< $ReadOnlyArray<GlobalAccountUserInfo>, >([]); - const callSearchUsers = useLegacyAshoatKeyserverCall(searchUsers); + const setSearchResultsFromServer = React.useCallback( + (userInfos: $ReadOnlyArray<GlobalAccountUserInfo>) => { + setSearchResults(userInfos.filter(({ id }) => id !== currentUserID)); + }, + [currentUserID], + ); + + const callLegacyAshoatKeyserverSearchUsers = + useLegacyAshoatKeyserverCall(searchUsers); + const { + connected: identitySearchSocketConnected, + sendPrefixQuery: callIdentitySearchUsers, + } = useIdentitySearch(); + const dispatchActionPromise = useDispatchActionPromise(); + React.useEffect(() => { if (forwardLookupSearchText.length === 0) { - setServerSearchResults([]); + setSearchResults([]); return; } - const searchUsersPromise = (async () => { - try { - const { userInfos } = await callSearchUsers(forwardLookupSearchText); - setServerSearchResults( - userInfos.filter(({ id }) => id !== currentUserID), - ); - } catch (err) { - setServerSearchResults([]); + if (usingCommServicesAccessToken && identitySearchSocketConnected) { + try { + const identitySearchResult = await callIdentitySearchUsers( + forwardLookupSearchText, + ); + const userInfos = identitySearchResult.map(user => ({ + id: user.userID, + username: user.username, + avatar: null, + })); + setSearchResultsFromServer(userInfos); + return; + } catch (err) { + console.error(err); + } } + const { userInfos: keyserverSearchResult } = + await callLegacyAshoatKeyserverSearchUsers(forwardLookupSearchText); + setSearchResultsFromServer(keyserverSearchResult); })(); void dispatchActionPromise(searchUsersActionTypes, searchUsersPromise); }, [ - callSearchUsers, - currentUserID, + setSearchResultsFromServer, + callLegacyAshoatKeyserverSearchUsers, + callIdentitySearchUsers, + identitySearchSocketConnected, dispatchActionPromise, forwardLookupSearchText, ]); - - return serverSearchResults; + return searchResults; } function filterChatMessageInfosForSearch( diff --git a/native/root.react.js b/native/root.react.js --- a/native/root.react.js +++ b/native/root.react.js @@ -31,6 +31,7 @@ import { MediaCacheProvider } from 'lib/components/media-cache-provider.react.js'; import PrekeysHandler from 'lib/components/prekeys-handler.react.js'; import { StaffContextProvider } from 'lib/components/staff-provider.react.js'; +import { IdentitySearchProvider } from 'lib/identity-search/identity-search-context.js'; import { CallKeyserverEndpointProvider } from 'lib/keyserver-conn/call-keyserver-endpoint-provider.react.js'; import { TunnelbrokerProvider } from 'lib/tunnelbroker/tunnelbroker-context.js'; import { actionLogger } from 'lib/utils/action-logger.js'; @@ -304,56 +305,60 @@ <IdentityServiceContextProvider> <OlmSessionCreatorProvider> <TunnelbrokerProvider initMessage={tunnelbrokerInitMessage}> - <FeatureFlagsProvider> - <NavContext.Provider value={navContext}> - <RootContext.Provider value={rootContext}> - <InputStateContainer> - <MessageEditingContextProvider> - <SafeAreaProvider initialMetrics={initialWindowMetrics}> - <ActionSheetProvider> - <ENSCacheProvider provider={provider}> - <MediaCacheProvider - persistence={filesystemMediaCache} - > - <EditUserAvatarProvider> - <NativeEditThreadAvatarProvider> - <MarkdownContextProvider> - <MessageSearchProvider> - <BottomSheetProvider> - <RegistrationContextProvider> - <SQLiteDataHandler /> - <ConnectedStatusBar /> - <ReduxPersistGate - persistor={getPersistor()} - > - {gated} - </ReduxPersistGate> - <PersistedStateGate> - <KeyserverConnectionsHandler - socketComponent={Socket} - detectUnsupervisedBackgroundRef={ - detectUnsupervisedBackgroundRef - } - /> - <VersionSupportedChecker /> - <PrekeysHandler /> - </PersistedStateGate> - {navigation} - </RegistrationContextProvider> - </BottomSheetProvider> - </MessageSearchProvider> - </MarkdownContextProvider> - </NativeEditThreadAvatarProvider> - </EditUserAvatarProvider> - </MediaCacheProvider> - </ENSCacheProvider> - </ActionSheetProvider> - </SafeAreaProvider> - </MessageEditingContextProvider> - </InputStateContainer> - </RootContext.Provider> - </NavContext.Provider> - </FeatureFlagsProvider> + <IdentitySearchProvider> + <FeatureFlagsProvider> + <NavContext.Provider value={navContext}> + <RootContext.Provider value={rootContext}> + <InputStateContainer> + <MessageEditingContextProvider> + <SafeAreaProvider + initialMetrics={initialWindowMetrics} + > + <ActionSheetProvider> + <ENSCacheProvider provider={provider}> + <MediaCacheProvider + persistence={filesystemMediaCache} + > + <EditUserAvatarProvider> + <NativeEditThreadAvatarProvider> + <MarkdownContextProvider> + <MessageSearchProvider> + <BottomSheetProvider> + <RegistrationContextProvider> + <SQLiteDataHandler /> + <ConnectedStatusBar /> + <ReduxPersistGate + persistor={getPersistor()} + > + {gated} + </ReduxPersistGate> + <PersistedStateGate> + <KeyserverConnectionsHandler + socketComponent={Socket} + detectUnsupervisedBackgroundRef={ + detectUnsupervisedBackgroundRef + } + /> + <VersionSupportedChecker /> + <PrekeysHandler /> + </PersistedStateGate> + {navigation} + </RegistrationContextProvider> + </BottomSheetProvider> + </MessageSearchProvider> + </MarkdownContextProvider> + </NativeEditThreadAvatarProvider> + </EditUserAvatarProvider> + </MediaCacheProvider> + </ENSCacheProvider> + </ActionSheetProvider> + </SafeAreaProvider> + </MessageEditingContextProvider> + </InputStateContainer> + </RootContext.Provider> + </NavContext.Provider> + </FeatureFlagsProvider> + </IdentitySearchProvider> </TunnelbrokerProvider> </OlmSessionCreatorProvider> </IdentityServiceContextProvider> diff --git a/web/app.react.js b/web/app.react.js --- a/web/app.react.js +++ b/web/app.react.js @@ -21,6 +21,7 @@ useModalContext, } from 'lib/components/modal-provider.react.js'; import { StaffContextProvider } from 'lib/components/staff-provider.react.js'; +import { IdentitySearchProvider } from 'lib/identity-search/identity-search-context.js'; import { createLoadingStatusSelector, combineLoadingStatuses, @@ -408,15 +409,17 @@ return ( <AppThemeWrapper> <TunnelbrokerProvider initMessage={tunnelbrokerInitMessage}> - <App - {...props} - navInfo={navInfo} - entriesLoadingStatus={entriesLoadingStatus} - loggedIn={loggedIn} - activeThreadCurrentlyUnread={activeThreadCurrentlyUnread} - dispatch={dispatch} - modals={modals} - /> + <IdentitySearchProvider> + <App + {...props} + navInfo={navInfo} + entriesLoadingStatus={entriesLoadingStatus} + loggedIn={loggedIn} + activeThreadCurrentlyUnread={activeThreadCurrentlyUnread} + dispatch={dispatch} + modals={modals} + /> + </IdentitySearchProvider> </TunnelbrokerProvider> </AppThemeWrapper> ); 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 @@ -55,13 +55,13 @@ [userInfoInputArray], ); - const serverSearchResults = useSearchUsers(usernameInputText); + const searchResults = useSearchUsers(usernameInputText); const userListItems = usePotentialMemberItems({ text: usernameInputText, userInfos: otherUserInfos, excludeUserIDs: userInfoInputIDs, - includeServerSearchUsers: serverSearchResults, + includeServerSearchUsers: searchResults, }); const userListItemsWithENSNames = useENSNames(userListItems);