You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

JitsiKeyboardAvoidingView.js 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // @flow
  2. import { useHeaderHeight } from '@react-navigation/elements';
  3. import React, { useCallback, useEffect, useState } from 'react';
  4. import {
  5. Keyboard,
  6. KeyboardAvoidingView,
  7. Platform,
  8. StatusBar
  9. } from 'react-native';
  10. import { useSafeAreaInsets } from 'react-native-safe-area-context';
  11. import { StyleType } from '../../styles';
  12. type Props = {
  13. /**
  14. * The children component(s) of the Modal, to be rendered.
  15. */
  16. children: React$Node,
  17. /**
  18. * Additional style to be appended to the KeyboardAvoidingView content container.
  19. */
  20. contentContainerStyle?: StyleType,
  21. /**
  22. * Is a text input rendered at the bottom of the screen?
  23. */
  24. hasBottomTextInput: boolean,
  25. /**
  26. * Is the screen rendering a tab navigator?
  27. */
  28. hasTabNavigator: boolean,
  29. /**
  30. * Additional style to be appended to the KeyboardAvoidingView.
  31. */
  32. style?: StyleType
  33. }
  34. const JitsiKeyboardAvoidingView = (
  35. {
  36. children,
  37. contentContainerStyle,
  38. hasTabNavigator,
  39. hasBottomTextInput,
  40. style
  41. }: Props) => {
  42. const headerHeight = useHeaderHeight();
  43. const insets = useSafeAreaInsets();
  44. const [ bottomPadding, setBottomPadding ] = useState(insets.bottom);
  45. useEffect(() => {
  46. // This useEffect is needed because insets are undefined at first for some reason
  47. // https://github.com/th3rdwave/react-native-safe-area-context/issues/54
  48. setBottomPadding(insets.bottom);
  49. }, [ insets.bottom ]);
  50. const tabNavigatorPadding
  51. = hasTabNavigator ? headerHeight : 0;
  52. const noNotchDevicePadding = bottomPadding || 10;
  53. const iosVerticalOffset
  54. = headerHeight + noNotchDevicePadding + tabNavigatorPadding;
  55. const androidVerticalOffset = hasBottomTextInput
  56. ? headerHeight + StatusBar.currentHeight : headerHeight;
  57. // Tells the view what to do with taps
  58. const shouldSetResponse = useCallback(() => true);
  59. const onRelease = useCallback(() => Keyboard.dismiss());
  60. return (
  61. <KeyboardAvoidingView
  62. behavior = { Platform.OS === 'ios' ? 'padding' : 'height' }
  63. contentContainerStyle = { contentContainerStyle }
  64. enabled = { true }
  65. keyboardVerticalOffset = {
  66. Platform.OS === 'ios'
  67. ? iosVerticalOffset
  68. : androidVerticalOffset
  69. }
  70. onResponderRelease = { onRelease }
  71. onStartShouldSetResponder = { shouldSetResponse }
  72. style = { style }>
  73. { children }
  74. </KeyboardAvoidingView>
  75. );
  76. };
  77. export default JitsiKeyboardAvoidingView;