Update search input with useAutocomplete (#11023)

This commit is contained in:
DS Boyce
2026-06-30 10:34:17 -07:00
committed by GitHub
parent 6607118729
commit 298c83bcba
9 changed files with 285 additions and 91 deletions
+57 -16
View File
@@ -23,7 +23,6 @@ import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
import {MagnifyingGlassIcon} from '#/lib/icons'
import {type NavigationProp, type SearchParams} from '#/lib/routes/types'
import {listenSoftReset} from '#/state/events'
import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
import {
unstableCacheProfileView,
useProfilesQuery,
@@ -43,8 +42,8 @@ import {
} from '#/screens/Search/searchParams'
import {makeSearchQuery} from '#/screens/Search/utils'
import {atoms as a, tokens, useBreakpoints, useTheme, web} from '#/alf'
import {useAutocomplete} from '#/components/Autocomplete'
import {Button, ButtonIcon} from '#/components/Button'
import {SearchInput} from '#/components/forms/SearchInput'
import {ArrowLeft_Stroke2_Corner0_Rounded as ArrowLeftIcon} from '#/components/icons/Arrow'
import {ArrowShareRight_Stroke2_Corner2_Rounded as ShareIcon} from '#/components/icons/ArrowShareRight'
import * as Layout from '#/components/Layout'
@@ -57,6 +56,7 @@ import type * as bsky from '#/types/bsky'
import {AdvancedSearchDialog} from './components/AdvancedSearchDialog'
import {AutocompleteResults} from './components/AutocompleteResults'
import {DetectedLanguagesAdmonition} from './components/DetectedLanguagesAdmonition'
import {SearchAutocompleteInput} from './components/SearchAutocompleteInput'
import {SearchHistory} from './components/SearchHistory'
import {SearchLanguageDropdown} from './components/SearchLanguageDropdown'
import {Explore} from './Explore'
@@ -125,8 +125,16 @@ export function SearchScreenShell({
setSearchText(text)
}, [])
const {data: autocompleteData, isFetching: isAutocompleteFetching} =
useActorAutocompleteQuery(searchText, true)
const {items: autocompleteItems, isFetching: isAutocompleteFetching} =
useAutocomplete({
type: 'profile',
/*
* On web the dropdown (SearchAutocompleteInput) owns its own autocomplete
* query; only the native inline list consumes this one, so pass an empty
* query on web to keep the hook a no-op instead of doing wasted work.
*/
query: IS_NATIVE ? searchText : '',
})
const [showAutocomplete, setShowAutocomplete] = useState(false)
@@ -388,6 +396,38 @@ export function SearchScreenShell({
[updateProfileHistory, queryClient],
)
/**
* Web only. Selecting a profile from the anchored autocomplete dropdown.
*/
const onSelectProfile = useCallback(
(profile: bsky.profile.AnyProfileView, position: number) => {
ax.metric('search:autocomplete:press', {
profileDid: profile.did,
position,
})
handleProfileClick(profile)
navigation.navigate('Profile', {name: profile.handle})
},
[ax, handleProfileClick, navigation],
)
/**
* Web only. Selecting the "Search for X" row from the anchored autocomplete
* dropdown. This runs the typed query as-is (not a suggested profile), so it
* is attributed to `typed` rather than `autocomplete`.
*/
const onSelectSearch = useCallback(
(value: string) => {
ax.metric('search:query', {
source: 'typed',
filterCount: countActiveFilters(filters),
})
updateSearchText(value)
navigateToItem(value)
},
[ax, filters, navigateToItem, updateSearchText],
)
const onSoftReset = useCallback(() => {
if (IS_WEB) {
/*
@@ -495,13 +535,11 @@ export function SearchScreenShell({
{isExplore ? <Trans>Explore</Trans> : <Trans>Search</Trans>}
</Layout.Header.TitleText>
</Layout.Header.Content>
{showFilters ? (
advancedSearchV2Enabled ? null : (
<SearchLanguageDropdown
value={filters.lang ?? ''}
onChange={onChangeLang}
/>
)
{showFilters && !advancedSearchV2Enabled ? (
<SearchLanguageDropdown
value={filters.lang ?? ''}
onChange={onChangeLang}
/>
) : (
<Layout.Header.Slot />
)}
@@ -528,7 +566,7 @@ export function SearchScreenShell({
size="large"
variant="ghost"
color="secondary"
shape="rectangular"
shape="round"
style={[a.px_sm]}
onPress={onPressCancelSearch}
hitSlop={HITSLOP_10}>
@@ -536,7 +574,7 @@ export function SearchScreenShell({
</Button>
)}
<View style={[a.flex_1]}>
<SearchInput
<SearchAutocompleteInput
testID="searchScreenInput"
ref={textInput}
value={searchText}
@@ -547,6 +585,9 @@ export function SearchScreenShell({
placeholder={inputPlaceholder ?? l`Search`}
hitSlop={{...HITSLOP_20, top: 0}}
hotkey={true}
fixedParams={Boolean(fixedParams)}
onSelectProfile={onSelectProfile}
onSelectSearch={onSelectSearch}
/>
</View>
</View>
@@ -589,10 +630,10 @@ export function SearchScreenShell({
display: showAutocomplete && !fixedParams ? 'flex' : 'none',
flex: 1,
}}>
{searchText.length > 0 ? (
{searchText.length > 0 && IS_NATIVE ? (
<AutocompleteResults
isAutocompleteFetching={isAutocompleteFetching}
autocompleteData={autocompleteData}
items={autocompleteItems}
isFetching={isAutocompleteFetching}
searchText={searchText}
onSubmit={onSubmit('autocomplete')}
onResultPress={onAutocompleteResultPress}