Moderator: Mute or stop video for a peer globally (#316)

auto_join_3.3
L4ky 2020-05-08 00:23:16 +02:00 committed by GitHub
parent 837aa1ace2
commit 2eab32cafa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 168 additions and 0 deletions

View File

@ -1389,6 +1389,46 @@ export default class RoomClient
peerActions.setPeerKickInProgress(peerId, false)); peerActions.setPeerKickInProgress(peerId, false));
} }
async mutePeer(peerId)
{
logger.debug('mutePeer() [peerId:"%s"]', peerId);
store.dispatch(
peerActions.setMutePeerInProgress(peerId, true));
try
{
await this.sendRequest('moderator:mute', { peerId });
}
catch (error)
{
logger.error('mutePeer() failed: %o', error);
}
store.dispatch(
peerActions.setMutePeerInProgress(peerId, false));
}
async stopPeerVideo(peerId)
{
logger.debug('stopPeerVideo() [peerId:"%s"]', peerId);
store.dispatch(
peerActions.setStopPeerVideoInProgress(peerId, true));
try
{
await this.sendRequest('moderator:stopVideo', { peerId });
}
catch (error)
{
logger.error('stopPeerVideo() failed: %o', error);
}
store.dispatch(
peerActions.setStopPeerVideoInProgress(peerId, false));
}
async muteAllPeers() async muteAllPeers()
{ {
logger.debug('muteAllPeers()'); logger.debug('muteAllPeers()');

View File

@ -69,3 +69,15 @@ export const setPeerKickInProgress = (peerId, flag) =>
type : 'SET_PEER_KICK_IN_PROGRESS', type : 'SET_PEER_KICK_IN_PROGRESS',
payload : { peerId, flag } payload : { peerId, flag }
}); });
export const setMutePeerInProgress = (peerId, flag) =>
({
type : 'STOP_PEER_AUDIO_IN_PROGRESS',
payload : { peerId, flag }
});
export const setStopPeerVideoInProgress = (peerId, flag) =>
({
type : 'STOP_PEER_VIDEO_IN_PROGRESS',
payload : { peerId, flag }
});

View File

@ -11,6 +11,8 @@ import IconButton from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip'; import Tooltip from '@material-ui/core/Tooltip';
import VideocamIcon from '@material-ui/icons/Videocam'; import VideocamIcon from '@material-ui/icons/Videocam';
import VideocamOffIcon from '@material-ui/icons/VideocamOff'; import VideocamOffIcon from '@material-ui/icons/VideocamOff';
import MicIcon from '@material-ui/icons/Mic';
import MicOffIcon from '@material-ui/icons/MicOff';
import VolumeUpIcon from '@material-ui/icons/VolumeUp'; import VolumeUpIcon from '@material-ui/icons/VolumeUp';
import VolumeOffIcon from '@material-ui/icons/VolumeOff'; import VolumeOffIcon from '@material-ui/icons/VolumeOff';
import ScreenIcon from '@material-ui/icons/ScreenShare'; import ScreenIcon from '@material-ui/icons/ScreenShare';
@ -250,6 +252,60 @@ const ListPeer = (props) =>
</IconButton> </IconButton>
</Tooltip> </Tooltip>
} }
{ isModerator && micConsumer &&
<Tooltip
title={intl.formatMessage({
id : 'tooltip.muteParticipant',
defaultMessage : 'Mute globally participant mic'
})}
placement='bottom'
>
<IconButton
className={classes.buttons}
style={{ color: green[500] }}
disabled={!isModerator || peer.stopPeerAudioInProgress}
onClick={(e) =>
{
e.stopPropagation();
roomClient.mutePeer(peer.id);
}}
>
{ !micConsumer.remotelyPaused ?
<MicIcon />
:
<MicOffIcon />
}
</IconButton>
</Tooltip>
}
{ isModerator && webcamConsumer &&
<Tooltip
title={intl.formatMessage({
id : 'tooltip.muteParticipantVideo',
defaultMessage : 'Mute globally participant video'
})}
placement='bottom'
>
<IconButton
className={classes.buttons}
style={{ color: green[500] }}
disabled={!isModerator || peer.stopPeerVideoInProgress}
onClick={(e) =>
{
e.stopPropagation();
roomClient.stopPeerVideo(peer.id);
}}
>
{ !webcamConsumer.remotelyPaused ?
<VideocamIcon />
:
<VideocamOffIcon />
}
</IconButton>
</Tooltip>
}
{children} {children}
</div> </div>
); );

View File

@ -68,6 +68,18 @@ const peer = (state = {}, action) =>
return { ...state, roles }; return { ...state, roles };
} }
case 'STOP_PEER_AUDIO_IN_PROGRESS':
return {
...state,
stopPeerAudioInProgress : action.payload.flag
};
case 'STOP_PEER_VIDEO_IN_PROGRESS':
return {
...state,
stopPeerVideoInProgress : action.payload.flag
};
default: default:
return state; return state;
} }
@ -102,6 +114,8 @@ const peers = (state = {}, action) =>
case 'ADD_CONSUMER': case 'ADD_CONSUMER':
case 'ADD_PEER_ROLE': case 'ADD_PEER_ROLE':
case 'REMOVE_PEER_ROLE': case 'REMOVE_PEER_ROLE':
case 'STOP_PEER_AUDIO_IN_PROGRESS':
case 'STOP_PEER_VIDEO_IN_PROGRESS':
{ {
const oldPeer = state[action.payload.peerId]; const oldPeer = state[action.payload.peerId];

View File

@ -1369,6 +1369,29 @@ class Room extends EventEmitter
break; break;
} }
case 'moderator:mute':
{
if (
!peer.roles.some(
(role) => permissionsFromRoles.MODERATE_ROOM.includes(role)
)
)
throw new Error('peer not authorized');
const { peerId } = request.data;
const mutePeer = this._peers[peerId];
if (!mutePeer)
throw new Error(`peer with id "${peerId}" not found`);
this._notification(mutePeer.socket, 'moderator:mute');
cb();
break;
}
case 'moderator:muteAll': case 'moderator:muteAll':
{ {
if ( if (
@ -1386,6 +1409,29 @@ class Room extends EventEmitter
break; break;
} }
case 'moderator:stopVideo':
{
if (
!peer.roles.some(
(role) => permissionsFromRoles.MODERATE_ROOM.includes(role)
)
)
throw new Error('peer not authorized');
const { peerId } = request.data;
const stopVideoPeer = this._peers[peerId];
if (!stopVideoPeer)
throw new Error(`peer with id "${peerId}" not found`);
this._notification(stopVideoPeer.socket, 'moderator:stopVideo');
cb();
break;
}
case 'moderator:stopAllVideo': case 'moderator:stopAllVideo':
{ {
if ( if (