Make scroll handling contextual (#2200)
* Add an intermediate List component * Fix type * Add onScrolledDownChange * Port pager to use onScrolledDownChange * Fix on mobile * Don't pass down onScroll (replacement TBD) * Remove resetMainScroll * Replace onMainScroll with MainScrollProvider * Hook ScrollProvider to pager * Fix the remaining special case * Optimize a bit * Enforce that onScroll cannot be passed * Keep value updated even if no handler * Also memo it
This commit is contained in:
parent
fa3ccafa80
commit
7fd7970237
26 changed files with 280 additions and 354 deletions
|
@ -7,13 +7,15 @@ import {useNavigation} from '@react-navigation/native'
|
|||
import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed'
|
||||
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
||||
import {MainScrollProvider} from '../util/MainScrollProvider'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {useSetMinimalShellMode} from '#/state/shell'
|
||||
import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
|
||||
import {ComposeIcon2} from 'lib/icons'
|
||||
import {colors, s} from 'lib/styles'
|
||||
import {FlatList, View, useWindowDimensions} from 'react-native'
|
||||
import {View, useWindowDimensions} from 'react-native'
|
||||
import {ListMethods} from '../util/List'
|
||||
import {Feed} from '../posts/Feed'
|
||||
import {TextLink} from '../util/Link'
|
||||
import {FAB} from '../util/fab/FAB'
|
||||
|
@ -51,10 +53,11 @@ export function FeedPage({
|
|||
const {isDesktop} = useWebMediaQueries()
|
||||
const queryClient = useQueryClient()
|
||||
const {openComposer} = useComposerControls()
|
||||
const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll()
|
||||
const [isScrolledDown, setIsScrolledDown] = React.useState(false)
|
||||
const setMinimalShellMode = useSetMinimalShellMode()
|
||||
const {screen, track} = useAnalytics()
|
||||
const headerOffset = useHeaderOffset()
|
||||
const scrollElRef = React.useRef<FlatList>(null)
|
||||
const scrollElRef = React.useRef<ListMethods>(null)
|
||||
const [hasNew, setHasNew] = React.useState(false)
|
||||
|
||||
const scrollToTop = React.useCallback(() => {
|
||||
|
@ -62,8 +65,8 @@ export function FeedPage({
|
|||
animated: isNative,
|
||||
offset: -headerOffset,
|
||||
})
|
||||
resetMainScroll()
|
||||
}, [headerOffset, resetMainScroll])
|
||||
setMinimalShellMode(false)
|
||||
}, [headerOffset, setMinimalShellMode])
|
||||
|
||||
const onSoftReset = React.useCallback(() => {
|
||||
const isScreenFocused =
|
||||
|
@ -164,21 +167,22 @@ export function FeedPage({
|
|||
|
||||
return (
|
||||
<View testID={testID} style={s.h100pct}>
|
||||
<Feed
|
||||
testID={testID ? `${testID}-feed` : undefined}
|
||||
enabled={isPageFocused}
|
||||
feed={feed}
|
||||
feedParams={feedParams}
|
||||
pollInterval={POLL_FREQ}
|
||||
scrollElRef={scrollElRef}
|
||||
onScroll={onMainScroll}
|
||||
onHasNew={setHasNew}
|
||||
scrollEventThrottle={1}
|
||||
renderEmptyState={renderEmptyState}
|
||||
renderEndOfFeed={renderEndOfFeed}
|
||||
ListHeaderComponent={ListHeaderComponent}
|
||||
headerOffset={headerOffset}
|
||||
/>
|
||||
<MainScrollProvider>
|
||||
<Feed
|
||||
testID={testID ? `${testID}-feed` : undefined}
|
||||
enabled={isPageFocused}
|
||||
feed={feed}
|
||||
feedParams={feedParams}
|
||||
pollInterval={POLL_FREQ}
|
||||
scrollElRef={scrollElRef}
|
||||
onScrolledDownChange={setIsScrolledDown}
|
||||
onHasNew={setHasNew}
|
||||
renderEmptyState={renderEmptyState}
|
||||
renderEndOfFeed={renderEndOfFeed}
|
||||
ListHeaderComponent={ListHeaderComponent}
|
||||
headerOffset={headerOffset}
|
||||
/>
|
||||
</MainScrollProvider>
|
||||
{(isScrolledDown || hasNew) && (
|
||||
<LoadLatestBtn
|
||||
onPress={onPressLoadLatest}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, {MutableRefObject} from 'react'
|
||||
import React from 'react'
|
||||
import {
|
||||
Dimensions,
|
||||
RefreshControl,
|
||||
|
@ -8,18 +8,16 @@ import {
|
|||
ViewStyle,
|
||||
} from 'react-native'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
import {FlatList} from '../util/Views'
|
||||
import {List, ListRef} from '../util/List'
|
||||
import {FeedSourceCardLoaded} from './FeedSourceCard'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
|
||||
import {Text} from '../util/text/Text'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useProfileFeedgensQuery, RQKEY} from '#/state/queries/profile-feedgens'
|
||||
import {OnScrollHandler} from '#/lib/hooks/useOnMainScroll'
|
||||
import {logger} from '#/logger'
|
||||
import {Trans} from '@lingui/macro'
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
||||
import {useTheme} from '#/lib/ThemeContext'
|
||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||
import {hydrateFeedGenerator} from '#/state/queries/feed'
|
||||
|
@ -37,9 +35,7 @@ interface SectionRef {
|
|||
|
||||
interface ProfileFeedgensProps {
|
||||
did: string
|
||||
scrollElRef: MutableRefObject<FlatList<any> | null>
|
||||
onScroll?: OnScrollHandler
|
||||
scrollEventThrottle?: number
|
||||
scrollElRef: ListRef
|
||||
headerOffset: number
|
||||
enabled?: boolean
|
||||
style?: StyleProp<ViewStyle>
|
||||
|
@ -50,16 +46,7 @@ export const ProfileFeedgens = React.forwardRef<
|
|||
SectionRef,
|
||||
ProfileFeedgensProps
|
||||
>(function ProfileFeedgensImpl(
|
||||
{
|
||||
did,
|
||||
scrollElRef,
|
||||
onScroll,
|
||||
scrollEventThrottle,
|
||||
headerOffset,
|
||||
enabled,
|
||||
style,
|
||||
testID,
|
||||
},
|
||||
{did, scrollElRef, headerOffset, enabled, style, testID},
|
||||
ref,
|
||||
) {
|
||||
const pal = usePalette('default')
|
||||
|
@ -185,10 +172,9 @@ export const ProfileFeedgens = React.forwardRef<
|
|||
[error, refetch, onPressRetryLoadMore, pal, preferences],
|
||||
)
|
||||
|
||||
const scrollHandler = useAnimatedScrollHandler(onScroll || {})
|
||||
return (
|
||||
<View testID={testID} style={style}>
|
||||
<FlatList
|
||||
<List
|
||||
testID={testID ? `${testID}-flatlist` : undefined}
|
||||
ref={scrollElRef}
|
||||
data={items}
|
||||
|
@ -207,8 +193,6 @@ export const ProfileFeedgens = React.forwardRef<
|
|||
minHeight: Dimensions.get('window').height * 1.5,
|
||||
}}
|
||||
style={{paddingTop: headerOffset}}
|
||||
onScroll={onScroll != null ? scrollHandler : undefined}
|
||||
scrollEventThrottle={scrollEventThrottle}
|
||||
indicatorStyle={theme.colorScheme === 'dark' ? 'white' : 'black'}
|
||||
removeClippedSubviews={true}
|
||||
contentOffset={{x: 0, y: headerOffset * -1}}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue