1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
import {useState, useCallback, useRef} from 'react'
import {NativeSyntheticEvent, NativeScrollEvent} from 'react-native'
import {s} from 'lib/styles'
import {useWebMediaQueries} from './useWebMediaQueries'
import {useSetMinimalShellMode, useMinimalShellMode} from '#/state/shell'
const Y_LIMIT = 10
const useDeviceLimits = () => {
const {isDesktop} = useWebMediaQueries()
return {
dyLimitUp: isDesktop ? 30 : 10,
dyLimitDown: isDesktop ? 150 : 10,
}
}
export type OnScrollCb = (
event: NativeSyntheticEvent<NativeScrollEvent>,
) => void
export type ResetCb = () => void
export function useOnMainScroll(): [OnScrollCb, boolean, ResetCb] {
let lastY = useRef(0)
let [isScrolledDown, setIsScrolledDown] = useState(false)
const {dyLimitUp, dyLimitDown} = useDeviceLimits()
const minimalShellMode = useMinimalShellMode()
const setMinimalShellMode = useSetMinimalShellMode()
return [
useCallback(
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
const y = event.nativeEvent.contentOffset.y
const dy = y - (lastY.current || 0)
lastY.current = y
if (!minimalShellMode && dy > dyLimitDown && y > Y_LIMIT) {
setMinimalShellMode(true)
} else if (minimalShellMode && (dy < dyLimitUp * -1 || y <= Y_LIMIT)) {
setMinimalShellMode(false)
}
if (
!isScrolledDown &&
event.nativeEvent.contentOffset.y > s.window.height
) {
setIsScrolledDown(true)
} else if (
isScrolledDown &&
event.nativeEvent.contentOffset.y < s.window.height
) {
setIsScrolledDown(false)
}
},
[
dyLimitDown,
dyLimitUp,
isScrolledDown,
minimalShellMode,
setMinimalShellMode,
],
),
isScrolledDown,
useCallback(() => {
setIsScrolledDown(false)
setMinimalShellMode(false)
lastY.current = 1e8 // NOTE we set this very high so that the onScroll logic works right -prf
}, [setIsScrolledDown, setMinimalShellMode]),
]
}
|