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:
parent
ffa55cca1e
commit
97ca3fb622
|
@ -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>);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
|
@ -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 } />
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue