Fix search typeahead performance with absolute overlay (#11103)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,11 @@ import {
|
||||
View,
|
||||
type ViewStyle,
|
||||
} from 'react-native'
|
||||
import Animated, {
|
||||
Easing,
|
||||
FadeInDown,
|
||||
FadeOutDown,
|
||||
} from 'react-native-reanimated'
|
||||
import {setStringAsync} from 'expo-clipboard'
|
||||
import {Trans, useLingui} from '@lingui/react/macro'
|
||||
import {useFocusEffect, useNavigation, useRoute} from '@react-navigation/native'
|
||||
@@ -41,7 +46,15 @@ import {
|
||||
withoutFilterParams,
|
||||
} from '#/screens/Search/searchParams'
|
||||
import {makeSearchQuery} from '#/screens/Search/utils'
|
||||
import {atoms as a, tokens, useBreakpoints, useTheme, web} from '#/alf'
|
||||
import {
|
||||
atoms as a,
|
||||
native,
|
||||
platform,
|
||||
tokens,
|
||||
useBreakpoints,
|
||||
useTheme,
|
||||
web,
|
||||
} from '#/alf'
|
||||
import {useAutocomplete} from '#/components/Autocomplete'
|
||||
import {Button, ButtonIcon} from '#/components/Button'
|
||||
import {ArrowLeft_Stroke2_Corner0_Rounded as ArrowLeftIcon} from '#/components/icons/Arrow'
|
||||
@@ -387,13 +400,14 @@ export function SearchScreenShell({
|
||||
|
||||
const handleProfileClick = useCallback(
|
||||
(profile: bsky.profile.AnyProfileView) => {
|
||||
updateSearchText('')
|
||||
unstableCacheProfileView(queryClient, profile)
|
||||
// Slight delay to avoid updating during push nav animation.
|
||||
setTimeout(() => {
|
||||
updateProfileHistory(profile)
|
||||
}, 400)
|
||||
},
|
||||
[updateProfileHistory, queryClient],
|
||||
[updateProfileHistory, queryClient, updateSearchText],
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -468,6 +482,17 @@ export function SearchScreenShell({
|
||||
}
|
||||
}, [setShowAutocomplete])
|
||||
|
||||
const onSearchInputBlur = useCallback(() => {
|
||||
/*
|
||||
* Bind autocomplete visibility to focus state on native. On web this
|
||||
* doesn't work because of focus management, which would render the
|
||||
* autocomplete results uninteractable.
|
||||
*/
|
||||
if (IS_NATIVE) {
|
||||
setShowAutocomplete(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const focusSearchInput = useCallback(
|
||||
(tab?: TabParam) => {
|
||||
textInput.current?.focus()
|
||||
@@ -597,6 +622,7 @@ export function SearchScreenShell({
|
||||
ref={textInput}
|
||||
value={searchText}
|
||||
onFocus={onSearchInputFocus}
|
||||
onBlur={onSearchInputBlur}
|
||||
onChangeText={onChangeText}
|
||||
onClearText={onPressClearQuery}
|
||||
onSubmitEditing={onSubmit('typed')}
|
||||
@@ -643,52 +669,57 @@ export function SearchScreenShell({
|
||||
</Layout.Center>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
display: showAutocomplete && !fixedParams ? 'flex' : 'none',
|
||||
flex: 1,
|
||||
}}>
|
||||
{searchText.length > 0 && IS_NATIVE ? (
|
||||
<AutocompleteResults
|
||||
items={autocompleteItems}
|
||||
isFetching={isAutocompleteFetching}
|
||||
searchText={searchText}
|
||||
onSubmit={onSubmit('autocomplete')}
|
||||
onResultPress={onAutocompleteResultPress}
|
||||
onProfileClick={handleProfileClick}
|
||||
/>
|
||||
) : (
|
||||
<SearchHistory
|
||||
searchHistory={termHistory}
|
||||
selectedProfiles={
|
||||
accountHistoryProfiles?.profiles.filter(p =>
|
||||
accountHistory.includes(p.did),
|
||||
) ?? []
|
||||
}
|
||||
onItemClick={handleHistoryItemClick}
|
||||
onProfileClick={handleProfileClick}
|
||||
onRemoveItemClick={deleteSearchHistoryItem}
|
||||
onRemoveProfileClick={deleteProfileHistoryItem}
|
||||
<View style={[a.flex_1, a.relative]}>
|
||||
<View style={[a.flex_1, web(showAutocomplete && a.hidden)]}>
|
||||
<SearchScreenInner
|
||||
key={filters.lang ?? ''}
|
||||
activeTab={activeTab}
|
||||
setActiveTab={setActiveTab}
|
||||
query={query}
|
||||
queryWithParams={queryWithParams}
|
||||
filters={filters}
|
||||
hasFilters={hasFilters}
|
||||
headerHeight={headerHeight}
|
||||
focusSearchInput={focusSearchInput}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{showAutocomplete && !fixedParams && (
|
||||
<Animated.View
|
||||
entering={native(FadeInDown.easing(Easing.out(Easing.cubic)))}
|
||||
exiting={native(FadeOutDown.easing(Easing.out(Easing.cubic)))}
|
||||
style={platform({
|
||||
web: [a.flex_1],
|
||||
native: [t.atoms.bg, a.absolute, a.inset_0],
|
||||
})}
|
||||
accessibilityViewIsModal
|
||||
accessibilityRole="list">
|
||||
{searchText.length > 0 && IS_NATIVE ? (
|
||||
<AutocompleteResults
|
||||
items={autocompleteItems}
|
||||
isFetching={isAutocompleteFetching}
|
||||
searchText={searchText}
|
||||
onSubmit={onSubmit('autocomplete')}
|
||||
onResultPress={onAutocompleteResultPress}
|
||||
onProfileClick={handleProfileClick}
|
||||
/>
|
||||
) : (
|
||||
<SearchHistory
|
||||
searchHistory={termHistory}
|
||||
selectedProfiles={
|
||||
accountHistoryProfiles?.profiles.filter(p =>
|
||||
accountHistory.includes(p.did),
|
||||
) ?? []
|
||||
}
|
||||
onItemClick={handleHistoryItemClick}
|
||||
onProfileClick={handleProfileClick}
|
||||
onRemoveItemClick={deleteSearchHistoryItem}
|
||||
onRemoveProfileClick={deleteProfileHistoryItem}
|
||||
/>
|
||||
)}
|
||||
</Animated.View>
|
||||
)}
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
display: showAutocomplete ? 'none' : 'flex',
|
||||
flex: 1,
|
||||
}}>
|
||||
<SearchScreenInner
|
||||
key={filters.lang ?? ''}
|
||||
activeTab={activeTab}
|
||||
setActiveTab={setActiveTab}
|
||||
query={query}
|
||||
queryWithParams={queryWithParams}
|
||||
filters={filters}
|
||||
hasFilters={hasFilters}
|
||||
headerHeight={headerHeight}
|
||||
focusSearchInput={focusSearchInput}
|
||||
/>
|
||||
</View>
|
||||
</Layout.Screen>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user