import { ParamListBase, useNavigation } from '@react-navigation/native' import type { NativeStackNavigationProp } from '@react-navigation/native-stack' import React, { createContext, useContext, useEffect, useState } from 'react' import { Dimensions, Keyboard, KeyboardAvoidingView, Platform, StyleSheet, View, ViewProps, } from 'react-native' import { useSafeAreaInsets } from 'react-native-safe-area-context' import { useChatContext } from '../../contexts/chat_context' // Default true: outside a KeyboardView there's no measurement to wait for. const KeyboardViewReadyContext = createContext(true) export const useKeyboardViewReady = () => useContext(KeyboardViewReadyContext) export function KeyboardView({ children }: Pick) { const styles = useStyles() const isKeyboardOpen = useKeyboardOpen() const screenHeight = Dimensions.get('screen').height const [pageSheetGap, setPageSheetGap] = useState(0) const hasTransitionedIn = useHasTransitionedIn() const { bottom } = useSafeAreaInsets() const { edgeToEdge } = useChatContext() const behavior: 'padding' | 'height' | 'position' | undefined = Platform.select({ android: edgeToEdge ? 'padding' : undefined, ios: 'padding', }) return ( { const { height: viewHeight } = event.nativeEvent.layout setPageSheetGap(screenHeight - viewHeight) }} > {children} ) } const useHasTransitionedIn = () => { const navigation = useNavigation>() const [hasTransitionedIn, setHasTransitionedIn] = useState(false) useEffect(() => { return navigation.addListener('transitionEnd', event => { if (event.data.closing) return setHasTransitionedIn(true) }) }, [navigation]) return hasTransitionedIn } export const useKeyboardOpen = () => { const [open, setOpen] = useState(false) useEffect(() => { return Keyboard.addListener('keyboardDidShow', () => { setOpen(true) }).remove }, []) useEffect(() => { return Keyboard.addListener('keyboardDidHide', () => { setOpen(false) }).remove }, []) return open } const useStyles = () => { return StyleSheet.create({ pageGapView: { flex: 1, }, keyboardView: { flex: 1, }, }) }