search input revamp
This commit is contained in:
@@ -226,6 +226,7 @@ export function createInput(Component: typeof TextInput) {
|
|||||||
<>
|
<>
|
||||||
<Component
|
<Component
|
||||||
accessibilityHint={undefined}
|
accessibilityHint={undefined}
|
||||||
|
hitSlop={HITSLOP_20}
|
||||||
{...rest}
|
{...rest}
|
||||||
accessibilityLabel={label}
|
accessibilityLabel={label}
|
||||||
ref={refs}
|
ref={refs}
|
||||||
@@ -242,7 +243,6 @@ export function createInput(Component: typeof TextInput) {
|
|||||||
placeholder={placeholder || label}
|
placeholder={placeholder || label}
|
||||||
placeholderTextColor={t.palette.contrast_500}
|
placeholderTextColor={t.palette.contrast_500}
|
||||||
keyboardAppearance={t.name === 'light' ? 'light' : 'dark'}
|
keyboardAppearance={t.name === 'light' ? 'light' : 'dark'}
|
||||||
hitSlop={HITSLOP_20}
|
|
||||||
style={flattened}
|
style={flattened}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react'
|
import React, {useLayoutEffect} from 'react'
|
||||||
import {
|
import {
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
Image,
|
Image,
|
||||||
@@ -11,6 +11,10 @@ import {
|
|||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {ScrollView as RNGHScrollView} from 'react-native-gesture-handler'
|
import {ScrollView as RNGHScrollView} from 'react-native-gesture-handler'
|
||||||
import RNPickerSelect from 'react-native-picker-select'
|
import RNPickerSelect from 'react-native-picker-select'
|
||||||
|
import Animated, {
|
||||||
|
FadingTransition,
|
||||||
|
LinearTransition,
|
||||||
|
} from 'react-native-reanimated'
|
||||||
import {AppBskyActorDefs, AppBskyFeedDefs, moderateProfile} from '@atproto/api'
|
import {AppBskyActorDefs, AppBskyFeedDefs, moderateProfile} from '@atproto/api'
|
||||||
import {
|
import {
|
||||||
FontAwesomeIcon,
|
FontAwesomeIcon,
|
||||||
@@ -22,7 +26,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage'
|
|||||||
import {useFocusEffect, useNavigation} from '@react-navigation/native'
|
import {useFocusEffect, useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {APP_LANGUAGES, LANGUAGES} from '#/lib/../locale/languages'
|
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 {HITSLOP_10} from '#/lib/constants'
|
||||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
import {usePalette} from '#/lib/hooks/usePalette'
|
import {usePalette} from '#/lib/hooks/usePalette'
|
||||||
@@ -47,7 +51,6 @@ import {useActorSearch} from '#/state/queries/actor-search'
|
|||||||
import {usePopularFeedsSearch} from '#/state/queries/feed'
|
import {usePopularFeedsSearch} from '#/state/queries/feed'
|
||||||
import {useSearchPostsQuery} from '#/state/queries/search-posts'
|
import {useSearchPostsQuery} from '#/state/queries/search-posts'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {useSetDrawerOpen} from '#/state/shell'
|
|
||||||
import {useSetMinimalShellMode} from '#/state/shell'
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
import {Pager} from '#/view/com/pager/Pager'
|
import {Pager} from '#/view/com/pager/Pager'
|
||||||
import {TabBar} from '#/view/com/pager/TabBar'
|
import {TabBar} from '#/view/com/pager/TabBar'
|
||||||
@@ -61,16 +64,16 @@ import {SearchLinkCard, SearchProfileCard} from '#/view/shell/desktop/Search'
|
|||||||
import {makeSearchQuery, parseSearchQuery} from '#/screens/Search/utils'
|
import {makeSearchQuery, parseSearchQuery} from '#/screens/Search/utils'
|
||||||
import {
|
import {
|
||||||
atoms as a,
|
atoms as a,
|
||||||
|
native,
|
||||||
tokens,
|
tokens,
|
||||||
useBreakpoints,
|
useBreakpoints,
|
||||||
useTheme as useThemeNew,
|
useTheme as useThemeNew,
|
||||||
web,
|
web,
|
||||||
} from '#/alf'
|
} from '#/alf'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import * as FeedCard from '#/components/FeedCard'
|
import * as FeedCard from '#/components/FeedCard'
|
||||||
import {SearchInput} from '#/components/forms/SearchInput'
|
import {SearchInput} from '#/components/forms/SearchInput'
|
||||||
import {ChevronBottom_Stroke2_Corner0_Rounded as ChevronDown} from '#/components/icons/Chevron'
|
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 * as Layout from '#/components/Layout'
|
||||||
|
|
||||||
function Loader() {
|
function Loader() {
|
||||||
@@ -602,7 +605,6 @@ export function SearchScreen(
|
|||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const textInput = React.useRef<TextInput>(null)
|
const textInput = React.useRef<TextInput>(null)
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const setDrawerOpen = useSetDrawerOpen()
|
|
||||||
const setMinimalShellMode = useSetMinimalShellMode()
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
|
|
||||||
// Query terms
|
// Query terms
|
||||||
@@ -621,11 +623,17 @@ export function SearchScreen(
|
|||||||
initialQuery: queryParam,
|
initialQuery: queryParam,
|
||||||
})
|
})
|
||||||
const showFilters = Boolean(queryWithParams && !showAutocomplete)
|
const showFilters = Boolean(queryWithParams && !showAutocomplete)
|
||||||
/*
|
|
||||||
* Arbitrary sizing, so guess and check, used for sticky header alignment and
|
// web only - measure header height for sticky positioning
|
||||||
* sizing.
|
const [headerHeight, setHeaderHeight] = React.useState(0)
|
||||||
*/
|
const headerRef = React.useRef(null)
|
||||||
const headerHeight = 60 + (showFilters ? 40 : 0)
|
useLayoutEffect(() => {
|
||||||
|
if (isWeb) {
|
||||||
|
if (!headerRef.current) return
|
||||||
|
const measurement = (headerRef.current as Element).getBoundingClientRect()
|
||||||
|
setHeaderHeight(measurement.height)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useNonReactiveCallback(() => {
|
useNonReactiveCallback(() => {
|
||||||
@@ -654,11 +662,6 @@ export function SearchScreen(
|
|||||||
loadSearchHistory()
|
loadSearchHistory()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const onPressMenu = React.useCallback(() => {
|
|
||||||
textInput.current?.blur()
|
|
||||||
setDrawerOpen(true)
|
|
||||||
}, [setDrawerOpen])
|
|
||||||
|
|
||||||
const onPressClearQuery = React.useCallback(() => {
|
const onPressClearQuery = React.useCallback(() => {
|
||||||
scrollToTopWeb()
|
scrollToTopWeb()
|
||||||
setSearchText('')
|
setSearchText('')
|
||||||
@@ -843,33 +846,51 @@ export function SearchScreen(
|
|||||||
return (
|
return (
|
||||||
<Layout.Screen testID="searchScreen">
|
<Layout.Screen testID="searchScreen">
|
||||||
<View
|
<View
|
||||||
|
ref={headerRef}
|
||||||
|
onLayout={evt => {
|
||||||
|
if (isWeb) setHeaderHeight(evt.nativeEvent.layout.height)
|
||||||
|
}}
|
||||||
style={[
|
style={[
|
||||||
|
t.atoms.bg,
|
||||||
web({
|
web({
|
||||||
height: headerHeight,
|
|
||||||
position: 'sticky',
|
position: 'sticky',
|
||||||
top: 0,
|
top: 0,
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
}),
|
}),
|
||||||
]}>
|
]}>
|
||||||
<Layout.Center>
|
<Layout.Center>
|
||||||
<View style={[a.p_md, a.pb_sm, a.gap_sm, t.atoms.bg]}>
|
|
||||||
<View style={[a.flex_row, a.gap_sm]}>
|
|
||||||
{!gtMobile && !showAutocomplete && (
|
{!gtMobile && !showAutocomplete && (
|
||||||
<Button
|
<Animated.View
|
||||||
testID="viewHeaderBackOrMenuBtn"
|
layout={native(FadingTransition)}
|
||||||
onPress={onPressMenu}
|
// HACK: shift up search input. we can't remove the top padding
|
||||||
hitSlop={HITSLOP_10}
|
// on the search input because it messes up the layout animation
|
||||||
label={_(msg`Menu`)}
|
// if we add it only when the header is hidden
|
||||||
accessibilityHint={_(
|
style={{marginBottom: tokens.space.md * -1}}>
|
||||||
msg`Access navigation links and settings`,
|
<Layout.Header.Outer noBottomBorder>
|
||||||
|
<Layout.Header.MenuButton />
|
||||||
|
<Layout.Header.Content
|
||||||
|
align={showFilters ? 'left' : 'platform'}>
|
||||||
|
<Layout.Header.TitleText>
|
||||||
|
<Trans>Search</Trans>
|
||||||
|
</Layout.Header.TitleText>
|
||||||
|
</Layout.Header.Content>
|
||||||
|
{showFilters ? (
|
||||||
|
<View style={[{minWidth: 140}]}>
|
||||||
|
<SearchLanguageDropdown
|
||||||
|
value={params.lang}
|
||||||
|
onChange={params.setLang}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<Layout.Header.Slot />
|
||||||
)}
|
)}
|
||||||
size="large"
|
</Layout.Header.Outer>
|
||||||
variant="solid"
|
</Animated.View>
|
||||||
color="secondary"
|
|
||||||
shape="square">
|
|
||||||
<ButtonIcon icon={Menu} size="lg" />
|
|
||||||
</Button>
|
|
||||||
)}
|
)}
|
||||||
|
<Animated.View
|
||||||
|
style={[a.px_md, a.pt_md, a.pb_sm]}
|
||||||
|
layout={native(LinearTransition)}>
|
||||||
|
<View style={[a.flex_row, a.gap_sm]}>
|
||||||
<View style={[a.flex_1]}>
|
<View style={[a.flex_1]}>
|
||||||
<SearchInput
|
<SearchInput
|
||||||
ref={textInput}
|
ref={textInput}
|
||||||
@@ -878,6 +899,8 @@ export function SearchScreen(
|
|||||||
onChangeText={onChangeText}
|
onChangeText={onChangeText}
|
||||||
onClearText={onPressClearQuery}
|
onClearText={onPressClearQuery}
|
||||||
onSubmitEditing={onSubmit}
|
onSubmitEditing={onSubmit}
|
||||||
|
placeholder={_(msg`Search for posts, users, or feeds`)}
|
||||||
|
hitSlop={{...HITSLOP_20, top: 0}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
{showAutocomplete && (
|
{showAutocomplete && (
|
||||||
@@ -895,24 +918,7 @@ export function SearchScreen(
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
</Animated.View>
|
||||||
{showFilters && (
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.justify_between,
|
|
||||||
a.gap_sm,
|
|
||||||
]}>
|
|
||||||
<View style={[{width: 140}]}>
|
|
||||||
<SearchLanguageDropdown
|
|
||||||
value={params.lang}
|
|
||||||
onChange={params.setLang}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</Layout.Center>
|
</Layout.Center>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user