diff --git a/react/features/participants-pane/components/ParticipantQuickAction.js b/react/features/participants-pane/components/ParticipantQuickAction.js index 7d957fdd0..1c5990a4a 100644 --- a/react/features/participants-pane/components/ParticipantQuickAction.js +++ b/react/features/participants-pane/components/ParticipantQuickAction.js @@ -63,12 +63,15 @@ export default function ParticipantQuickAction({ ); } - default: { + case QUICK_ACTION_BUTTON.ASK_TO_UNMUTE: { return ( ); } + default: { + return null; + } } } diff --git a/react/features/participants-pane/components/web/MeetingParticipantItem.js b/react/features/participants-pane/components/web/MeetingParticipantItem.js index 0f8cf4218..1dec1d95e 100644 --- a/react/features/participants-pane/components/web/MeetingParticipantItem.js +++ b/react/features/participants-pane/components/web/MeetingParticipantItem.js @@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useState } from 'react'; +import { isSupported } from '../../../av-moderation/functions'; import { translate } from '../../../base/i18n'; import { JitsiTrackEvents } from '../../../base/lib-jitsi-meet'; import { MEDIA_TYPE } from '../../../base/media'; @@ -9,6 +10,7 @@ import { getLocalParticipant, getParticipantByIdOrUndefined, getParticipantDisplayName, + isLocalParticipantModerator, isParticipantModerator } from '../../../base/participants'; import { connect } from '../../../base/redux'; @@ -18,7 +20,7 @@ import { isParticipantAudioMuted, isParticipantVideoMuted } from '../../../base/tracks'; -import { ACTION_TRIGGER, type MediaState, MEDIA_STATE } from '../../constants'; +import { ACTION_TRIGGER, type MediaState, MEDIA_STATE, QUICK_ACTION_BUTTON } from '../../constants'; import { getParticipantAudioMediaState, getParticipantVideoMediaState, @@ -51,11 +53,21 @@ type Props = { */ _displayName: string, + /** + * Whether or not moderation is supported. + */ + _isModerationSupported: boolean, + /** * True if the participant is the local participant. */ _local: Boolean, + /** + * Whether or not the local participant is moderator. + */ + _localModerator: boolean, + /** * Shared video local participant owner. */ @@ -162,7 +174,9 @@ function MeetingParticipantItem({ _audioTrack, _disableModeratorIndicator, _displayName, + _isModerationSupported, _local, + _localModerator, _localVideoOwner, _participant, _participantID, @@ -220,6 +234,10 @@ function MeetingParticipantItem({ askToUnmuteText = t('participantsPane.actions.allowVideo'); } + const buttonType = _isModerationSupported + ? _localModerator ? QUICK_ACTION_BUTTON.ASK_TO_UNMUTE : _quickActionButtonType + : ''; + return ( @@ -287,12 +305,16 @@ function _mapStateToProps(state, ownProps): Object { const { disableModeratorIndicator } = state['features/base/config']; + const _localModerator = isLocalParticipantModerator(state); + return { _audioMediaState, _audioTrack, _disableModeratorIndicator: disableModeratorIndicator, _displayName: getParticipantDisplayName(state, participant?.id), + _isModerationSupported: isSupported()(state), _local: Boolean(participant?.local), + _localModerator, _localVideoOwner: Boolean(ownerId === localParticipantId), _participant: participant, _participantID: participant?.id, diff --git a/react/features/video-menu/components/AbstractMuteEveryoneDialog.js b/react/features/video-menu/components/AbstractMuteEveryoneDialog.js index 7a80c7e82..53c35d9ae 100644 --- a/react/features/video-menu/components/AbstractMuteEveryoneDialog.js +++ b/react/features/video-menu/components/AbstractMuteEveryoneDialog.js @@ -3,7 +3,7 @@ import React from 'react'; import { requestDisableAudioModeration, requestEnableAudioModeration } from '../../av-moderation/actions'; -import { isEnabledFromState } from '../../av-moderation/functions'; +import { isEnabledFromState, isSupported } from '../../av-moderation/functions'; import { Dialog } from '../../base/dialog'; import { MEDIA_TYPE } from '../../base/media'; import { getLocalParticipant, getParticipantDisplayName } from '../../base/participants'; @@ -23,7 +23,8 @@ export type Props = AbstractProps & { exclude: Array, title: string, showAdvancedModerationToggle: boolean, - isAudioModerationEnabled: boolean + isAudioModerationEnabled: boolean, + isModerationSupported: boolean }; type State = { @@ -135,6 +136,7 @@ export function abstractMapStateToProps(state: Object, ownProps: Props) { title: t('dialog.muteEveryoneElseTitle', { whom }) } : { title: t('dialog.muteEveryoneTitle'), - isAudioModerationEnabled: isEnabledFromState(MEDIA_TYPE.AUDIO, state) + isAudioModerationEnabled: isEnabledFromState(MEDIA_TYPE.AUDIO, state), + isModerationSupported: isSupported()(state) }; } diff --git a/react/features/video-menu/components/AbstractMuteEveryonesVideoDialog.js b/react/features/video-menu/components/AbstractMuteEveryonesVideoDialog.js index 129977d31..d1fb8cf95 100644 --- a/react/features/video-menu/components/AbstractMuteEveryonesVideoDialog.js +++ b/react/features/video-menu/components/AbstractMuteEveryonesVideoDialog.js @@ -3,7 +3,7 @@ import React from 'react'; import { requestDisableVideoModeration, requestEnableVideoModeration } from '../../av-moderation/actions'; -import { isEnabledFromState } from '../../av-moderation/functions'; +import { isEnabledFromState, isSupported } from '../../av-moderation/functions'; import { Dialog } from '../../base/dialog'; import { MEDIA_TYPE } from '../../base/media'; import { getLocalParticipant, getParticipantDisplayName } from '../../base/participants'; @@ -23,7 +23,8 @@ export type Props = AbstractProps & { exclude: Array, title: string, showAdvancedModerationToggle: boolean, - isVideoModerationEnabled: boolean + isVideoModerationEnabled: boolean, + isModerationSupported: boolean }; type State = { @@ -137,6 +138,7 @@ export function abstractMapStateToProps(state: Object, ownProps: Props) { title: t('dialog.muteEveryoneElsesVideoTitle', { whom }) } : { title: t('dialog.muteEveryonesVideoTitle'), - isVideoModerationEnabled + isVideoModerationEnabled, + isModerationSupported: isSupported()(state) }; } diff --git a/react/features/video-menu/components/web/MuteEveryoneDialog.js b/react/features/video-menu/components/web/MuteEveryoneDialog.js index 281b436d8..6afb7a86f 100644 --- a/react/features/video-menu/components/web/MuteEveryoneDialog.js +++ b/react/features/video-menu/components/web/MuteEveryoneDialog.js @@ -48,7 +48,7 @@ class MuteEveryoneDialog extends AbstractMuteEveryoneDialog { width = 'small'>
{ this.state.content } - {this.props.exclude.length === 0 && ( + { this.props.isModerationSupported && this.props.exclude.length === 0 && ( <>
diff --git a/react/features/video-menu/components/web/MuteEveryonesVideoDialog.js b/react/features/video-menu/components/web/MuteEveryonesVideoDialog.js index e4bc7d37c..2bb76b176 100644 --- a/react/features/video-menu/components/web/MuteEveryonesVideoDialog.js +++ b/react/features/video-menu/components/web/MuteEveryonesVideoDialog.js @@ -48,7 +48,7 @@ class MuteEveryonesVideoDialog extends AbstractMuteEveryonesVideoDialog { width = 'small'>
{this.state.content} - {this.props.exclude.length === 0 && ( + { this.props.isModerationSupported && this.props.exclude.length === 0 && ( <>