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.tsx 2.2KB

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