Scroll feed search bar to top of screen on focus (#2602)

* Scroll feed search bar to top on focus

* update comment
zio/stable
Samuel Newman 2024-01-24 04:22:22 +00:00 committed by GitHub
parent 382383ca87
commit 94f39bb3eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 36 additions and 1 deletions

View File

@ -1,5 +1,5 @@
import React from 'react'
import {ActivityIndicator, StyleSheet, View} from 'react-native'
import {ActivityIndicator, StyleSheet, View, type FlatList} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
import {ViewHeader} from 'view/com/util/ViewHeader'
@ -34,6 +34,7 @@ import {
import {cleanError} from 'lib/strings/errors'
import {useComposerControls} from '#/state/shell/composer'
import {useSession} from '#/state/session'
import {isNative} from '#/platform/detection'
type Props = NativeStackScreenProps<FeedsTabNavigatorParams, 'Feeds'>
@ -118,6 +119,7 @@ export function FeedsScreen(_props: Props) {
error: searchError,
} = useSearchPopularFeedsMutation()
const {hasSession} = useSession()
const listRef = React.useRef<FlatList>(null)
/**
* A search query is present. We may not have search results yet.
@ -338,6 +340,35 @@ export function FeedsScreen(_props: Props) {
)
}, [pal, _])
const searchBarIndex = items.findIndex(
item => item.type === 'popularFeedsHeader',
)
const onChangeSearchFocus = React.useCallback(
(focus: boolean) => {
if (focus && searchBarIndex > -1) {
if (isNative) {
// scrollToIndex scrolls the exact right amount, so use if available
listRef.current?.scrollToIndex({
index: searchBarIndex,
animated: true,
})
} else {
// web implementation only supports scrollToOffset
// thus, we calculate the offset based on the index
// pixel values are estimates, I wasn't able to get it pixel perfect :(
const headerHeight = isMobile ? 43 : 53
const feedItemHeight = isMobile ? 49 : 58
listRef.current?.scrollToOffset({
offset: searchBarIndex * feedItemHeight - headerHeight,
animated: true,
})
}
}
},
[searchBarIndex, isMobile],
)
const renderItem = React.useCallback(
({item}: {item: FlatlistSlice}) => {
if (item.type === 'error') {
@ -415,6 +446,7 @@ export function FeedsScreen(_props: Props) {
onChangeQuery={onChangeQuery}
onPressCancelSearch={onPressCancelSearch}
onSubmitQuery={onSubmitQuery}
setIsInputFocused={onChangeSearchFocus}
style={{flex: 1, maxWidth: 250}}
/>
)}
@ -427,6 +459,7 @@ export function FeedsScreen(_props: Props) {
onChangeQuery={onChangeQuery}
onPressCancelSearch={onPressCancelSearch}
onSubmitQuery={onSubmitQuery}
setIsInputFocused={onChangeSearchFocus}
/>
</View>
)}
@ -469,6 +502,7 @@ export function FeedsScreen(_props: Props) {
onChangeQuery,
onPressCancelSearch,
onSubmitQuery,
onChangeSearchFocus,
],
)
@ -486,6 +520,7 @@ export function FeedsScreen(_props: Props) {
{preferences ? <View /> : <ActivityIndicator />}
<List
ref={listRef}
style={[!isTabletOrDesktop && s.flex1, styles.list]}
data={items}
keyExtractor={item => item.key}