From b37199a5a02e9957d3f564035004a39190c91a62 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Wed, 12 Feb 2025 22:48:29 +0000 Subject: Improved search page (#7590) * search input revamp * fix web * rm "useThemeNew" * fix overlap during transition * animate header properly * reduce gap * animate cancel button in * don't move search bar when focused * remove cancel button animation --- src/components/Layout/Header/index.tsx | 3 +- src/components/forms/TextField.tsx | 2 +- src/view/screens/Search/Search.tsx | 189 +++++++++++++++++---------------- 3 files changed, 101 insertions(+), 93 deletions(-) diff --git a/src/components/Layout/Header/index.tsx b/src/components/Layout/Header/index.tsx index d38cf9d94..3af0215c5 100644 --- a/src/components/Layout/Header/index.tsx +++ b/src/components/Layout/Header/index.tsx @@ -1,5 +1,5 @@ import {createContext, useCallback, useContext} from 'react' -import {GestureResponderEvent, View} from 'react-native' +import {GestureResponderEvent, Keyboard, View} from 'react-native' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useNavigation} from '@react-navigation/native' @@ -140,6 +140,7 @@ export function MenuButton() { const {gtMobile} = useBreakpoints() const onPress = useCallback(() => { + Keyboard.dismiss() setDrawerOpen(true) }, [setDrawerOpen]) diff --git a/src/components/forms/TextField.tsx b/src/components/forms/TextField.tsx index 410cc654e..d28700df9 100644 --- a/src/components/forms/TextField.tsx +++ b/src/components/forms/TextField.tsx @@ -226,6 +226,7 @@ export function createInput(Component: typeof TextInput) { <> diff --git a/src/view/screens/Search/Search.tsx b/src/view/screens/Search/Search.tsx index d2fb1d45b..3e711ab56 100644 --- a/src/view/screens/Search/Search.tsx +++ b/src/view/screens/Search/Search.tsx @@ -1,4 +1,4 @@ -import React, {useCallback} from 'react' +import React, {useCallback, useLayoutEffect} from 'react' import { ActivityIndicator, Image, @@ -21,7 +21,7 @@ import {useLingui} from '@lingui/react' import {useFocusEffect, useNavigation} from '@react-navigation/native' import {APP_LANGUAGES, LANGUAGES} from '#/lib/../locale/languages' -import {createHitslop} from '#/lib/constants' +import {createHitslop, HITSLOP_20} from '#/lib/constants' import {HITSLOP_10} from '#/lib/constants' import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' import {usePalette} from '#/lib/hooks/usePalette' @@ -46,7 +46,6 @@ import {usePopularFeedsSearch} from '#/state/queries/feed' import {useProfilesQuery} from '#/state/queries/profile' import {useSearchPostsQuery} from '#/state/queries/search-posts' import {useSession} from '#/state/session' -import {useSetDrawerOpen} from '#/state/shell' import {useSetMinimalShellMode} from '#/state/shell' import {Pager} from '#/view/com/pager/Pager' import {TabBar} from '#/view/com/pager/TabBar' @@ -58,18 +57,11 @@ import {Text} from '#/view/com/util/text/Text' import {Explore} from '#/view/screens/Search/Explore' import {SearchLinkCard, SearchProfileCard} from '#/view/shell/desktop/Search' import {makeSearchQuery, parseSearchQuery} from '#/screens/Search/utils' -import { - atoms as a, - tokens, - useBreakpoints, - useTheme as useThemeNew, - web, -} from '#/alf' -import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import {atoms as a, tokens, useBreakpoints, useTheme, web} from '#/alf' +import {Button, ButtonText} from '#/components/Button' import * as FeedCard from '#/components/FeedCard' import {SearchInput} from '#/components/forms/SearchInput' import {ChevronBottom_Stroke2_Corner0_Rounded as ChevronDown} from '#/components/icons/Chevron' -import {Menu_Stroke2_Corner0_Rounded as Menu} from '#/components/icons/Menu' import * as Layout from '#/components/Layout' import {account, useStorage} from '#/storage' @@ -278,7 +270,7 @@ let SearchScreenFeedsResults = ({ query: string active: boolean }): React.ReactNode => { - const t = useThemeNew() + const t = useTheme() const {_} = useLingui() const {data: results, isFetched} = usePopularFeedsSearch({ @@ -323,7 +315,7 @@ function SearchLanguageDropdown({ value: string onChange(value: string): void }) { - const t = useThemeNew() + const t = useTheme() const {_} = useLingui() const {appLanguage, contentLanguages} = useLanguagePrefs() @@ -534,12 +526,7 @@ let SearchScreenInner = ({ ( - + section.title)} {...props} /> )} @@ -597,12 +584,11 @@ SearchScreenInner = React.memo(SearchScreenInner) export function SearchScreen( props: NativeStackScreenProps, ) { - const t = useThemeNew() + const t = useTheme() const {gtMobile} = useBreakpoints() const navigation = useNavigation() const textInput = React.useRef(null) const {_} = useLingui() - const setDrawerOpen = useSetDrawerOpen() const setMinimalShellMode = useSetMinimalShellMode() const {currentAccount} = useSession() @@ -630,6 +616,7 @@ export function SearchScreen( const updateSearchHistory = useCallback( async (item: string) => { + if (!item) return const newSearchHistory = [ item, ...termHistory.filter(search => search !== item), @@ -667,11 +654,17 @@ export function SearchScreen( initialQuery: queryParam, }) const showFilters = Boolean(queryWithParams && !showAutocomplete) - /* - * Arbitrary sizing, so guess and check, used for sticky header alignment and - * sizing. - */ - const headerHeight = 60 + (showFilters ? 40 : 0) + + // web only - measure header height for sticky positioning + const [headerHeight, setHeaderHeight] = React.useState(0) + const headerRef = React.useRef(null) + useLayoutEffect(() => { + if (isWeb) { + if (!headerRef.current) return + const measurement = (headerRef.current as Element).getBoundingClientRect() + setHeaderHeight(measurement.height) + } + }, []) useFocusEffect( useNonReactiveCallback(() => { @@ -681,11 +674,6 @@ export function SearchScreen( }), ) - const onPressMenu = React.useCallback(() => { - textInput.current?.blur() - setDrawerOpen(true) - }, [setDrawerOpen]) - const onPressClearQuery = React.useCallback(() => { scrollToTopWeb() setSearchText('') @@ -789,75 +777,94 @@ export function SearchScreen( return ( { + if (isWeb) setHeaderHeight(evt.nativeEvent.layout.height) + }} style={[ + a.relative, + a.z_10, web({ - height: headerHeight, position: 'sticky', top: 0, - zIndex: 1, }), ]}> - - - - {!gtMobile && !showAutocomplete && ( - - )} - - - - {showAutocomplete && ( - - )} + + {!gtMobile && ( + - - {showFilters && ( - - - + + + + + {showAutocomplete && ( + + )} - )} + + {showFilters && gtMobile && ( + + + + + + )} + -- cgit 1.4.1