mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import {
2 createContext,
3 useCallback,
4 useContext,
5 useEffect,
6 useMemo,
7 useRef,
8} from 'react'
9import {
10 KeyboardProvider,
11 useKeyboardController,
12} from 'react-native-keyboard-controller'
13import {useFocusEffect} from '@react-navigation/native'
14
15import {IS_DEV} from '#/env'
16
17const KeyboardControllerRefCountContext = createContext<{
18 incrementRefCount: () => void
19 decrementRefCount: () => void
20}>({
21 incrementRefCount: () => {},
22 decrementRefCount: () => {},
23})
24
25export function KeyboardControllerProvider({
26 children,
27}: {
28 children: React.ReactNode
29}) {
30 return (
31 <KeyboardProvider
32 enabled={false}
33 // I don't think this is necessary, but Chesterton's fence and all that -sfn
34 statusBarTranslucent={true}>
35 <KeyboardControllerProviderInner>
36 {children}
37 </KeyboardControllerProviderInner>
38 </KeyboardProvider>
39 )
40}
41
42function KeyboardControllerProviderInner({
43 children,
44}: {
45 children: React.ReactNode
46}) {
47 const {setEnabled} = useKeyboardController()
48 const refCount = useRef(0)
49
50 const value = useMemo(
51 () => ({
52 incrementRefCount: () => {
53 refCount.current++
54 setEnabled(refCount.current > 0)
55 },
56 decrementRefCount: () => {
57 refCount.current--
58 setEnabled(refCount.current > 0)
59
60 if (IS_DEV && refCount.current < 0) {
61 console.error('KeyboardController ref count < 0')
62 }
63 },
64 }),
65 [setEnabled],
66 )
67
68 return (
69 <KeyboardControllerRefCountContext.Provider value={value}>
70 {children}
71 </KeyboardControllerRefCountContext.Provider>
72 )
73}
74
75export function useEnableKeyboardController(shouldEnable: boolean) {
76 const {incrementRefCount, decrementRefCount} = useContext(
77 KeyboardControllerRefCountContext,
78 )
79
80 useEffect(() => {
81 if (!shouldEnable) {
82 return
83 }
84 incrementRefCount()
85 return () => {
86 decrementRefCount()
87 }
88 }, [shouldEnable, incrementRefCount, decrementRefCount])
89}
90
91/**
92 * Like `useEnableKeyboardController`, but using `useFocusEffect`
93 */
94export function useEnableKeyboardControllerScreen(shouldEnable: boolean) {
95 const {incrementRefCount, decrementRefCount} = useContext(
96 KeyboardControllerRefCountContext,
97 )
98
99 useFocusEffect(
100 useCallback(() => {
101 if (!shouldEnable) {
102 return
103 }
104 incrementRefCount()
105 return () => {
106 decrementRefCount()
107 }
108 }, [shouldEnable, incrementRefCount, decrementRefCount]),
109 )
110}