1
- import React , { createContext , useContext } from 'react' ;
1
+ import React , {
2
+ createContext ,
3
+ useContext ,
4
+ useEffect ,
5
+ useMemo ,
6
+ useState ,
7
+ } from 'react' ;
8
+ import { Dimensions , Platform } from 'react-native' ;
2
9
import {
3
10
Easing ,
4
11
type SharedValue ,
@@ -18,12 +25,22 @@ export const ScrollContext = createContext<ScrollContextTuple>(INITIAL_VALUE);
18
25
19
26
export const useScrollContext = ( ) => useContext ( ScrollContext ) ;
20
27
21
- export const useScrollDirectionTracker = (
22
- setIsAtBottom : ( isAtBottom : boolean ) => void
23
- ) => {
28
+ export const useScrollDirectionTracker = ( {
29
+ setIsAtBottom,
30
+ atBottomThreshold = 1 , // multiple of screen/viewport height
31
+ } : {
32
+ setIsAtBottom : ( isAtBottom : boolean ) => void ;
33
+ atBottomThreshold ?: number ;
34
+ } ) => {
24
35
const [ scrollValue ] = useScrollContext ( ) ;
25
36
const previousScrollValue = useSharedValue ( 0 ) ;
26
37
const isAtBottom = useSharedValue ( true ) ;
38
+ const viewportHeight = useViewportHeight ( ) ;
39
+
40
+ const AT_BOTTOM_THRESHOLD = useMemo (
41
+ ( ) => viewportHeight * atBottomThreshold ,
42
+ [ viewportHeight , atBottomThreshold ]
43
+ ) ;
27
44
28
45
return useAnimatedScrollHandler ( ( event ) => {
29
46
const { y } = event . contentOffset ;
@@ -40,14 +57,30 @@ export const useScrollDirectionTracker = (
40
57
41
58
previousScrollValue . value = y ;
42
59
43
- const atBottom = y <= 0 ;
60
+ const atBottom = y <= AT_BOTTOM_THRESHOLD ;
44
61
if ( isAtBottom . value !== atBottom ) {
45
62
isAtBottom . value = atBottom ;
46
63
runOnJS ( setIsAtBottom ) ( atBottom ) ;
47
64
}
48
65
} ) ;
49
66
} ;
50
67
68
+ function useViewportHeight ( ) {
69
+ const [ height , setHeight ] = useState (
70
+ Platform . OS === 'web' ? window . innerHeight : Dimensions . get ( 'window' ) . height
71
+ ) ;
72
+
73
+ useEffect ( ( ) => {
74
+ if ( Platform . OS === 'web' ) {
75
+ const handleResize = ( ) => setHeight ( window . innerHeight ) ;
76
+ window . addEventListener ( 'resize' , handleResize ) ;
77
+ return ( ) => window . removeEventListener ( 'resize' , handleResize ) ;
78
+ }
79
+ } , [ ] ) ;
80
+
81
+ return height ;
82
+ }
83
+
51
84
export const ScrollContextProvider : React . FC < React . PropsWithChildren > = ( {
52
85
children,
53
86
} ) => {
0 commit comments