use usethrottledvalue for autocomplete
This commit is contained in:
@@ -28,7 +28,7 @@ import {s} from '#/lib/styles'
|
|||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
import {isNative, isWeb} from '#/platform/detection'
|
||||||
import {listenSoftReset} from '#/state/events'
|
import {listenSoftReset} from '#/state/events'
|
||||||
import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete'
|
import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
|
||||||
import {useActorSearch} from '#/state/queries/actor-search'
|
import {useActorSearch} from '#/state/queries/actor-search'
|
||||||
import {useModerationOpts} from '#/state/queries/preferences'
|
import {useModerationOpts} from '#/state/queries/preferences'
|
||||||
import {useSearchPostsQuery} from '#/state/queries/search-posts'
|
import {useSearchPostsQuery} from '#/state/queries/search-posts'
|
||||||
@@ -59,6 +59,7 @@ import {
|
|||||||
} from '#/view/shell/desktop/Search'
|
} from '#/view/shell/desktop/Search'
|
||||||
import {ProfileCardFeedLoadingPlaceholder} from 'view/com/util/LoadingPlaceholder'
|
import {ProfileCardFeedLoadingPlaceholder} from 'view/com/util/LoadingPlaceholder'
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a} from '#/alf'
|
||||||
|
import {useThrottledValue} from '#/components/hooks/useThrottledValue'
|
||||||
|
|
||||||
function Loader() {
|
function Loader() {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
@@ -537,7 +538,6 @@ export function SearchScreen(
|
|||||||
const {track} = useAnalytics()
|
const {track} = useAnalytics()
|
||||||
const setDrawerOpen = useSetDrawerOpen()
|
const setDrawerOpen = useSetDrawerOpen()
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
const search = useActorAutocompleteFn()
|
|
||||||
const setMinimalShellMode = useSetMinimalShellMode()
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
const {isTabletOrDesktop, isTabletOrMobile} = useWebMediaQueries()
|
const {isTabletOrDesktop, isTabletOrMobile} = useWebMediaQueries()
|
||||||
|
|
||||||
@@ -545,36 +545,20 @@ export function SearchScreen(
|
|||||||
undefined,
|
undefined,
|
||||||
)
|
)
|
||||||
const [isFetching, setIsFetching] = React.useState<boolean>(false)
|
const [isFetching, setIsFetching] = React.useState<boolean>(false)
|
||||||
const [query, setQuery] = React.useState<string>(props.route?.params?.q || '')
|
|
||||||
const [searchResults, setSearchResults] = React.useState<
|
// Query terms
|
||||||
AppBskyActorDefs.ProfileViewBasic[]
|
const q = props.route?.params?.q ?? ''
|
||||||
>([])
|
const [query, setQuery] = React.useState<string>(q)
|
||||||
|
const [searchInput, setSearchInput] = React.useState<string>(q)
|
||||||
|
const throttledInput = useThrottledValue(searchInput, 300)
|
||||||
|
|
||||||
|
const autocompleteResults = useActorAutocompleteQuery(throttledInput)
|
||||||
|
|
||||||
const [inputIsFocused, setInputIsFocused] = React.useState(false)
|
const [inputIsFocused, setInputIsFocused] = React.useState(false)
|
||||||
const [showAutocompleteResults, setShowAutocompleteResults] =
|
const [showAutocompleteResults, setShowAutocompleteResults] =
|
||||||
React.useState(false)
|
React.useState(false)
|
||||||
const [searchHistory, setSearchHistory] = React.useState<string[]>([])
|
const [searchHistory, setSearchHistory] = React.useState<string[]>([])
|
||||||
|
|
||||||
/**
|
|
||||||
* The Search screen's `q` param
|
|
||||||
*/
|
|
||||||
const queryParam = props.route?.params?.q
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If `true`, this means we received new instructions from the router. This
|
|
||||||
* is handled in a effect, and used to update the value of `query` locally
|
|
||||||
* within this screen.
|
|
||||||
*/
|
|
||||||
const routeParamsMismatch = queryParam && queryParam !== query
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (queryParam && routeParamsMismatch) {
|
|
||||||
// reset immediately and let local state take over
|
|
||||||
navigation.setParams({q: ''})
|
|
||||||
// update query for next search
|
|
||||||
setQuery(queryParam)
|
|
||||||
}
|
|
||||||
}, [queryParam, routeParamsMismatch, navigation])
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const loadSearchHistory = async () => {
|
const loadSearchHistory = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -610,39 +594,14 @@ export function SearchScreen(
|
|||||||
setShowAutocompleteResults(false)
|
setShowAutocompleteResults(false)
|
||||||
}, [setQuery])
|
}, [setQuery])
|
||||||
|
|
||||||
const onChangeText = React.useCallback(
|
const onChangeText = React.useCallback(async (text: string) => {
|
||||||
async (text: string) => {
|
scrollToTopWeb()
|
||||||
scrollToTopWeb()
|
setSearchInput(text)
|
||||||
|
|
||||||
setQuery(text)
|
const showAutoComplete = text.length > 0
|
||||||
|
setIsFetching(showAutoComplete)
|
||||||
if (text.length > 0) {
|
setShowAutocompleteResults(showAutoComplete)
|
||||||
setIsFetching(true)
|
}, [])
|
||||||
setShowAutocompleteResults(true)
|
|
||||||
|
|
||||||
if (searchDebounceTimeout.current) {
|
|
||||||
clearTimeout(searchDebounceTimeout.current)
|
|
||||||
}
|
|
||||||
|
|
||||||
searchDebounceTimeout.current = setTimeout(async () => {
|
|
||||||
const results = await search({query: text, limit: 30})
|
|
||||||
|
|
||||||
if (results) {
|
|
||||||
setSearchResults(results)
|
|
||||||
setIsFetching(false)
|
|
||||||
}
|
|
||||||
}, 300)
|
|
||||||
} else {
|
|
||||||
if (searchDebounceTimeout.current) {
|
|
||||||
clearTimeout(searchDebounceTimeout.current)
|
|
||||||
}
|
|
||||||
setSearchResults([])
|
|
||||||
setIsFetching(false)
|
|
||||||
setShowAutocompleteResults(false)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[setQuery, search, setSearchResults],
|
|
||||||
)
|
|
||||||
|
|
||||||
const updateSearchHistory = React.useCallback(
|
const updateSearchHistory = React.useCallback(
|
||||||
async (newQuery: string) => {
|
async (newQuery: string) => {
|
||||||
@@ -672,7 +631,8 @@ export function SearchScreen(
|
|||||||
scrollToTopWeb()
|
scrollToTopWeb()
|
||||||
setShowAutocompleteResults(false)
|
setShowAutocompleteResults(false)
|
||||||
updateSearchHistory(query)
|
updateSearchHistory(query)
|
||||||
}, [query, setShowAutocompleteResults, updateSearchHistory])
|
navigation.push('Search', {q: query})
|
||||||
|
}, [navigation, query, updateSearchHistory])
|
||||||
|
|
||||||
const onSoftReset = React.useCallback(() => {
|
const onSoftReset = React.useCallback(() => {
|
||||||
scrollToTopWeb()
|
scrollToTopWeb()
|
||||||
@@ -684,6 +644,7 @@ export function SearchScreen(
|
|||||||
return match && match[1]
|
return match && match[1]
|
||||||
}, [query])
|
}, [query])
|
||||||
|
|
||||||
|
// TODO ???
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
React.useCallback(() => {
|
React.useCallback(() => {
|
||||||
setMinimalShellMode(false)
|
setMinimalShellMode(false)
|
||||||
@@ -829,7 +790,7 @@ export function SearchScreen(
|
|||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{searchResults.map(item => (
|
{autocompleteResults.data?.map(item => (
|
||||||
<SearchProfileCard
|
<SearchProfileCard
|
||||||
key={item.did}
|
key={item.did}
|
||||||
profile={item}
|
profile={item}
|
||||||
@@ -885,8 +846,6 @@ export function SearchScreen(
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</CenteredView>
|
</CenteredView>
|
||||||
) : routeParamsMismatch ? (
|
|
||||||
<ActivityIndicator />
|
|
||||||
) : (
|
) : (
|
||||||
<SearchScreenInner query={query} />
|
<SearchScreenInner query={query} />
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user