Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

Whiteboard.tsx 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import { ExcalidrawApp } from '@jitsi/excalidraw';
  2. import clsx from 'clsx';
  3. import React, { useCallback, useEffect, useRef } from 'react';
  4. import { WithTranslation } from 'react-i18next';
  5. import { useSelector } from 'react-redux';
  6. // @ts-expect-error
  7. import Filmstrip from '../../../../../modules/UI/videolayout/Filmstrip';
  8. import { IReduxState } from '../../../app/types';
  9. import { translate } from '../../../base/i18n/functions';
  10. import { getLocalParticipant } from '../../../base/participants/functions';
  11. import { getVerticalViewMaxWidth } from '../../../filmstrip/functions.web';
  12. import { getToolboxHeight } from '../../../toolbox/functions.web';
  13. import { shouldDisplayTileView } from '../../../video-layout/functions.any';
  14. import { WHITEBOARD_UI_OPTIONS } from '../../constants';
  15. import {
  16. getCollabDetails,
  17. getCollabServerUrl,
  18. isWhiteboardOpen,
  19. isWhiteboardVisible
  20. } from '../../functions';
  21. /**
  22. * Space taken by meeting elements like the subject and the watermark.
  23. */
  24. const HEIGHT_OFFSET = 80;
  25. interface IDimensions {
  26. /* The height of the component. */
  27. height: string;
  28. /* The width of the component. */
  29. width: string;
  30. }
  31. /**
  32. * The Whiteboard component.
  33. *
  34. * @param {Props} props - The React props passed to this component.
  35. * @returns {JSX.Element} - The React component.
  36. */
  37. const Whiteboard = (props: WithTranslation): JSX.Element => {
  38. const excalidrawRef = useRef<any>(null);
  39. const collabAPIRef = useRef<any>(null);
  40. const isOpen = useSelector(isWhiteboardOpen);
  41. const isVisible = useSelector(isWhiteboardVisible);
  42. const isInTileView = useSelector(shouldDisplayTileView);
  43. const { clientHeight, clientWidth } = useSelector((state: IReduxState) => state['features/base/responsive-ui']);
  44. const { visible: filmstripVisible, isResizing } = useSelector((state: IReduxState) => state['features/filmstrip']);
  45. const filmstripWidth: number = useSelector(getVerticalViewMaxWidth);
  46. const collabDetails = useSelector(getCollabDetails);
  47. const collabServerUrl = useSelector(getCollabServerUrl);
  48. const { defaultRemoteDisplayName } = useSelector((state: IReduxState) => state['features/base/config']);
  49. const localParticipantName = useSelector(getLocalParticipant)?.name || defaultRemoteDisplayName || 'Fellow Jitster';
  50. useEffect(() => {
  51. if (!collabAPIRef.current) {
  52. return;
  53. }
  54. collabAPIRef.current.setUsername(localParticipantName);
  55. }, [ localParticipantName ]);
  56. /**
  57. * Computes the width and the height of the component.
  58. *
  59. * @returns {IDimensions} - The dimensions of the component.
  60. */
  61. const getDimensions = (): IDimensions => {
  62. let width: number;
  63. let height: number;
  64. if (interfaceConfig.VERTICAL_FILMSTRIP) {
  65. if (filmstripVisible) {
  66. width = clientWidth - filmstripWidth;
  67. } else {
  68. width = clientWidth;
  69. }
  70. height = clientHeight - getToolboxHeight();
  71. } else {
  72. if (filmstripVisible) {
  73. height = clientHeight - Filmstrip.getFilmstripHeight();
  74. } else {
  75. height = clientHeight;
  76. }
  77. width = clientWidth;
  78. }
  79. return {
  80. width: `${width}px`,
  81. height: `${height - HEIGHT_OFFSET}px`
  82. };
  83. };
  84. const getCollabAPI = useCallback(collabAPI => {
  85. if (collabAPIRef.current) {
  86. return;
  87. }
  88. collabAPIRef.current = collabAPI;
  89. collabAPIRef.current.setUsername(localParticipantName);
  90. }, [ localParticipantName ]);
  91. return (
  92. <div
  93. className = { clsx(
  94. isResizing && 'disable-pointer',
  95. 'whiteboard-container'
  96. ) }
  97. style = {{
  98. ...getDimensions(),
  99. marginTop: `${HEIGHT_OFFSET}px`,
  100. display: `${isInTileView || !isVisible ? 'none' : 'block'}`
  101. }}>
  102. {
  103. isOpen && (
  104. <div className = 'excalidraw-wrapper'>
  105. {/*
  106. * Excalidraw renders a few lvl 2 headings. This is
  107. * quite fortunate, because we actually use lvl 1
  108. * headings to mark the big sections of our app. So make
  109. * sure to mark the Excalidraw context with a lvl 1
  110. * heading before showing the whiteboard.
  111. */
  112. <span
  113. aria-level = { 1 }
  114. className = 'sr-only'
  115. role = 'heading'>
  116. { props.t('whiteboard.accessibilityLabel.heading') }
  117. </span>
  118. }
  119. <ExcalidrawApp
  120. collabDetails = { collabDetails }
  121. collabServerUrl = { collabServerUrl }
  122. excalidraw = {{
  123. isCollaborating: true,
  124. // @ts-ignore
  125. ref: excalidrawRef,
  126. theme: 'light',
  127. UIOptions: WHITEBOARD_UI_OPTIONS
  128. }}
  129. getCollabAPI = { getCollabAPI } />
  130. </div>
  131. )
  132. }
  133. </div>
  134. );
  135. };
  136. export default translate(Whiteboard);