This commit is contained in:
Eric Bailey
2024-09-24 10:22:13 -05:00
parent bf37cc0914
commit 257573cd9c
+177 -139
View File
@@ -22,7 +22,6 @@ import {useLingui} from '@lingui/react'
import AsyncStorage from '@react-native-async-storage/async-storage' import AsyncStorage from '@react-native-async-storage/async-storage'
import {useFocusEffect, useNavigation} from '@react-navigation/native' import {useFocusEffect, useNavigation} from '@react-navigation/native'
import {LANGUAGES} from '#/lib/../locale/languages'
import {useAnalytics} from '#/lib/analytics/analytics' import {useAnalytics} from '#/lib/analytics/analytics'
import {createHitslop} from '#/lib/constants' import {createHitslop} from '#/lib/constants'
import {HITSLOP_10} from '#/lib/constants' import {HITSLOP_10} from '#/lib/constants'
@@ -37,6 +36,7 @@ import {
SearchTabNavigatorParams, SearchTabNavigatorParams,
} from '#/lib/routes/types' } from '#/lib/routes/types'
import {augmentSearchQuery} from '#/lib/strings/helpers' import {augmentSearchQuery} from '#/lib/strings/helpers'
import {LANGUAGES} from '#/locale/languages'
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'
@@ -61,11 +61,13 @@ import {Explore} from '#/view/screens/Search/Explore'
import {SearchLinkCard, SearchProfileCard} from '#/view/shell/desktop/Search' import {SearchLinkCard, SearchProfileCard} from '#/view/shell/desktop/Search'
import {atoms as a, useBreakpoints, useTheme as useThemeNew, web} from '#/alf' import {atoms as a, useBreakpoints, useTheme as useThemeNew, web} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
import * as FeedCard from '#/components/FeedCard' import * as FeedCard from '#/components/FeedCard'
import * as TextField from '#/components/forms/TextField' import * as TextField from '#/components/forms/TextField'
import {ChevronBottom_Stroke2_Corner0_Rounded as ChevronDown} from '#/components/icons/Chevron' import {ChevronBottom_Stroke2_Corner0_Rounded as ChevronDown} from '#/components/icons/Chevron'
import {MagnifyingGlass2_Stroke2_Corner0_Rounded as MagnifyingGlass} from '#/components/icons/MagnifyingGlass2' import {MagnifyingGlass2_Stroke2_Corner0_Rounded as MagnifyingGlass} from '#/components/icons/MagnifyingGlass2'
import {Menu_Stroke2_Corner0_Rounded as Menu} from '#/components/icons/Menu' import {Menu_Stroke2_Corner0_Rounded as Menu} from '#/components/icons/Menu'
import {SettingsGear2_Stroke2_Corner0_Rounded as Gear} from '#/components/icons/SettingsGear2'
import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
import {Text as NewText} from '#/components/Typography' import {Text as NewText} from '#/components/Typography'
@@ -409,8 +411,14 @@ function SearchLanguageDropdown({
) )
} }
let SearchScreenInner = ({query}: {query?: string}): React.ReactNode => { let SearchScreenInner = ({
const t = useThemeNew() queryWithoutLanguage,
queryWithLanguage,
}: {
query?: string
queryWithoutLanguage: string
queryWithLanguage: string
}): React.ReactNode => {
const pal = usePalette('default') const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled() const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
@@ -418,14 +426,6 @@ let SearchScreenInner = ({query}: {query?: string}): React.ReactNode => {
const {isDesktop} = useWebMediaQueries() const {isDesktop} = useWebMediaQueries()
const [activeTab, setActiveTab] = React.useState(0) const [activeTab, setActiveTab] = React.useState(0)
const {_} = useLingui() const {_} = useLingui()
const {gtMobile} = useBreakpoints()
const {contentLanguages} = useLanguagePrefs()
const [language, setLanguage] = React.useState(
parseLanguageFromQuery(query || '') || contentLanguages[0],
)
const queryWithoutLang = sanitizeLangFromQuery(query || '')
const queryWithLang = queryWithoutLang + ` lang:${language}`
const onPageSelected = React.useCallback( const onPageSelected = React.useCallback(
(index: number) => { (index: number) => {
@@ -437,13 +437,13 @@ let SearchScreenInner = ({query}: {query?: string}): React.ReactNode => {
) )
const sections = React.useMemo(() => { const sections = React.useMemo(() => {
if (!queryWithoutLang) return [] if (!queryWithoutLanguage) return []
return [ return [
{ {
title: _(msg`Top`), title: _(msg`Top`),
component: ( component: (
<SearchScreenPostResults <SearchScreenPostResults
query={queryWithLang} query={queryWithLanguage}
sort="top" sort="top"
active={activeTab === 0} active={activeTab === 0}
/> />
@@ -453,7 +453,7 @@ let SearchScreenInner = ({query}: {query?: string}): React.ReactNode => {
title: _(msg`Latest`), title: _(msg`Latest`),
component: ( component: (
<SearchScreenPostResults <SearchScreenPostResults
query={queryWithLang} query={queryWithLanguage}
sort="latest" sort="latest"
active={activeTab === 1} active={activeTab === 1}
/> />
@@ -463,7 +463,7 @@ let SearchScreenInner = ({query}: {query?: string}): React.ReactNode => {
title: _(msg`People`), title: _(msg`People`),
component: ( component: (
<SearchScreenUserResults <SearchScreenUserResults
query={queryWithoutLang} query={queryWithoutLanguage}
active={activeTab === 2} active={activeTab === 2}
/> />
), ),
@@ -472,49 +472,29 @@ let SearchScreenInner = ({query}: {query?: string}): React.ReactNode => {
title: _(msg`Feeds`), title: _(msg`Feeds`),
component: ( component: (
<SearchScreenFeedsResults <SearchScreenFeedsResults
query={queryWithoutLang} query={queryWithoutLanguage}
active={activeTab === 3} active={activeTab === 3}
/> />
), ),
}, },
] ]
}, [_, queryWithoutLang, queryWithLang, activeTab]) }, [_, queryWithoutLanguage, queryWithLanguage, activeTab])
return queryWithoutLang ? ( return queryWithoutLanguage ? (
<> <Pager
<CenteredView onPageSelected={onPageSelected}
sideBorders={gtMobile} renderTabBar={props => (
style={[ <CenteredView
isWeb && a.pt_sm, sideBorders
isNative && a.pb_xs, style={[pal.border, pal.view, styles.tabBarContainer]}>
a.px_md, <TabBar items={sections.map(section => section.title)} {...props} />
t.atoms.border_contrast_low, </CenteredView>
]}> )}
<View style={[a.flex_row, a.justify_end, a.align_center, a.gap_sm]}> initialPage={0}>
<NewText style={[a.font_bold, t.atoms.text_contrast_medium]}> {sections.map((section, i) => (
<Trans>Language:</Trans> <View key={i}>{section.component}</View>
</NewText> ))}
<View style={[{width: 120}]}> </Pager>
<SearchLanguageDropdown value={language} onChange={setLanguage} />
</View>
</View>
</CenteredView>
<Pager
onPageSelected={onPageSelected}
renderTabBar={props => (
<CenteredView
sideBorders
style={[pal.border, pal.view, styles.tabBarContainer]}>
<TabBar items={sections.map(section => section.title)} {...props} />
</CenteredView>
)}
initialPage={0}>
{sections.map((section, i) => (
<View key={i}>{section.component}</View>
))}
</Pager>
</>
) : hasSession ? ( ) : hasSession ? (
<Explore /> <Explore />
) : ( ) : (
@@ -784,95 +764,153 @@ export function SearchScreen(
[selectedProfiles], [selectedProfiles],
) )
return ( const {contentLanguages} = useLanguagePrefs()
<View style={isWeb ? null : {flex: 1}}> const [language, setLanguage] = React.useState(
<CenteredView parseLanguageFromQuery(queryParam || '') || contentLanguages[0],
style={[ )
a.p_md, const queryWithoutLanguage = sanitizeLangFromQuery(queryParam || '')
a.pb_0, const queryWithLanguage = queryWithoutLanguage + ` lang:${language}`
a.flex_row, const control = Dialog.useDialogControl()
a.gap_sm,
t.atoms.bg,
web({
height: HEADER_HEIGHT, // TODO
position: 'sticky',
top: 0,
zIndex: 1,
}),
]}
sideBorders={gtMobile}>
{!gtMobile && (
<Button
testID="viewHeaderBackOrMenuBtn"
onPress={onPressMenu}
hitSlop={HITSLOP_10}
label={_(msg`Menu`)}
accessibilityHint={_(msg`Access navigation links and settings`)}
size="large"
variant="ghost"
color="secondary"
shape="square">
<ButtonIcon icon={Menu} size="lg" />
</Button>
)}
<SearchInputBox
textInput={textInput}
searchText={searchText}
showAutocomplete={showAutocomplete}
setShowAutocomplete={setShowAutocomplete}
onChangeText={onChangeText}
onSubmit={onSubmit}
onPressClearQuery={onPressClearQuery}
/>
{showAutocomplete && (
<Button
label={_(msg`Cancel search`)}
size="large"
variant="ghost"
color="secondary"
style={[a.px_sm]}
onPress={onPressCancelSearch}
hitSlop={HITSLOP_10}>
<ButtonText>
<Trans>Cancel</Trans>
</ButtonText>
</Button>
)}
</CenteredView>
<View return (
style={{ <>
display: showAutocomplete ? 'flex' : 'none', <Dialog.Outer control={control}>
flex: 1, <Dialog.Handle />
}}>
{searchText.length > 0 ? ( <Dialog.ScrollableInner
<AutocompleteResults label={_(msg`Advanced search parameters`)}
isAutocompleteFetching={isAutocompleteFetching} style={[
autocompleteData={autocompleteData} gtMobile ? {width: 'auto', maxWidth: 400, minWidth: 200} : a.w_full,
searchText={searchText} ]}>
onSubmit={onSubmit} <View style={[a.gap_xs]}>
onResultPress={onAutocompleteResultPress} <NewText style={[a.text_lg, a.font_heavy]}>
onProfileClick={handleProfileClick} <Trans>Advanced search</Trans>
</NewText>
<NewText style={[a.text_md, t.atoms.text_contrast_medium]}>
<Trans>For more tips and tricks, check out this blog post.</Trans>
</NewText>
</View>
<View style={[a.pt_md]}>
<SearchLanguageDropdown value={language} onChange={setLanguage} />
</View>
<Dialog.Close />
</Dialog.ScrollableInner>
</Dialog.Outer>
<View style={isWeb ? null : {flex: 1}}>
<CenteredView
style={[
a.p_md,
a.pb_0,
a.flex_row,
a.gap_xs,
t.atoms.bg,
web({
height: HEADER_HEIGHT, // TODO
position: 'sticky',
top: 0,
zIndex: 1,
}),
]}
sideBorders={gtMobile}>
{!gtMobile && (
<Button
testID="viewHeaderBackOrMenuBtn"
onPress={onPressMenu}
hitSlop={HITSLOP_10}
label={_(msg`Menu`)}
accessibilityHint={_(msg`Access navigation links and settings`)}
size="large"
variant="ghost"
color="secondary"
shape="square"
style={{
marginLeft: -6,
}}>
<ButtonIcon icon={Menu} size="lg" />
</Button>
)}
<View style={[a.flex_1]}>
<SearchInputBox
textInput={textInput}
searchText={searchText}
showAutocomplete={showAutocomplete}
setShowAutocomplete={setShowAutocomplete}
onChangeText={onChangeText}
onSubmit={onSubmit}
onPressClearQuery={onPressClearQuery}
/>
</View>
{showAutocomplete && (
<Button
label={_(msg`Cancel search`)}
size="large"
variant="ghost"
color="secondary"
style={[a.px_sm]}
onPress={onPressCancelSearch}
hitSlop={HITSLOP_10}>
<ButtonText>
<Trans>Cancel</Trans>
</ButtonText>
</Button>
)}
{searchText && !showAutocomplete && (
<Button
label={_(msg`Customize search`)}
size="large"
shape="square"
color="secondary"
variant="ghost"
style={{
marginRight: -6,
}}
onPress={() => {
control.open()
}}>
<ButtonIcon icon={Gear} size="lg" />
</Button>
)}
</CenteredView>
<View
style={{
display: showAutocomplete ? 'flex' : 'none',
flex: 1,
}}>
{searchText.length > 0 ? (
<AutocompleteResults
isAutocompleteFetching={isAutocompleteFetching}
autocompleteData={autocompleteData}
searchText={searchText}
onSubmit={onSubmit}
onResultPress={onAutocompleteResultPress}
onProfileClick={handleProfileClick}
/>
) : (
<SearchHistory
searchHistory={searchHistory}
selectedProfiles={selectedProfiles}
onItemClick={handleHistoryItemClick}
onProfileClick={handleProfileClick}
onRemoveItemClick={handleRemoveHistoryItem}
onRemoveProfileClick={handleRemoveProfile}
/>
)}
</View>
<View
style={{
display: showAutocomplete ? 'none' : 'flex',
flex: 1,
}}>
<SearchScreenInner
queryWithoutLanguage={queryWithoutLanguage}
queryWithLanguage={queryWithLanguage}
/> />
) : ( </View>
<SearchHistory
searchHistory={searchHistory}
selectedProfiles={selectedProfiles}
onItemClick={handleHistoryItemClick}
onProfileClick={handleProfileClick}
onRemoveItemClick={handleRemoveHistoryItem}
onRemoveProfileClick={handleRemoveProfile}
/>
)}
</View> </View>
<View </>
style={{
display: showAutocomplete ? 'none' : 'flex',
flex: 1,
}}>
<SearchScreenInner query={queryParam} />
</View>
</View>
) )
} }
@@ -897,7 +935,7 @@ let SearchInputBox = ({
const t = useThemeNew() const t = useThemeNew()
return ( return (
<View style={[a.flex_1, a.relative]}> <View style={[a.w_full, a.relative]}>
<TextField.Root> <TextField.Root>
<TextField.Icon icon={MagnifyingGlass} /> <TextField.Icon icon={MagnifyingGlass} />
<TextField.Input <TextField.Input