Scroll feed search bar to top of screen on focus (#2602)
* Scroll feed search bar to top on focus * update commentzio/stable
parent
382383ca87
commit
94f39bb3eb
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react'
|
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 {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
|
import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
|
||||||
import {ViewHeader} from 'view/com/util/ViewHeader'
|
import {ViewHeader} from 'view/com/util/ViewHeader'
|
||||||
|
@ -34,6 +34,7 @@ import {
|
||||||
import {cleanError} from 'lib/strings/errors'
|
import {cleanError} from 'lib/strings/errors'
|
||||||
import {useComposerControls} from '#/state/shell/composer'
|
import {useComposerControls} from '#/state/shell/composer'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
|
import {isNative} from '#/platform/detection'
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<FeedsTabNavigatorParams, 'Feeds'>
|
type Props = NativeStackScreenProps<FeedsTabNavigatorParams, 'Feeds'>
|
||||||
|
|
||||||
|
@ -118,6 +119,7 @@ export function FeedsScreen(_props: Props) {
|
||||||
error: searchError,
|
error: searchError,
|
||||||
} = useSearchPopularFeedsMutation()
|
} = useSearchPopularFeedsMutation()
|
||||||
const {hasSession} = useSession()
|
const {hasSession} = useSession()
|
||||||
|
const listRef = React.useRef<FlatList>(null)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A search query is present. We may not have search results yet.
|
* A search query is present. We may not have search results yet.
|
||||||
|
@ -338,6 +340,35 @@ export function FeedsScreen(_props: Props) {
|
||||||
)
|
)
|
||||||
}, [pal, _])
|
}, [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(
|
const renderItem = React.useCallback(
|
||||||
({item}: {item: FlatlistSlice}) => {
|
({item}: {item: FlatlistSlice}) => {
|
||||||
if (item.type === 'error') {
|
if (item.type === 'error') {
|
||||||
|
@ -415,6 +446,7 @@ export function FeedsScreen(_props: Props) {
|
||||||
onChangeQuery={onChangeQuery}
|
onChangeQuery={onChangeQuery}
|
||||||
onPressCancelSearch={onPressCancelSearch}
|
onPressCancelSearch={onPressCancelSearch}
|
||||||
onSubmitQuery={onSubmitQuery}
|
onSubmitQuery={onSubmitQuery}
|
||||||
|
setIsInputFocused={onChangeSearchFocus}
|
||||||
style={{flex: 1, maxWidth: 250}}
|
style={{flex: 1, maxWidth: 250}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -427,6 +459,7 @@ export function FeedsScreen(_props: Props) {
|
||||||
onChangeQuery={onChangeQuery}
|
onChangeQuery={onChangeQuery}
|
||||||
onPressCancelSearch={onPressCancelSearch}
|
onPressCancelSearch={onPressCancelSearch}
|
||||||
onSubmitQuery={onSubmitQuery}
|
onSubmitQuery={onSubmitQuery}
|
||||||
|
setIsInputFocused={onChangeSearchFocus}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
@ -469,6 +502,7 @@ export function FeedsScreen(_props: Props) {
|
||||||
onChangeQuery,
|
onChangeQuery,
|
||||||
onPressCancelSearch,
|
onPressCancelSearch,
|
||||||
onSubmitQuery,
|
onSubmitQuery,
|
||||||
|
onChangeSearchFocus,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -486,6 +520,7 @@ export function FeedsScreen(_props: Props) {
|
||||||
{preferences ? <View /> : <ActivityIndicator />}
|
{preferences ? <View /> : <ActivityIndicator />}
|
||||||
|
|
||||||
<List
|
<List
|
||||||
|
ref={listRef}
|
||||||
style={[!isTabletOrDesktop && s.flex1, styles.list]}
|
style={[!isTabletOrDesktop && s.flex1, styles.list]}
|
||||||
data={items}
|
data={items}
|
||||||
keyExtractor={item => item.key}
|
keyExtractor={item => item.key}
|
||||||
|
|
Loading…
Reference in New Issue