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.

TouchmoveHack.js 2.2KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // @flow
  2. import { makeStyles } from '@material-ui/core/styles';
  3. import clsx from 'clsx';
  4. import React, { useEffect, useRef } from 'react';
  5. import { isMobileBrowser } from '../../../base/environment/utils';
  6. type Props = {
  7. /**
  8. * The component(s) that need to be scrollable on mobile.
  9. */
  10. children: React$Node,
  11. /**
  12. * Whether the component should be flex container or not.
  13. */
  14. flex?: boolean,
  15. /**
  16. * Whether the component is rendered within a modal.
  17. */
  18. isModal: boolean,
  19. };
  20. const useStyles = makeStyles(() => {
  21. return {
  22. flex: {
  23. display: 'flex',
  24. flex: 1
  25. },
  26. base: {
  27. height: '100%',
  28. overflow: 'auto'
  29. }
  30. };
  31. });
  32. /**
  33. * Component that disables {@code touchmove} propagation below it.
  34. *
  35. * @returns {ReactElement}
  36. */
  37. function TouchmoveHack({ children, isModal, flex }: Props) {
  38. if (!isModal || !isMobileBrowser()) {
  39. return children;
  40. }
  41. const touchMoveElementRef = useRef(null);
  42. /**
  43. * Atlaskit's {@code Modal} uses a third party library to disable touchmove events
  44. * which makes scrolling inside dialogs impossible. We therefore employ this hack
  45. * to intercept and stop the propagation of touchmove events from this wrapper that
  46. * is placed around the chat conversation from the {@code ChatDialog}.
  47. *
  48. * @param {Event} event - The touchmove event fired within the component.
  49. * @returns {void}
  50. */
  51. function handleTouchMove(event: TouchEvent) {
  52. event.stopImmediatePropagation();
  53. }
  54. useEffect(() => {
  55. if (touchMoveElementRef && touchMoveElementRef.current) {
  56. touchMoveElementRef.current.addEventListener('touchmove', handleTouchMove, true);
  57. }
  58. return () => {
  59. if (touchMoveElementRef && touchMoveElementRef.current) {
  60. touchMoveElementRef.current.removeEventListener('touchmove', handleTouchMove, true);
  61. }
  62. };
  63. }, []);
  64. const classes = useStyles();
  65. return (
  66. <div
  67. className = { clsx(classes.base, flex && classes.flex) }
  68. ref = { touchMoveElementRef }>
  69. {children}
  70. </div>
  71. );
  72. }
  73. export default TouchmoveHack;