show scroll to top button when scrolling stops

zio/stable
Ansh Nanda 2023-05-23 15:48:14 -07:00
parent 0fd5c9294a
commit 858ec6438d
3 changed files with 28 additions and 3 deletions

View File

@ -2,6 +2,9 @@ import {useState} from 'react'
import {NativeSyntheticEvent, NativeScrollEvent} from 'react-native' import {NativeSyntheticEvent, NativeScrollEvent} from 'react-native'
import {RootStoreModel} from 'state/index' import {RootStoreModel} from 'state/index'
export type onMomentumScrollEndCb = (
event: NativeSyntheticEvent<NativeScrollEvent>,
) => void
export type OnScrollCb = ( export type OnScrollCb = (
event: NativeSyntheticEvent<NativeScrollEvent>, event: NativeSyntheticEvent<NativeScrollEvent>,
) => void ) => void

View File

@ -14,7 +14,7 @@ import {ErrorMessage} from '../util/error/ErrorMessage'
import {PostsFeedModel} from 'state/models/feeds/posts' import {PostsFeedModel} from 'state/models/feeds/posts'
import {FeedSlice} from './FeedSlice' import {FeedSlice} from './FeedSlice'
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn' import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
import {OnScrollCb} from 'lib/hooks/useOnMainScroll' import {OnScrollCb, onMomentumScrollEndCb} from 'lib/hooks/useOnMainScroll'
import {s} from 'lib/styles' import {s} from 'lib/styles'
import {useAnalytics} from 'lib/analytics' import {useAnalytics} from 'lib/analytics'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
@ -31,6 +31,8 @@ export const Feed = observer(function Feed({
scrollElRef, scrollElRef,
onPressTryAgain, onPressTryAgain,
onScroll, onScroll,
scrollEventThrottle,
onMomentumScrollEnd,
renderEmptyState, renderEmptyState,
testID, testID,
headerOffset = 0, headerOffset = 0,
@ -43,6 +45,8 @@ export const Feed = observer(function Feed({
scrollElRef?: MutableRefObject<FlatList<any> | null> scrollElRef?: MutableRefObject<FlatList<any> | null>
onPressTryAgain?: () => void onPressTryAgain?: () => void
onScroll?: OnScrollCb onScroll?: OnScrollCb
scrollEventThrottle?: number
onMomentumScrollEnd?: onMomentumScrollEndCb
renderEmptyState?: () => JSX.Element renderEmptyState?: () => JSX.Element
testID?: string testID?: string
headerOffset?: number headerOffset?: number
@ -180,6 +184,8 @@ export const Feed = observer(function Feed({
contentContainerStyle={s.contentContainer} contentContainerStyle={s.contentContainer}
style={{paddingTop: headerOffset}} style={{paddingTop: headerOffset}}
onScroll={onScroll} onScroll={onScroll}
scrollEventThrottle={scrollEventThrottle}
onMomentumScrollEnd={onMomentumScrollEnd}
onEndReached={onEndReached} onEndReached={onEndReached}
onEndReachedThreshold={0.6} onEndReachedThreshold={0.6}
removeClippedSubviews={true} removeClippedSubviews={true}

View File

@ -1,4 +1,4 @@
import React, {useMemo, useRef} from 'react' import React, {useMemo, useRef, useState} from 'react'
import {NativeStackScreenProps} from '@react-navigation/native-stack' import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
@ -25,6 +25,8 @@ import {useSetTitle} from 'lib/hooks/useSetTitle'
import {shareUrl} from 'lib/sharing' import {shareUrl} from 'lib/sharing'
import {toShareUrl} from 'lib/strings/url-helpers' import {toShareUrl} from 'lib/strings/url-helpers'
import {Haptics} from 'lib/haptics' import {Haptics} from 'lib/haptics'
import { LoadLatestBtn } from 'view/com/util/load-latest/LoadLatestBtn'
import { onMomentumScrollEndCb } from 'lib/hooks/useOnMainScroll'
const HITSLOP = {top: 5, left: 5, bottom: 5, right: 5} const HITSLOP = {top: 5, left: 5, bottom: 5, right: 5}
@ -48,7 +50,7 @@ export const CustomFeedScreen = withAuthRequired(
return feed return feed
}, [store, uri]) }, [store, uri])
const isPinned = store.me.savedFeeds.isPinned(uri) const isPinned = store.me.savedFeeds.isPinned(uri)
const [allowScrollToTop, setAllowScrollToTop] = useState(false)
useSetTitle(currentFeed?.displayName) useSetTitle(currentFeed?.displayName)
const onToggleSaved = React.useCallback(async () => { const onToggleSaved = React.useCallback(async () => {
@ -266,15 +268,29 @@ export const CustomFeedScreen = withAuthRequired(
isPinned, isPinned,
]) ])
const onMomentumScrollEnd: onMomentumScrollEndCb = React.useCallback((event) => {
if (event.nativeEvent.contentOffset.y > 200) {
setAllowScrollToTop(true)
} else {
setAllowScrollToTop(false)
}
}, [])
return ( return (
<View style={s.hContentRegion}> <View style={s.hContentRegion}>
<ViewHeader title="" renderButton={renderHeaderBtns} /> <ViewHeader title="" renderButton={renderHeaderBtns} />
<Feed <Feed
scrollElRef={scrollElRef} scrollElRef={scrollElRef}
feed={algoFeed} feed={algoFeed}
onMomentumScrollEnd={onMomentumScrollEnd}
ListHeaderComponent={renderListHeaderComponent} ListHeaderComponent={renderListHeaderComponent}
extraData={[uri, isPinned]} extraData={[uri, isPinned]}
/> />
{allowScrollToTop ? <LoadLatestBtn onPress={() => {
scrollElRef.current?.scrollToOffset({offset: 0, animated: true})
}}
label='Scroll to top'
/> : null}
</View> </View>
) )
}), }),