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.

FooterContextMenu.tsx 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /* eslint-disable lines-around-comment */
  2. import { Theme } from '@mui/material';
  3. import React, { useCallback } from 'react';
  4. import { useTranslation } from 'react-i18next';
  5. import { useDispatch, useSelector } from 'react-redux';
  6. import { makeStyles } from 'tss-react/mui';
  7. import { IReduxState } from '../../../app/types';
  8. import {
  9. requestDisableAudioModeration,
  10. requestDisableVideoModeration,
  11. requestEnableAudioModeration,
  12. requestEnableVideoModeration
  13. } from '../../../av-moderation/actions';
  14. import {
  15. isEnabled as isAvModerationEnabled,
  16. isSupported as isAvModerationSupported
  17. } from '../../../av-moderation/functions';
  18. import { openDialog } from '../../../base/dialog/actions';
  19. import {
  20. IconCheck,
  21. IconHorizontalPoints,
  22. IconVideoOff
  23. } from '../../../base/icons/svg';
  24. import { MEDIA_TYPE } from '../../../base/media/constants';
  25. import {
  26. getParticipantCount,
  27. isEveryoneModerator
  28. } from '../../../base/participants/functions';
  29. import ContextMenu from '../../../base/ui/components/web/ContextMenu';
  30. import ContextMenuItemGroup from '../../../base/ui/components/web/ContextMenuItemGroup';
  31. import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
  32. import {
  33. openSettingsDialog,
  34. shouldShowModeratorSettings
  35. // @ts-ignore
  36. } from '../../../settings';
  37. import { SETTINGS_TABS } from '../../../settings/constants';
  38. // @ts-ignore
  39. import { MuteEveryonesVideoDialog } from '../../../video-menu/components';
  40. const useStyles = makeStyles()((theme: Theme) => {
  41. return {
  42. contextMenu: {
  43. bottom: 'auto',
  44. margin: '0',
  45. right: 0,
  46. top: '-8px',
  47. transform: 'translateY(-100%)',
  48. width: '283px'
  49. },
  50. text: {
  51. color: theme.palette.text02,
  52. padding: '10px 16px',
  53. height: '40px',
  54. overflow: 'hidden',
  55. display: 'flex',
  56. alignItems: 'center',
  57. boxSizing: 'border-box'
  58. },
  59. indentedLabel: {
  60. '& > span': {
  61. marginLeft: '36px'
  62. }
  63. }
  64. };
  65. });
  66. type Props = {
  67. /**
  68. * Whether the menu is open.
  69. */
  70. isOpen: boolean;
  71. /**
  72. * Drawer close callback.
  73. */
  74. onDrawerClose: (e?: React.MouseEvent) => void;
  75. /**
  76. * Callback for the mouse leaving this item.
  77. */
  78. onMouseLeave?: (e?: React.MouseEvent) => void;
  79. };
  80. export const FooterContextMenu = ({ isOpen, onDrawerClose, onMouseLeave }: Props) => {
  81. const dispatch = useDispatch();
  82. const isModerationSupported = useSelector((state: IReduxState) => isAvModerationSupported()(state));
  83. const allModerators = useSelector(isEveryoneModerator);
  84. const isModeratorSettingsTabEnabled = useSelector(shouldShowModeratorSettings);
  85. const participantCount = useSelector(getParticipantCount);
  86. const isAudioModerationEnabled = useSelector(isAvModerationEnabled(MEDIA_TYPE.AUDIO));
  87. const isVideoModerationEnabled = useSelector(isAvModerationEnabled(MEDIA_TYPE.VIDEO));
  88. const isBreakoutRoom = useSelector(isInBreakoutRoom);
  89. const { t } = useTranslation();
  90. const disableAudioModeration = useCallback(() => dispatch(requestDisableAudioModeration()), [ dispatch ]);
  91. const disableVideoModeration = useCallback(() => dispatch(requestDisableVideoModeration()), [ dispatch ]);
  92. const enableAudioModeration = useCallback(() => dispatch(requestEnableAudioModeration()), [ dispatch ]);
  93. const enableVideoModeration = useCallback(() => dispatch(requestEnableVideoModeration()), [ dispatch ]);
  94. const { classes } = useStyles();
  95. const muteAllVideo = useCallback(
  96. () => dispatch(openDialog(MuteEveryonesVideoDialog)), [ dispatch ]);
  97. const openModeratorSettings = () => dispatch(openSettingsDialog(SETTINGS_TABS.MODERATOR));
  98. const actions = [
  99. {
  100. accessibilityLabel: t('participantsPane.actions.audioModeration'),
  101. className: isAudioModerationEnabled ? classes.indentedLabel : '',
  102. id: isAudioModerationEnabled
  103. ? 'participants-pane-context-menu-stop-audio-moderation'
  104. : 'participants-pane-context-menu-start-audio-moderation',
  105. icon: !isAudioModerationEnabled && IconCheck,
  106. onClick: isAudioModerationEnabled ? disableAudioModeration : enableAudioModeration,
  107. text: t('participantsPane.actions.audioModeration')
  108. }, {
  109. accessibilityLabel: t('participantsPane.actions.videoModeration'),
  110. className: isVideoModerationEnabled ? classes.indentedLabel : '',
  111. id: isVideoModerationEnabled
  112. ? 'participants-pane-context-menu-stop-video-moderation'
  113. : 'participants-pane-context-menu-start-video-moderation',
  114. icon: !isVideoModerationEnabled && IconCheck,
  115. onClick: isVideoModerationEnabled ? disableVideoModeration : enableVideoModeration,
  116. text: t('participantsPane.actions.videoModeration')
  117. }
  118. ];
  119. return (
  120. <ContextMenu
  121. className = { classes.contextMenu }
  122. hidden = { !isOpen }
  123. isDrawerOpen = { isOpen }
  124. onDrawerClose = { onDrawerClose }
  125. onMouseLeave = { onMouseLeave }>
  126. <ContextMenuItemGroup
  127. actions = { [ {
  128. accessibilityLabel: t('participantsPane.actions.stopEveryonesVideo'),
  129. id: 'participants-pane-context-menu-stop-video',
  130. icon: IconVideoOff,
  131. onClick: muteAllVideo,
  132. text: t('participantsPane.actions.stopEveryonesVideo')
  133. } ] } />
  134. {!isBreakoutRoom && isModerationSupported && (participantCount === 1 || !allModerators) && (
  135. <ContextMenuItemGroup actions = { actions }>
  136. <div className = { classes.text }>
  137. <span>{t('participantsPane.actions.allow')}</span>
  138. </div>
  139. </ContextMenuItemGroup>
  140. )}
  141. {isModeratorSettingsTabEnabled && (
  142. <ContextMenuItemGroup
  143. actions = { [ {
  144. accessibilityLabel: t('participantsPane.actions.moreModerationControls'),
  145. id: 'participants-pane-open-moderation-control-settings',
  146. icon: IconHorizontalPoints,
  147. onClick: openModeratorSettings,
  148. text: t('participantsPane.actions.moreModerationControls')
  149. } ] } />
  150. )}
  151. </ContextMenu>
  152. );
  153. };