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.

KeyboardAvoider.js 1.6KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. // @flow
  2. import React, { useEffect, useState } from 'react';
  3. import { isIosMobileBrowser } from '../../../base/environment/utils';
  4. /**
  5. * Component that renders an element to lift the chat input above the Safari keyboard,
  6. * computing the appropriate height comparisons based on the {@code visualViewport}.
  7. *
  8. * @returns {ReactElement}
  9. */
  10. function KeyboardAvoider() {
  11. if (!isIosMobileBrowser()) {
  12. return null;
  13. }
  14. const [ elementHeight, setElementHeight ] = useState(0);
  15. const [ storedHeight, setStoredHeight ] = useState(window.innerHeight);
  16. /**
  17. * Handles the resizing of the visual viewport in order to compute
  18. * the {@code KeyboardAvoider}'s height.
  19. *
  20. * @returns {void}
  21. */
  22. function handleViewportResize() {
  23. const { innerWidth, visualViewport: { width, height } } = window;
  24. // Compare the widths to make sure the {@code visualViewport} didn't resize due to zooming.
  25. if (width === innerWidth) {
  26. if (height < storedHeight) {
  27. setElementHeight(storedHeight - height);
  28. } else {
  29. setElementHeight(0);
  30. }
  31. setStoredHeight(height);
  32. }
  33. }
  34. useEffect(() => {
  35. // Call the handler in case the keyboard is open when the {@code KeyboardAvoider} is mounted.
  36. handleViewportResize();
  37. window.visualViewport.addEventListener('resize', handleViewportResize);
  38. return () => {
  39. window.visualViewport.removeEventListener('resize', handleViewportResize);
  40. };
  41. }, []);
  42. return <div style = {{ height: `${elementHeight}px` }} />;
  43. }
  44. export default KeyboardAvoider;