fix(multi-stream): fix virtual screenshare participant's thumbnail.

Add a screenshare status indicator at the bottom.
Fix the font and size of the resolution/fps stats so that it matches with that of the other thumbnails.
This commit is contained in:
Jaya Allamsetty 2022-05-12 18:47:38 -04:00
parent ffa55cca1e
commit 97ca3fb622
6 changed files with 66 additions and 39 deletions

View File

@ -281,7 +281,7 @@ class ConnectionStatsTable extends Component<Props> {
*/ */
_renderScreenShareStatus() { _renderScreenShareStatus() {
const { classes } = this.props; const { classes } = this.props;
const className = isMobileBrowser() ? 'connection-info connection-info__mobile' : 'connection-info'; const className = clsx(classes.connectionStatsTable, { [classes.mobile]: isMobileBrowser() });
return (<ContextMenu return (<ContextMenu
className = { classes.contextMenu } className = { classes.contextMenu }
@ -290,13 +290,10 @@ class ConnectionStatsTable extends Component<Props> {
<div <div
className = { className } className = { className }
onClick = { onClick }> onClick = { onClick }>
{ <table className = 'connection-info__container'> <tbody>
<tbody> { this._renderResolution() }
{ this._renderResolution() } { this._renderFrameRate() }
{ this._renderFrameRate() } </tbody>
</tbody>
</table> }
</div> </div>
</ContextMenu>); </ContextMenu>);
} }

View File

@ -2,10 +2,16 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { getMultipleVideoSupportFeatureFlag } from '../../../base/config';
import { MEDIA_TYPE } from '../../../base/media'; import { MEDIA_TYPE } from '../../../base/media';
import { getParticipantByIdOrUndefined, PARTICIPANT_ROLE } from '../../../base/participants'; import { getParticipantByIdOrUndefined, PARTICIPANT_ROLE } from '../../../base/participants';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import { getTrackByMediaTypeAndParticipant, isLocalTrackMuted, isRemoteTrackMuted } from '../../../base/tracks'; import {
getTrackByMediaTypeAndParticipant,
getVirtualScreenshareParticipantTrack,
isLocalTrackMuted,
isRemoteTrackMuted
} from '../../../base/tracks';
import { getIndicatorsTooltipPosition } from '../../functions.web'; import { getIndicatorsTooltipPosition } from '../../functions.web';
import AudioMutedIndicator from './AudioMutedIndicator'; import AudioMutedIndicator from './AudioMutedIndicator';
@ -83,9 +89,9 @@ class StatusIndicators extends Component<Props> {
* @param {Object} ownProps - The own props of the component. * @param {Object} ownProps - The own props of the component.
* @private * @private
* @returns {{ * @returns {{
* _currentLayout: string, * _showAudioMutedIndicator: boolean,
* _showModeratorIndicator: boolean, * _showModeratorIndicator: boolean,
* _showVideoMutedIndicator: boolean * _showScreenShareIndicator: boolean
* }} * }}
*/ */
function _mapStateToProps(state, ownProps) { function _mapStateToProps(state, ownProps) {
@ -93,15 +99,18 @@ 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 = getParticipantByIdOrUndefined(state, participantID); const participant = getParticipantByIdOrUndefined(state, participantID);
const tracks = state['features/base/tracks']; const tracks = state['features/base/tracks'];
const isMultiStreamSupportEnabled = getMultipleVideoSupportFeatureFlag(state);
let isAudioMuted = true; let isAudioMuted = true;
let isScreenSharing = false; let isScreenSharing = false;
if (participant?.local) { if (participant?.local) {
isAudioMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.AUDIO); isAudioMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.AUDIO);
} else if (!participant?.isFakeParticipant) { // remote participants excluding shared video } else if (!participant?.isFakeParticipant) { // remote participants excluding shared video
const track = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, participantID); const track = isMultiStreamSupportEnabled
? getVirtualScreenshareParticipantTrack(tracks, participantID)
: getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, participantID);
isScreenSharing = track?.videoType === 'desktop'; isScreenSharing = track?.videoType === 'desktop';
isAudioMuted = isRemoteTrackMuted(tracks, MEDIA_TYPE.AUDIO, participantID); isAudioMuted = isRemoteTrackMuted(tracks, MEDIA_TYPE.AUDIO, participantID);

View File

@ -137,10 +137,9 @@ export type Props = {|
_isCurrentlyOnLargeVideo: boolean, _isCurrentlyOnLargeVideo: boolean,
/** /**
* Indicates whether the participant is a virtual screen share participant. This prop is behind the * Disable/enable the dominant speaker indicator.
* sourceNameSignaling feature flag.
*/ */
_isVirtualScreenshareParticipant: boolean, _isDominantSpeakerDisabled: boolean,
/** /**
* Whether we are currently running in a mobile browser. * Whether we are currently running in a mobile browser.
@ -157,20 +156,21 @@ export type Props = {|
*/ */
_isScreenSharing: boolean, _isScreenSharing: boolean,
/**
* Indicates whether testing mode is enabled.
*/
_isTestModeEnabled: boolean,
/** /**
* Indicates whether the video associated with the thumbnail is playable. * Indicates whether the video associated with the thumbnail is playable.
*/ */
_isVideoPlayable: boolean, _isVideoPlayable: boolean,
/** /**
* Disable/enable the dominant speaker indicator. * Indicates whether the participant is a virtual screen share participant. This prop is behind the
* sourceNameSignaling feature flag.
*/ */
_isDominantSpeakerDisabled: boolean, _isVirtualScreenshareParticipant: boolean,
/**
* Indicates whether testing mode is enabled.
*/
_isTestModeEnabled: boolean,
/** /**
* The current local video flip setting. * The current local video flip setting.
@ -187,6 +187,11 @@ export type Props = {|
*/ */
_raisedHand: boolean, _raisedHand: boolean,
/**
* Whether source name signaling is enabled.
*/
_sourceNameSignalingEnabled: boolean,
/** /**
* Whether or not the current layout is stage filmstrip layout. * Whether or not the current layout is stage filmstrip layout.
*/ */
@ -253,12 +258,7 @@ export type Props = {|
* The width of the thumbnail. Used for expanding the width of the thumbnails on last row in case * The width of the thumbnail. Used for expanding the width of the thumbnails on last row in case
* there is empty space. * there is empty space.
*/ */
width?: number, width?: number
/**
* Whether source name signaling is enabled.
*/
_sourceNameSignalingEnabled: boolean
|}; |};
const defaultStyles = theme => { const defaultStyles = theme => {
@ -1074,6 +1074,7 @@ class Thumbnail extends Component<Props, State> {
) }> ) }>
<ThumbnailBottomIndicators <ThumbnailBottomIndicators
className = { classes.indicatorsBackground } className = { classes.indicatorsBackground }
isVirtualScreenshareParticipant = { false }
local = { local } local = { local }
participantId = { id } participantId = { id }
thumbnailType = { _thumbnailType } /> thumbnailType = { _thumbnailType } />
@ -1138,6 +1139,7 @@ class Thumbnail extends Component<Props, State> {
classes = { classes } classes = { classes }
containerClassName = { this._getContainerClassName() } containerClassName = { this._getContainerClassName() }
isHovered = { isHovered } isHovered = { isHovered }
isLocal = { local }
isMobile = { _isMobile } isMobile = { _isMobile }
onClick = { this._onClick } onClick = { this._onClick }
onMouseEnter = { this._onMouseEnter } onMouseEnter = { this._onMouseEnter }

View File

@ -4,7 +4,11 @@ import { makeStyles } from '@material-ui/styles';
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { isDisplayNameVisible, isNameReadOnly } from '../../../base/config/functions.any'; import {
getMultipleVideoSupportFeatureFlag,
isDisplayNameVisible,
isNameReadOnly
} from '../../../base/config/functions.any';
import DisplayName from '../../../display-name/components/web/DisplayName'; import DisplayName from '../../../display-name/components/web/DisplayName';
import { THUMBNAIL_TYPE } from '../../constants'; import { THUMBNAIL_TYPE } from '../../constants';
@ -19,6 +23,11 @@ type Props = {
*/ */
className: string, className: string,
/**
* Whether it is a virtual screenshare participant thumbnail.
*/
isVirtualScreenshareParticipant: boolean,
/** /**
* Whether or not the indicators are for the local participant. * Whether or not the indicators are for the local participant.
*/ */
@ -61,6 +70,7 @@ const useStyles = makeStyles(() => {
const ThumbnailBottomIndicators = ({ const ThumbnailBottomIndicators = ({
className, className,
isVirtualScreenshareParticipant,
local, local,
participantId, participantId,
showStatusIndicators = true, showStatusIndicators = true,
@ -69,15 +79,18 @@ const ThumbnailBottomIndicators = ({
const styles = useStyles(); const styles = useStyles();
const _allowEditing = !useSelector(isNameReadOnly); const _allowEditing = !useSelector(isNameReadOnly);
const _defaultLocalDisplayName = interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME; const _defaultLocalDisplayName = interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME;
const _isMultiStreamEnabled = useSelector(getMultipleVideoSupportFeatureFlag);
const _showDisplayName = useSelector(isDisplayNameVisible); const _showDisplayName = useSelector(isDisplayNameVisible);
return (<div className = { className }> return (<div className = { className }>
{ {
showStatusIndicators && <StatusIndicators showStatusIndicators && <StatusIndicators
audio = { true } audio = { !isVirtualScreenshareParticipant }
moderator = { true } moderator = { true }
participantID = { participantId } participantID = { participantId }
screenshare = { thumbnailType === THUMBNAIL_TYPE.TILE } screenshare = { _isMultiStreamEnabled
? isVirtualScreenshareParticipant
: thumbnailType === THUMBNAIL_TYPE.TILE }
thumbnailType = { thumbnailType } /> thumbnailType = { thumbnailType } />
} }
{ {

View File

@ -5,7 +5,7 @@ import clsx from 'clsx';
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { getSourceNameSignalingFeatureFlag } from '../../../base/config'; import { getMultipleVideoSupportFeatureFlag } from '../../../base/config';
import { isMobileBrowser } from '../../../base/environment/utils'; import { isMobileBrowser } from '../../../base/environment/utils';
import ConnectionIndicator from '../../../connection-indicator/components/web/ConnectionIndicator'; import ConnectionIndicator from '../../../connection-indicator/components/web/ConnectionIndicator';
import { STATS_POPOVER_POSITION, THUMBNAIL_TYPE } from '../../constants'; import { STATS_POPOVER_POSITION, THUMBNAIL_TYPE } from '../../constants';
@ -98,10 +98,10 @@ const ThumbnailTopIndicators = ({
useSelector(state => state['features/base/config'].connectionIndicators?.autoHide) ?? true); useSelector(state => state['features/base/config'].connectionIndicators?.autoHide) ?? true);
const _connectionIndicatorDisabled = _isMobile const _connectionIndicatorDisabled = _isMobile
|| Boolean(useSelector(state => state['features/base/config'].connectionIndicators?.disabled)); || Boolean(useSelector(state => state['features/base/config'].connectionIndicators?.disabled));
const sourceNameSignalingEnabled = useSelector(getSourceNameSignalingFeatureFlag); const _isMultiStreamEnabled = useSelector(getMultipleVideoSupportFeatureFlag);
const showConnectionIndicator = isHovered || !_connectionIndicatorAutoHideEnabled; const showConnectionIndicator = isHovered || !_connectionIndicatorAutoHideEnabled;
if (sourceNameSignalingEnabled && isVirtualScreenshareParticipant) { if (_isMultiStreamEnabled && isVirtualScreenshareParticipant) {
return ( return (
<div className = { styles.container }> <div className = { styles.container }>
{!_connectionIndicatorDisabled {!_connectionIndicatorDisabled
@ -141,7 +141,7 @@ const ThumbnailTopIndicators = ({
<div className = { clsx(indicatorsClassName, 'top-indicators') }> <div className = { clsx(indicatorsClassName, 'top-indicators') }>
<StatusIndicators <StatusIndicators
participantID = { participantId } participantID = { participantId }
screenshare = { true } /> screenshare = { !_isMultiStreamEnabled } />
</div> </div>
)} )}
</div> </div>

View File

@ -27,6 +27,11 @@ type Props = {
*/ */
isHovered: boolean, isHovered: boolean,
/**
* Indicates whether the thumbnail is for local screenshare or not.
*/
isLocal: boolean,
/** /**
* Indicates whether we are currently running in a mobile browser. * Indicates whether we are currently running in a mobile browser.
*/ */
@ -92,6 +97,7 @@ const VirtualScreenshareParticipant = ({
classes, classes,
containerClassName, containerClassName,
isHovered, isHovered,
isLocal,
isMobile, isMobile,
onClick, onClick,
onMouseEnter, onMouseEnter,
@ -108,12 +114,11 @@ const VirtualScreenshareParticipant = ({
const currentLayout = useSelector(getCurrentLayout); const currentLayout = useSelector(getCurrentLayout);
const videoTrackId = videoTrack?.jitsiTrack?.getId(); const videoTrackId = videoTrack?.jitsiTrack?.getId();
const video = videoTrack && <VideoTrack const video = videoTrack && <VideoTrack
id = { `remoteVideo_${videoTrackId || ''}` } id = { isLocal ? 'localScreenshare_container' : `remoteVideo_${videoTrackId || ''}` }
muted = { true } muted = { true }
style = { styles.video } style = { styles.video }
videoTrack = { videoTrack } />; videoTrack = { videoTrack } />;
return ( return (
<span <span
className = { containerClassName } className = { containerClassName }
@ -154,9 +159,10 @@ const VirtualScreenshareParticipant = ({
<ThumbnailBottomIndicators <ThumbnailBottomIndicators
className = { classes.indicatorsBackground } className = { classes.indicatorsBackground }
currentLayout = { currentLayout } currentLayout = { currentLayout }
isVirtualScreenshareParticipant = { true }
local = { false } local = { false }
participantId = { participantId } participantId = { participantId }
showStatusIndicators = { false } /> showStatusIndicators = { true } />
</div> </div>
</span>); </span>);
}; };