Skip to content

Commit

Permalink
Add search button to header on feeds screen (#2848)
Browse files Browse the repository at this point in the history
* add search bar to header

* add button on web
  • Loading branch information
haileyok authored Feb 12, 2024
1 parent ba7463c commit b936da1
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 72 deletions.
125 changes: 70 additions & 55 deletions src/view/com/util/forms/SearchInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,64 +26,79 @@ interface Props {
onSubmitQuery: () => void
style?: StyleProp<ViewStyle>
}
export function SearchInput({
query,
setIsInputFocused,
onChangeQuery,
onPressCancelSearch,
onSubmitQuery,
style,
}: Props) {
const theme = useTheme()
const pal = usePalette('default')
const {_} = useLingui()
const textInput = React.useRef<TextInput>(null)

const onPressCancelSearchInner = React.useCallback(() => {
onPressCancelSearch()
textInput.current?.blur()
}, [onPressCancelSearch, textInput])
export interface SearchInputRef {
focus?: () => void
}

export const SearchInput = React.forwardRef<SearchInputRef, Props>(
function SearchInput(
{
query,
setIsInputFocused,
onChangeQuery,
onPressCancelSearch,
onSubmitQuery,
style,
},
ref,
) {
const theme = useTheme()
const pal = usePalette('default')
const {_} = useLingui()
const textInput = React.useRef<TextInput>(null)

const onPressCancelSearchInner = React.useCallback(() => {
onPressCancelSearch()
textInput.current?.blur()
}, [onPressCancelSearch, textInput])

return (
<View style={[pal.viewLight, styles.container, style]}>
<MagnifyingGlassIcon style={[pal.icon, styles.icon]} size={21} />
<TextInput
testID="searchTextInput"
ref={textInput}
placeholder={_(msg`Search`)}
placeholderTextColor={pal.colors.textLight}
selectTextOnFocus
returnKeyType="search"
value={query}
style={[pal.text, styles.input]}
keyboardAppearance={theme.colorScheme}
onFocus={() => setIsInputFocused?.(true)}
onBlur={() => setIsInputFocused?.(false)}
onChangeText={onChangeQuery}
onSubmitEditing={onSubmitQuery}
accessibilityRole="search"
accessibilityLabel={_(msg`Search`)}
accessibilityHint=""
autoCorrect={false}
autoCapitalize="none"
/>
{query ? (
<TouchableOpacity
onPress={onPressCancelSearchInner}
accessibilityRole="button"
accessibilityLabel={_(msg`Clear search query`)}
React.useImperativeHandle(ref, () => ({
focus: () => textInput.current?.focus(),
blur: () => textInput.current?.blur(),
}))

return (
<View style={[pal.viewLight, styles.container, style]}>
<MagnifyingGlassIcon style={[pal.icon, styles.icon]} size={21} />
<TextInput
testID="searchTextInput"
ref={textInput}
placeholder={_(msg`Search`)}
placeholderTextColor={pal.colors.textLight}
selectTextOnFocus
returnKeyType="search"
value={query}
style={[pal.text, styles.input]}
keyboardAppearance={theme.colorScheme}
onFocus={() => setIsInputFocused?.(true)}
onBlur={() => setIsInputFocused?.(false)}
onChangeText={onChangeQuery}
onSubmitEditing={onSubmitQuery}
accessibilityRole="search"
accessibilityLabel={_(msg`Search`)}
accessibilityHint=""
hitSlop={HITSLOP_10}>
<FontAwesomeIcon
icon="xmark"
size={16}
style={pal.textLight as FontAwesomeIconStyle}
/>
</TouchableOpacity>
) : undefined}
</View>
)
}
autoCorrect={false}
autoCapitalize="none"
/>
{query ? (
<TouchableOpacity
onPress={onPressCancelSearchInner}
accessibilityRole="button"
accessibilityLabel={_(msg`Clear search query`)}
accessibilityHint=""
hitSlop={HITSLOP_10}>
<FontAwesomeIcon
icon="xmark"
size={16}
style={pal.textLight as FontAwesomeIconStyle}
/>
</TouchableOpacity>
) : undefined}
</View>
)
},
)

const styles = StyleSheet.create({
container: {
Expand Down
73 changes: 56 additions & 17 deletions src/view/screens/Feeds.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import React from 'react'
import {ActivityIndicator, StyleSheet, View, type FlatList} from 'react-native'
import {
ActivityIndicator,
StyleSheet,
View,
type FlatList,
Pressable,
} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
import {ViewHeader} from 'view/com/util/ViewHeader'
Expand All @@ -8,9 +14,9 @@ import {Link} from 'view/com/util/Link'
import {NativeStackScreenProps, FeedsTabNavigatorParams} from 'lib/routes/types'
import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {ComposeIcon2, CogIcon} from 'lib/icons'
import {ComposeIcon2, CogIcon, MagnifyingGlassIcon2} from 'lib/icons'
import {s} from 'lib/styles'
import {SearchInput} from 'view/com/util/forms/SearchInput'
import {SearchInput, SearchInputRef} from 'view/com/util/forms/SearchInput'
import {UserAvatar} from 'view/com/util/UserAvatar'
import {
LoadingPlaceholder,
Expand All @@ -36,6 +42,7 @@ import {cleanError} from 'lib/strings/errors'
import {useComposerControls} from '#/state/shell/composer'
import {useSession} from '#/state/session'
import {isNative} from '#/platform/detection'
import {HITSLOP_10} from 'lib/constants'

type Props = NativeStackScreenProps<FeedsTabNavigatorParams, 'Feeds'>

Expand Down Expand Up @@ -121,6 +128,7 @@ export function FeedsScreen(_props: Props) {
} = useSearchPopularFeedsMutation()
const {hasSession} = useSession()
const listRef = React.useRef<FlatList>(null)
const searchInputRef = React.useRef<SearchInputRef>(null)

/**
* A search query is present. We may not have search results yet.
Expand Down Expand Up @@ -330,14 +338,26 @@ export function FeedsScreen(_props: Props) {

const renderHeaderBtn = React.useCallback(() => {
return (
<Link
href="/settings/saved-feeds"
hitSlop={10}
accessibilityRole="button"
accessibilityLabel={_(msg`Edit Saved Feeds`)}
accessibilityHint={_(msg`Opens screen to edit Saved Feeds`)}>
<CogIcon size={22} strokeWidth={2} style={pal.textLight} />
</Link>
<View style={styles.headerBtnGroup}>
<Pressable
accessibilityRole="button"
hitSlop={HITSLOP_10}
onPress={searchInputRef.current?.focus}>
<MagnifyingGlassIcon2
size={22}
strokeWidth={2}
style={pal.textLight}
/>
</Pressable>
<Link
href="/settings/saved-feeds"
hitSlop={10}
accessibilityRole="button"
accessibilityLabel={_(msg`Edit Saved Feeds`)}
accessibilityHint={_(msg`Opens screen to edit Saved Feeds`)}>
<CogIcon size={22} strokeWidth={2} style={pal.textLight} />
</Link>
</View>
)
}, [pal, _])

Expand Down Expand Up @@ -398,12 +418,24 @@ export function FeedsScreen(_props: Props) {
<Text type="title-lg" style={[pal.text, s.bold]}>
<Trans>My Feeds</Trans>
</Text>
<Link
href="/settings/saved-feeds"
accessibilityLabel={_(msg`Edit My Feeds`)}
accessibilityHint="">
<CogIcon strokeWidth={1.5} style={pal.icon} size={28} />
</Link>
<View style={styles.headerBtnGroup}>
<Pressable
accessibilityRole="button"
hitSlop={HITSLOP_10}
onPress={searchInputRef.current?.focus}>
<MagnifyingGlassIcon2
size={22}
strokeWidth={2}
style={pal.icon}
/>
</Pressable>
<Link
href="/settings/saved-feeds"
accessibilityLabel={_(msg`Edit My Feeds`)}
accessibilityHint="">
<CogIcon strokeWidth={1.5} style={pal.icon} size={28} />
</Link>
</View>
</View>
)
}
Expand Down Expand Up @@ -443,6 +475,7 @@ export function FeedsScreen(_props: Props) {

{!isMobile && (
<SearchInput
ref={searchInputRef}
query={query}
onChangeQuery={onChangeQuery}
onPressCancelSearch={onPressCancelSearch}
Expand All @@ -456,6 +489,7 @@ export function FeedsScreen(_props: Props) {
{isMobile && (
<View style={{paddingHorizontal: 8, paddingBottom: 10}}>
<SearchInput
ref={searchInputRef}
query={query}
onChangeQuery={onChangeQuery}
onPressCancelSearch={onPressCancelSearch}
Expand Down Expand Up @@ -663,4 +697,9 @@ const styles = StyleSheet.create({
paddingHorizontal: 4,
paddingVertical: 2,
},
headerBtnGroup: {
flexDirection: 'row',
gap: 15,
alignItems: 'center',
},
})

0 comments on commit b936da1

Please sign in to comment.