about summary refs log tree commit diff
path: root/src/lib/hooks
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/hooks')
-rw-r--r--src/lib/hooks/useEnableKeyboardController.tsx110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/lib/hooks/useEnableKeyboardController.tsx b/src/lib/hooks/useEnableKeyboardController.tsx
new file mode 100644
index 000000000..c7205d016
--- /dev/null
+++ b/src/lib/hooks/useEnableKeyboardController.tsx
@@ -0,0 +1,110 @@
+import {
+  createContext,
+  useCallback,
+  useContext,
+  useEffect,
+  useMemo,
+  useRef,
+} from 'react'
+import {
+  KeyboardProvider,
+  useKeyboardController,
+} from 'react-native-keyboard-controller'
+import {useFocusEffect} from '@react-navigation/native'
+
+import {IS_DEV} from '#/env'
+
+const KeyboardControllerRefCountContext = createContext<{
+  incrementRefCount: () => void
+  decrementRefCount: () => void
+}>({
+  incrementRefCount: () => {},
+  decrementRefCount: () => {},
+})
+
+export function KeyboardControllerProvider({
+  children,
+}: {
+  children: React.ReactNode
+}) {
+  return (
+    <KeyboardProvider
+      enabled={false}
+      // I don't think this is necessary, but Chesterton's fence and all that -sfn
+      statusBarTranslucent={true}>
+      <KeyboardControllerProviderInner>
+        {children}
+      </KeyboardControllerProviderInner>
+    </KeyboardProvider>
+  )
+}
+
+function KeyboardControllerProviderInner({
+  children,
+}: {
+  children: React.ReactNode
+}) {
+  const {setEnabled} = useKeyboardController()
+  const refCount = useRef(0)
+
+  const value = useMemo(
+    () => ({
+      incrementRefCount: () => {
+        refCount.current++
+        setEnabled(refCount.current > 0)
+      },
+      decrementRefCount: () => {
+        refCount.current--
+        setEnabled(refCount.current > 0)
+
+        if (IS_DEV && refCount.current < 0) {
+          console.error('KeyboardController ref count < 0')
+        }
+      },
+    }),
+    [setEnabled],
+  )
+
+  return (
+    <KeyboardControllerRefCountContext.Provider value={value}>
+      {children}
+    </KeyboardControllerRefCountContext.Provider>
+  )
+}
+
+export function useEnableKeyboardController(shouldEnable: boolean) {
+  const {incrementRefCount, decrementRefCount} = useContext(
+    KeyboardControllerRefCountContext,
+  )
+
+  useEffect(() => {
+    if (!shouldEnable) {
+      return
+    }
+    incrementRefCount()
+    return () => {
+      decrementRefCount()
+    }
+  }, [shouldEnable, incrementRefCount, decrementRefCount])
+}
+
+/**
+ * Like `useEnableKeyboardController`, but using `useFocusEffect`
+ */
+export function useEnableKeyboardControllerScreen(shouldEnable: boolean) {
+  const {incrementRefCount, decrementRefCount} = useContext(
+    KeyboardControllerRefCountContext,
+  )
+
+  useFocusEffect(
+    useCallback(() => {
+      if (!shouldEnable) {
+        return
+      }
+      incrementRefCount()
+      return () => {
+        decrementRefCount()
+      }
+    }, [shouldEnable, incrementRefCount, decrementRefCount]),
+  )
+}