diff options
author | Hailey <me@haileyok.com> | 2024-04-26 20:34:53 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-27 04:34:53 +0100 |
commit | 5f9136479b6dbcaaa9def57e0308326a00259e8b (patch) | |
tree | 55d660675e37508ed003654b31690b8b7ffcb674 /src/view/shell/desktop/Search.tsx | |
parent | d81a373d21af605db43c2076bfe486aa16e01de3 (diff) | |
download | voidsky-5f9136479b6dbcaaa9def57e0308326a00259e8b.tar.zst |
Improve usability of search on web (#3663)
* dont select the text on web * TODO REVERT THESE CHANGES * use `usethrottledvalue` for autocomplete * use `isFetching` from query * rm setTimeout * getting there * improve functionality of cancel button * rm todo * add comment back * encode `searchText` rather than `queryTerm` * use "back" on web in some cases * don't flash results in autocomplete * remove unnecesary usestate * rename everything to `query` temporarily * revert accidental lint * rm todo * rm comment * use `useFocusEffect` to update the query term on back navigation * `searchText` is always defined here * Fix race * remove back functionality * use `keepPreviousData` for query * rename `q` to `queryParam` * remove hack * remove `q=` on cancel * blur on submit * use `setParams` instead of `replace` * use `replace` on web still * clear the search input when we clear `q` on native * onPress dismiss attempt * Adjustments * Fix search history * Always hide autocomplete * Clear right pane search on select * `blur` on autosuggestion press * Rename to reduce diff * Fixes * Unify codepaths * Fixes * precache the autosuggestion * do the cache in the link card * Revert "precache the autosuggestion" This reverts commit 79c433e984621ba4231a2a4c4b3f4690b0516b4d. * use `throttledValue` and `keepPreviousData` in sidebar search * show spinner when fetching pt 1 * show spinner when fetching pt 2 * show spinner properly for autocomplete * Fix extra border * Position fixed * TS * Revert "TS" This reverts commit df187ea2d7a96d0f1832bc2392215f4d969a87c9. * Revert "Position fixed" This reverts commit 9c721c952b0fa4e5e4a23de38cab916ab13397e6. * Maybe fix iPad * Revert "TODO REVERT THESE CHANGES" This reverts commit 279f717f3091c9df8c73ba35f9a038e12f5a1122. * Rename var --------- Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
Diffstat (limited to 'src/view/shell/desktop/Search.tsx')
-rw-r--r-- | src/view/shell/desktop/Search.tsx | 106 |
1 files changed, 47 insertions, 59 deletions
diff --git a/src/view/shell/desktop/Search.tsx b/src/view/shell/desktop/Search.tsx index 0c5bd452f..52f28cc63 100644 --- a/src/view/shell/desktop/Search.tsx +++ b/src/view/shell/desktop/Search.tsx @@ -1,33 +1,35 @@ import React from 'react' import { - ViewStyle, - TextInput, - View, + ActivityIndicator, StyleSheet, + TextInput, TouchableOpacity, - ActivityIndicator, + View, + ViewStyle, } from 'react-native' -import {useNavigation, StackActions} from '@react-navigation/native' import { AppBskyActorDefs, moderateProfile, ModerationDecision, } from '@atproto/api' -import {Trans, msg} from '@lingui/macro' +import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {StackActions, useNavigation} from '@react-navigation/native' +import {useQueryClient} from '@tanstack/react-query' -import {s} from '#/lib/styles' +import {makeProfileLink} from '#/lib/routes/links' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' -import {makeProfileLink} from '#/lib/routes/links' -import {Link} from '#/view/com/util/Link' +import {s} from '#/lib/styles' +import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete' +import {useModerationOpts} from '#/state/queries/preferences' import {usePalette} from 'lib/hooks/usePalette' import {MagnifyingGlassIcon2} from 'lib/icons' import {NavigationProp} from 'lib/routes/types' -import {Text} from 'view/com/util/text/Text' +import {precacheProfile} from 'state/queries/profile' +import {Link} from '#/view/com/util/Link' import {UserAvatar} from '#/view/com/util/UserAvatar' -import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete' -import {useModerationOpts} from '#/state/queries/preferences' +import {Text} from 'view/com/util/text/Text' export const MATCH_HANDLE = /@?([a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(?:\.[a-zA-Z]{2,}))/ @@ -84,11 +86,19 @@ export function SearchLinkCard({ export function SearchProfileCard({ profile, moderation, + onPress: onPressInner, }: { profile: AppBskyActorDefs.ProfileViewBasic moderation: ModerationDecision + onPress: () => void }) { const pal = usePalette('default') + const queryClient = useQueryClient() + + const onPress = React.useCallback(() => { + precacheProfile(queryClient, profile) + onPressInner() + }, [queryClient, profile, onPressInner]) return ( <Link @@ -96,7 +106,8 @@ export function SearchProfileCard({ href={makeProfileLink(profile)} title={profile.handle} asAnchor - anchorNoUnderline> + anchorNoUnderline + onBeforePress={onPress}> <View style={[ pal.border, @@ -138,63 +149,35 @@ export function DesktopSearch() { const {_} = useLingui() const pal = usePalette('default') const navigation = useNavigation<NavigationProp>() - const searchDebounceTimeout = React.useRef<NodeJS.Timeout | undefined>( - undefined, - ) const [isActive, setIsActive] = React.useState<boolean>(false) - const [isFetching, setIsFetching] = React.useState<boolean>(false) const [query, setQuery] = React.useState<string>('') - const [searchResults, setSearchResults] = React.useState< - AppBskyActorDefs.ProfileViewBasic[] - >([]) + const {data: autocompleteData, isFetching} = useActorAutocompleteQuery( + query, + true, + ) const moderationOpts = useModerationOpts() - const search = useActorAutocompleteFn() - - const onChangeText = React.useCallback( - async (text: string) => { - setQuery(text) - - if (text.length > 0) { - setIsFetching(true) - setIsActive(true) - if (searchDebounceTimeout.current) - clearTimeout(searchDebounceTimeout.current) - - searchDebounceTimeout.current = setTimeout(async () => { - const results = await search({query: text}) - - if (results) { - setSearchResults(results) - setIsFetching(false) - } - }, 300) - } else { - if (searchDebounceTimeout.current) - clearTimeout(searchDebounceTimeout.current) - setSearchResults([]) - setIsFetching(false) - setIsActive(false) - } - }, - [setQuery, search, setSearchResults], - ) + const onChangeText = React.useCallback((text: string) => { + setQuery(text) + setIsActive(text.length > 0) + }, []) const onPressCancelSearch = React.useCallback(() => { setQuery('') setIsActive(false) - if (searchDebounceTimeout.current) - clearTimeout(searchDebounceTimeout.current) }, [setQuery]) + const onSubmit = React.useCallback(() => { setIsActive(false) if (!query.length) return - setSearchResults([]) - if (searchDebounceTimeout.current) - clearTimeout(searchDebounceTimeout.current) navigation.dispatch(StackActions.push('Search', {q: query})) - }, [query, navigation, setSearchResults]) + }, [query, navigation]) + + const onSearchProfileCardPress = React.useCallback(() => { + setQuery('') + setIsActive(false) + }, []) const queryMaybeHandle = React.useMemo(() => { const match = MATCH_HANDLE.exec(query) @@ -246,7 +229,7 @@ export function DesktopSearch() { {query !== '' && isActive && moderationOpts && ( <View style={[pal.view, pal.borderDark, styles.resultsContainer]}> - {isFetching ? ( + {isFetching && !autocompleteData?.length ? ( <View style={{padding: 8}}> <ActivityIndicator /> </View> @@ -255,7 +238,11 @@ export function DesktopSearch() { <SearchLinkCard label={_(msg`Search for "${query}"`)} to={`/search?q=${encodeURIComponent(query)}`} - style={{borderBottomWidth: 1}} + style={ + queryMaybeHandle || (autocompleteData?.length ?? 0) > 0 + ? {borderBottomWidth: 1} + : undefined + } /> {queryMaybeHandle ? ( @@ -265,11 +252,12 @@ export function DesktopSearch() { /> ) : null} - {searchResults.map(item => ( + {autocompleteData?.map(item => ( <SearchProfileCard key={item.did} profile={item} moderation={moderateProfile(item, moderationOpts)} + onPress={onSearchProfileCardPress} /> ))} </> |