ref(StatusIndicators): Use video muted from redux.

This commit is contained in:
Hristo Terezov 2020-10-23 17:48:56 -05:00
parent 3657c19e60
commit ca2343c31a
9 changed files with 58 additions and 42 deletions

View File

@ -3039,7 +3039,7 @@ export default {
* @param {boolean} muted - New muted status. * @param {boolean} muted - New muted status.
*/ */
setVideoMuteStatus(muted) { setVideoMuteStatus(muted) {
APP.UI.setVideoMuted(this.getMyUserId(), muted); APP.UI.setVideoMuted(this.getMyUserId());
APP.API.notifyVideoMutedStatusChanged(muted); APP.API.notifyVideoMutedStatusChanged(muted);
}, },

View File

@ -366,8 +366,8 @@ UI.setAudioMuted = function(id, muted) {
/** /**
* Sets muted video state for participant * Sets muted video state for participant
*/ */
UI.setVideoMuted = function(id, muted) { UI.setVideoMuted = function(id) {
VideoLayout.onVideoMute(id, muted); VideoLayout.onVideoMute(id);
if (APP.conference.isLocalId(id)) { if (APP.conference.isLocalId(id)) {
APP.conference.updateVideoIconEnabled(); APP.conference.updateVideoIconEnabled();
} }

View File

@ -26,7 +26,6 @@ export default class SharedVideoThumb extends SmallVideo {
this.$container = $(this.container); this.$container = $(this.container);
this._setThumbnailSize(); this._setThumbnailSize();
this.bindHoverHandler(); this.bindHoverHandler();
this.isVideoMuted = true;
this.updateDisplayName(); this.updateDisplayName();
this.container.onclick = this._onContainerClick; this.container.onclick = this._onContainerClick;
} }

View File

@ -63,6 +63,7 @@ export default class LocalVideo extends SmallVideo {
this.addAudioLevelIndicator(); this.addAudioLevelIndicator();
this.updateIndicators(); this.updateIndicators();
this.updateStatusBar();
this.container.onclick = this._onContainerClick; this.container.onclick = this._onContainerClick;
} }

View File

@ -12,10 +12,13 @@ import { i18next } from '../../../react/features/base/i18n';
import { import {
JitsiParticipantConnectionStatus JitsiParticipantConnectionStatus
} from '../../../react/features/base/lib-jitsi-meet'; } from '../../../react/features/base/lib-jitsi-meet';
import { MEDIA_TYPE } from '../../../react/features/base/media';
import { import {
getParticipantById,
getPinnedParticipant, getPinnedParticipant,
pinParticipant pinParticipant
} from '../../../react/features/base/participants'; } from '../../../react/features/base/participants';
import { isRemoteTrackMuted } from '../../../react/features/base/tracks';
import { PresenceLabel } from '../../../react/features/presence-status'; import { PresenceLabel } from '../../../react/features/presence-status';
import { import {
REMOTE_CONTROL_MENU_STATES, REMOTE_CONTROL_MENU_STATES,
@ -310,11 +313,10 @@ export default class RemoteVideo extends SmallVideo {
} }
/** /**
* @inheritDoc * Video muted status changed handler.
* @override
*/ */
setVideoMutedView(isMuted) { onVideoMute() {
super.setVideoMutedView(isMuted); super.updateView();
// Update 'mutedWhileDisconnected' flag // Update 'mutedWhileDisconnected' flag
this._figureOutMutedWhileDisconnected(); this._figureOutMutedWhileDisconnected();
@ -328,10 +330,12 @@ export default class RemoteVideo extends SmallVideo {
*/ */
_figureOutMutedWhileDisconnected() { _figureOutMutedWhileDisconnected() {
const isActive = this.isConnectionActive(); const isActive = this.isConnectionActive();
const isVideoMuted
= isRemoteTrackMuted(APP.store.getState()['features/base/tracks'], MEDIA_TYPE.VIDEO, this.id);
if (!isActive && this.isVideoMuted) { if (!isActive && isVideoMuted) {
this.mutedWhileDisconnected = true; this.mutedWhileDisconnected = true;
} else if (isActive && !this.isVideoMuted) { } else if (isActive && !isVideoMuted) {
this.mutedWhileDisconnected = false; this.mutedWhileDisconnected = false;
} }
} }

View File

@ -11,11 +11,15 @@ import { Provider } from 'react-redux';
import { AudioLevelIndicator } from '../../../react/features/audio-level-indicator'; import { AudioLevelIndicator } from '../../../react/features/audio-level-indicator';
import { Avatar as AvatarDisplay } from '../../../react/features/base/avatar'; import { Avatar as AvatarDisplay } from '../../../react/features/base/avatar';
import { i18next } from '../../../react/features/base/i18n'; import { i18next } from '../../../react/features/base/i18n';
import { MEDIA_TYPE } from '../../../react/features/base/media';
import { import {
getLocalParticipant,
getParticipantById,
getParticipantCount, getParticipantCount,
getPinnedParticipant, getPinnedParticipant,
pinParticipant pinParticipant
} from '../../../react/features/base/participants'; } from '../../../react/features/base/participants';
import { isLocalTrackMuted, isRemoteTrackMuted } from '../../../react/features/base/tracks';
import { ConnectionIndicator } from '../../../react/features/connection-indicator'; import { ConnectionIndicator } from '../../../react/features/connection-indicator';
import { DisplayName } from '../../../react/features/display-name'; import { DisplayName } from '../../../react/features/display-name';
import { import {
@ -82,7 +86,6 @@ export default class SmallVideo {
*/ */
constructor(VideoLayout) { constructor(VideoLayout) {
this.isAudioMuted = false; this.isAudioMuted = false;
this.isVideoMuted = false;
this.isScreenSharing = false; this.isScreenSharing = false;
this.videoStream = null; this.videoStream = null;
this.audioStream = null; this.audioStream = null;
@ -242,19 +245,6 @@ export default class SmallVideo {
this.updateStatusBar(); this.updateStatusBar();
} }
/**
* Shows video muted indicator over small videos and disables/enables avatar
* if video muted.
*
* @param {boolean} isMuted indicates if we should set the view to muted view
* or not
*/
setVideoMutedView(isMuted) {
this.isVideoMuted = isMuted;
this.updateView();
this.updateStatusBar();
}
/** /**
* Create or updates the ReactElement for displaying status indicators about * Create or updates the ReactElement for displaying status indicators about
* audio mute, video mute, and moderator status. * audio mute, video mute, and moderator status.
@ -274,7 +264,6 @@ export default class SmallVideo {
<StatusIndicators <StatusIndicators
showAudioMutedIndicator = { this.isAudioMuted } showAudioMutedIndicator = { this.isAudioMuted }
showScreenShareIndicator = { this.isScreenSharing } showScreenShareIndicator = { this.isScreenSharing }
showVideoMutedIndicator = { this.isVideoMuted }
participantID = { this.id } /> participantID = { this.id } />
</I18nextProvider> </I18nextProvider>
</Provider>, </Provider>,
@ -449,7 +438,18 @@ export default class SmallVideo {
* or <tt>false</tt> otherwise. * or <tt>false</tt> otherwise.
*/ */
isVideoPlayable() { isVideoPlayable() {
return this.videoStream && !this.isVideoMuted && !APP.conference.isAudioOnly(); const state = APP.store.getState();
const tracks = state['features/base/tracks'];
const participant = this.id ? getParticipantById(state, this.id) : getLocalParticipant(state);
let isVideoMuted = true;
if (participant?.local) {
isVideoMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.VIDEO);
} else if (!participant?.isFakeParticipant) { // remote participants excluding shared video
isVideoMuted = isRemoteTrackMuted(tracks, MEDIA_TYPE.VIDEO, this.id);
}
return this.videoStream && !isVideoMuted && !APP.conference.isAudioOnly();
} }
/** /**
@ -490,7 +490,6 @@ export default class SmallVideo {
mutedWhileDisconnected: this.mutedWhileDisconnected, mutedWhileDisconnected: this.mutedWhileDisconnected,
canPlayEventReceived: this._canPlayEventReceived, canPlayEventReceived: this._canPlayEventReceived,
videoStream: Boolean(this.videoStream), videoStream: Boolean(this.videoStream),
isVideoMuted: this.isVideoMuted,
isScreenSharing: this.isScreenSharing, isScreenSharing: this.isScreenSharing,
videoStreamMuted: this.videoStream ? this.videoStream.isMuted() : 'no stream' videoStreamMuted: this.videoStream ? this.videoStream.isMuted() : 'no stream'
}; };

View File

@ -176,7 +176,7 @@ const VideoLayout = {
if (stream.getType() === 'audio') { if (stream.getType() === 'audio') {
this.onAudioMute(id, stream.isMuted()); this.onAudioMute(id, stream.isMuted());
} else { } else {
this.onVideoMute(id, stream.isMuted()); this.onVideoMute(id);
remoteVideo.setScreenSharing(stream.videoType === 'desktop'); remoteVideo.setScreenSharing(stream.videoType === 'desktop');
} }
}, },
@ -210,7 +210,7 @@ const VideoLayout = {
if (mediaType === 'audio') { if (mediaType === 'audio') {
APP.UI.setAudioMuted(participantId, true); APP.UI.setAudioMuted(participantId, true);
} else if (mediaType === 'video') { } else if (mediaType === 'video') {
APP.UI.setVideoMuted(participantId, true); APP.UI.setVideoMuted(participantId);
} else { } else {
logger.error(`Unsupported media type: ${mediaType}`); logger.error(`Unsupported media type: ${mediaType}`);
} }
@ -350,14 +350,14 @@ const VideoLayout = {
/** /**
* On video muted event. * On video muted event.
*/ */
onVideoMute(id, value) { onVideoMute(id) {
if (APP.conference.isLocalId(id)) { if (APP.conference.isLocalId(id)) {
localVideoThumbnail && localVideoThumbnail.setVideoMutedView(value); localVideoThumbnail && localVideoThumbnail.updateView();
} else { } else {
const remoteVideo = remoteVideos[id]; const remoteVideo = remoteVideos[id];
if (remoteVideo) { if (remoteVideo) {
remoteVideo.setVideoMutedView(value); remoteVideo.onVideoMute();
} }
} }

View File

@ -159,7 +159,7 @@ MiddlewareRegistry.register(store => next => action => {
} else if (jitsiTrack.isLocal()) { } else if (jitsiTrack.isLocal()) {
APP.conference.setVideoMuteStatus(muted); APP.conference.setVideoMuteStatus(muted);
} else { } else {
APP.UI.setVideoMuted(participantID, muted); APP.UI.setVideoMuted(participantID);
} }
APP.UI.onPeerVideoTypeChanged(participantID, jitsiTrack.videoType); APP.UI.onPeerVideoTypeChanged(participantID, jitsiTrack.videoType);
} else if (jitsiTrack.isLocal()) { } else if (jitsiTrack.isLocal()) {

View File

@ -2,8 +2,10 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { MEDIA_TYPE } from '../../../base/media';
import { getLocalParticipant, getParticipantById, PARTICIPANT_ROLE } from '../../../base/participants'; import { getLocalParticipant, getParticipantById, PARTICIPANT_ROLE } from '../../../base/participants';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import { isLocalTrackMuted, isRemoteTrackMuted } from '../../../base/tracks';
import { getCurrentLayout, LAYOUTS } from '../../../video-layout'; import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
import AudioMutedIndicator from './AudioMutedIndicator'; import AudioMutedIndicator from './AudioMutedIndicator';
@ -28,6 +30,11 @@ type Props = {
*/ */
_showModeratorIndicator: Boolean, _showModeratorIndicator: Boolean,
/**
* Indicates if the video muted indicator should be visible or not.
*/
_showVideoMutedIndicator: Boolean,
/** /**
* Indicates if the audio muted indicator should be visible or not. * Indicates if the audio muted indicator should be visible or not.
*/ */
@ -38,11 +45,6 @@ type Props = {
*/ */
showScreenShareIndicator: Boolean, showScreenShareIndicator: Boolean,
/**
* Indicates if the video muted indicator should be visible or not.
*/
showVideoMutedIndicator: Boolean,
/** /**
* The ID of the participant for which the status bar is rendered. * The ID of the participant for which the status bar is rendered.
*/ */
@ -67,7 +69,7 @@ class StatusIndicators extends Component<Props> {
_showModeratorIndicator, _showModeratorIndicator,
showAudioMutedIndicator, showAudioMutedIndicator,
showScreenShareIndicator, showScreenShareIndicator,
showVideoMutedIndicator _showVideoMutedIndicator
} = this.props; } = this.props;
let tooltipPosition; let tooltipPosition;
@ -86,7 +88,7 @@ class StatusIndicators extends Component<Props> {
<div> <div>
{ showAudioMutedIndicator ? <AudioMutedIndicator tooltipPosition = { tooltipPosition } /> : null } { showAudioMutedIndicator ? <AudioMutedIndicator tooltipPosition = { tooltipPosition } /> : null }
{ showScreenShareIndicator ? <ScreenShareIndicator tooltipPosition = { tooltipPosition } /> : null } { showScreenShareIndicator ? <ScreenShareIndicator tooltipPosition = { tooltipPosition } /> : null }
{ showVideoMutedIndicator ? <VideoMutedIndicator tooltipPosition = { tooltipPosition } /> : null } { _showVideoMutedIndicator ? <VideoMutedIndicator tooltipPosition = { tooltipPosition } /> : null }
{ _showModeratorIndicator ? <ModeratorIndicator tooltipPosition = { tooltipPosition } /> : null } { _showModeratorIndicator ? <ModeratorIndicator tooltipPosition = { tooltipPosition } /> : null }
</div> </div>
); );
@ -101,7 +103,8 @@ class StatusIndicators extends Component<Props> {
* @private * @private
* @returns {{ * @returns {{
* _currentLayout: string, * _currentLayout: string,
* _showModeratorIndicator: boolean * _showModeratorIndicator: boolean,
* _showVideoMutedIndicator: boolean
* }} * }}
*/ */
function _mapStateToProps(state, ownProps) { function _mapStateToProps(state, ownProps) {
@ -110,10 +113,20 @@ function _mapStateToProps(state, ownProps) {
// Only the local participant won't have id for the time when the conference is not yet joined. // Only the local participant won't have id for the time when the conference is not yet joined.
const participant = participantID ? getParticipantById(state, participantID) : getLocalParticipant(state); const participant = participantID ? getParticipantById(state, participantID) : getLocalParticipant(state);
const tracks = state['features/base/tracks'];
let isVideoMuted = true;
if (participant?.local) {
isVideoMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.VIDEO);
} else if (!participant?.isFakeParticipant) { // remote participants excluding shared video
isVideoMuted = isRemoteTrackMuted(tracks, MEDIA_TYPE.VIDEO, participantID);
}
return { return {
_currentLayout: getCurrentLayout(state), _currentLayout: getCurrentLayout(state),
_showModeratorIndicator: _showModeratorIndicator:
!interfaceConfig.DISABLE_FOCUS_INDICATOR && participant && participant.role === PARTICIPANT_ROLE.MODERATOR !interfaceConfig.DISABLE_FOCUS_INDICATOR && participant && participant.role === PARTICIPANT_ROLE.MODERATOR,
_showVideoMutedIndicator: isVideoMuted
}; };
} }