fix(multi-stream): Add a virtual SS tile on RN.
Add a second virtual SS tile on RN when a remote participant that has multi-stream mode enabled starts a screenshare.
This commit is contained in:
parent
43b0118ff8
commit
a707022d0b
|
@ -5,6 +5,7 @@ import { Text, View } from 'react-native';
|
||||||
|
|
||||||
import { SharedVideo } from '../../../shared-video/components/native';
|
import { SharedVideo } from '../../../shared-video/components/native';
|
||||||
import { Avatar } from '../../avatar';
|
import { Avatar } from '../../avatar';
|
||||||
|
import { getMultipleVideoSupportFeatureFlag } from '../../config/';
|
||||||
import { translate } from '../../i18n';
|
import { translate } from '../../i18n';
|
||||||
import { JitsiParticipantConnectionStatus } from '../../lib-jitsi-meet';
|
import { JitsiParticipantConnectionStatus } from '../../lib-jitsi-meet';
|
||||||
import {
|
import {
|
||||||
|
@ -14,7 +15,7 @@ import {
|
||||||
import { Container, TintedView } from '../../react';
|
import { Container, TintedView } from '../../react';
|
||||||
import { connect } from '../../redux';
|
import { connect } from '../../redux';
|
||||||
import { TestHint } from '../../testing/components';
|
import { TestHint } from '../../testing/components';
|
||||||
import { getTrackByMediaTypeAndParticipant } from '../../tracks';
|
import { getTrackByMediaTypeAndParticipant, getVirtualScreenshareParticipantTrack } from '../../tracks';
|
||||||
import { shouldRenderParticipantVideo, getParticipantById } from '../functions';
|
import { shouldRenderParticipantVideo, getParticipantById } from '../functions';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
@ -251,8 +252,12 @@ class ParticipantView extends Component<Props> {
|
||||||
function _mapStateToProps(state, ownProps) {
|
function _mapStateToProps(state, ownProps) {
|
||||||
const { disableVideo, participantId } = ownProps;
|
const { disableVideo, participantId } = ownProps;
|
||||||
const participant = getParticipantById(state, participantId);
|
const participant = getParticipantById(state, participantId);
|
||||||
|
const tracks = state['features/base/tracks'];
|
||||||
let connectionStatus;
|
let connectionStatus;
|
||||||
let participantName;
|
let participantName;
|
||||||
|
const videoTrack = getMultipleVideoSupportFeatureFlag(state) && participant?.isVirtualScreenshareParticipant
|
||||||
|
? getVirtualScreenshareParticipantTrack(tracks, participantId)
|
||||||
|
: getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, participantId);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_connectionStatus:
|
_connectionStatus:
|
||||||
|
@ -261,11 +266,7 @@ function _mapStateToProps(state, ownProps) {
|
||||||
_isFakeParticipant: participant && participant.isFakeParticipant,
|
_isFakeParticipant: participant && participant.isFakeParticipant,
|
||||||
_participantName: participantName,
|
_participantName: participantName,
|
||||||
_renderVideo: shouldRenderParticipantVideo(state, participantId) && !disableVideo,
|
_renderVideo: shouldRenderParticipantVideo(state, participantId) && !disableVideo,
|
||||||
_videoTrack:
|
_videoTrack: videoTrack
|
||||||
getTrackByMediaTypeAndParticipant(
|
|
||||||
state['features/base/tracks'],
|
|
||||||
MEDIA_TYPE.VIDEO,
|
|
||||||
participantId)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,11 @@ import { getMultipleVideoSupportFeatureFlag, getSourceNameSignalingFeatureFlag }
|
||||||
import { JitsiParticipantConnectionStatus } from '../lib-jitsi-meet';
|
import { JitsiParticipantConnectionStatus } from '../lib-jitsi-meet';
|
||||||
import { MEDIA_TYPE, shouldRenderVideoTrack } from '../media';
|
import { MEDIA_TYPE, shouldRenderVideoTrack } from '../media';
|
||||||
import { toState } from '../redux';
|
import { toState } from '../redux';
|
||||||
import { getScreenShareTrack, getTrackByMediaTypeAndParticipant } from '../tracks';
|
import {
|
||||||
|
getScreenShareTrack,
|
||||||
|
getTrackByMediaTypeAndParticipant,
|
||||||
|
getVirtualScreenshareParticipantTrack
|
||||||
|
} from '../tracks';
|
||||||
import { createDeferred } from '../util';
|
import { createDeferred } from '../util';
|
||||||
|
|
||||||
import { JIGASI_PARTICIPANT_ICON, MAX_DISPLAY_NAME_LENGTH, PARTICIPANT_ROLE } from './constants';
|
import { JIGASI_PARTICIPANT_ICON, MAX_DISPLAY_NAME_LENGTH, PARTICIPANT_ROLE } from './constants';
|
||||||
|
@ -478,8 +482,14 @@ export function shouldRenderParticipantVideo(stateful: Object | Function, id: st
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First check if we have an unmuted video track. */
|
/* First check if we have an unmuted video track. */
|
||||||
const videoTrack
|
const tracks = state['features/base/tracks'];
|
||||||
= getTrackByMediaTypeAndParticipant(state['features/base/tracks'], MEDIA_TYPE.VIDEO, id);
|
let videoTrack;
|
||||||
|
|
||||||
|
if (getMultipleVideoSupportFeatureFlag(state) && participant.isVirtualScreenshareParticipant) {
|
||||||
|
videoTrack = getVirtualScreenshareParticipantTrack(tracks, id);
|
||||||
|
} else {
|
||||||
|
videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, id);
|
||||||
|
}
|
||||||
|
|
||||||
if (!shouldRenderVideoTrack(videoTrack, /* waitForVideoStarted */ false)) {
|
if (!shouldRenderVideoTrack(videoTrack, /* waitForVideoStarted */ false)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import React, { PureComponent } from 'react';
|
||||||
import { Image, View } from 'react-native';
|
import { Image, View } from 'react-native';
|
||||||
import type { Dispatch } from 'redux';
|
import type { Dispatch } from 'redux';
|
||||||
|
|
||||||
|
import { getMultipleVideoSupportFeatureFlag } from '../../../base/config';
|
||||||
import { MEDIA_TYPE, VIDEO_TYPE } from '../../../base/media';
|
import { MEDIA_TYPE, VIDEO_TYPE } from '../../../base/media';
|
||||||
import {
|
import {
|
||||||
PARTICIPANT_ROLE,
|
PARTICIPANT_ROLE,
|
||||||
|
@ -55,11 +56,21 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
_isFakeParticipant: boolean,
|
_isFakeParticipant: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether multi-stream support is enabled.
|
||||||
|
*/
|
||||||
|
_isMultiStreamSupportEnabled: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether the participant is screen sharing.
|
* Indicates whether the participant is screen sharing.
|
||||||
*/
|
*/
|
||||||
_isScreenShare: boolean,
|
_isScreenShare: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the thumbnail is for a virtual screenshare participant.
|
||||||
|
*/
|
||||||
|
_isVirtualScreenshare: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether the participant is local.
|
* Indicates whether the participant is local.
|
||||||
*/
|
*/
|
||||||
|
@ -187,6 +198,7 @@ class Thumbnail extends PureComponent<Props> {
|
||||||
const {
|
const {
|
||||||
_audioMuted: audioMuted,
|
_audioMuted: audioMuted,
|
||||||
_isScreenShare: isScreenShare,
|
_isScreenShare: isScreenShare,
|
||||||
|
_isVirtualScreenshare,
|
||||||
_isFakeParticipant,
|
_isFakeParticipant,
|
||||||
_renderModeratorIndicator: renderModeratorIndicator,
|
_renderModeratorIndicator: renderModeratorIndicator,
|
||||||
_participantId: participantId,
|
_participantId: participantId,
|
||||||
|
@ -203,8 +215,8 @@ class Thumbnail extends PureComponent<Props> {
|
||||||
styles.thumbnailTopIndicatorContainer,
|
styles.thumbnailTopIndicatorContainer,
|
||||||
styles.thumbnailTopLeftIndicatorContainer
|
styles.thumbnailTopLeftIndicatorContainer
|
||||||
] }>
|
] }>
|
||||||
<ConnectionIndicator participantId = { participantId } />
|
{ !_isVirtualScreenshare && <ConnectionIndicator participantId = { participantId } /> }
|
||||||
<RaisedHandIndicator participantId = { participantId } />
|
{ !_isVirtualScreenshare && <RaisedHandIndicator participantId = { participantId } /> }
|
||||||
{tileView && isScreenShare && (
|
{tileView && isScreenShare && (
|
||||||
<View style = { styles.indicatorContainer }>
|
<View style = { styles.indicatorContainer }>
|
||||||
<ScreenShareIndicator />
|
<ScreenShareIndicator />
|
||||||
|
@ -215,10 +227,10 @@ class Thumbnail extends PureComponent<Props> {
|
||||||
key = 'bottom-indicators'
|
key = 'bottom-indicators'
|
||||||
style = { styles.thumbnailIndicatorContainer }>
|
style = { styles.thumbnailIndicatorContainer }>
|
||||||
<Container style = { (audioMuted || renderModeratorIndicator) && styles.bottomIndicatorsContainer }>
|
<Container style = { (audioMuted || renderModeratorIndicator) && styles.bottomIndicatorsContainer }>
|
||||||
{ audioMuted && <AudioMutedIndicator /> }
|
{ audioMuted && !_isVirtualScreenshare && <AudioMutedIndicator /> }
|
||||||
{ !tileView && _pinned && <PinnedIndicator />}
|
{ !tileView && _pinned && <PinnedIndicator />}
|
||||||
{ renderModeratorIndicator && <ModeratorIndicator />}
|
{ renderModeratorIndicator && !_isVirtualScreenshare && <ModeratorIndicator />}
|
||||||
{ !tileView && isScreenShare
|
{ !tileView && (isScreenShare || _isVirtualScreenshare)
|
||||||
&& <ScreenShareIndicator />
|
&& <ScreenShareIndicator />
|
||||||
}
|
}
|
||||||
</Container>
|
</Container>
|
||||||
|
@ -242,8 +254,9 @@ class Thumbnail extends PureComponent<Props> {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
_gifSrc,
|
_gifSrc,
|
||||||
_isScreenShare: isScreenShare,
|
|
||||||
_isFakeParticipant,
|
_isFakeParticipant,
|
||||||
|
_isScreenShare: isScreenShare,
|
||||||
|
_isVirtualScreenshare,
|
||||||
_participantId: participantId,
|
_participantId: participantId,
|
||||||
_raisedHand,
|
_raisedHand,
|
||||||
_renderDominantSpeakerIndicator,
|
_renderDominantSpeakerIndicator,
|
||||||
|
@ -266,8 +279,8 @@ class Thumbnail extends PureComponent<Props> {
|
||||||
style = { [
|
style = { [
|
||||||
styles.thumbnail,
|
styles.thumbnail,
|
||||||
styleOverrides,
|
styleOverrides,
|
||||||
_raisedHand ? styles.thumbnailRaisedHand : null,
|
_raisedHand && !_isVirtualScreenshare ? styles.thumbnailRaisedHand : null,
|
||||||
_renderDominantSpeakerIndicator ? styles.thumbnailDominantSpeaker : null
|
_renderDominantSpeakerIndicator && !_isVirtualScreenshare ? styles.thumbnailDominantSpeaker : null
|
||||||
] }
|
] }
|
||||||
touchFeedback = { false }>
|
touchFeedback = { false }>
|
||||||
{_gifSrc ? <Image
|
{_gifSrc ? <Image
|
||||||
|
@ -303,10 +316,9 @@ function _mapStateToProps(state, ownProps) {
|
||||||
const participant = getParticipantByIdOrUndefined(state, participantID);
|
const participant = getParticipantByIdOrUndefined(state, participantID);
|
||||||
const localParticipantId = getLocalParticipant(state).id;
|
const localParticipantId = getLocalParticipant(state).id;
|
||||||
const id = participant?.id;
|
const id = participant?.id;
|
||||||
const audioTrack
|
const audioTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.AUDIO, id);
|
||||||
= getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.AUDIO, id);
|
const videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, id);
|
||||||
const videoTrack
|
const isMultiStreamSupportEnabled = getMultipleVideoSupportFeatureFlag(state);
|
||||||
= getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, id);
|
|
||||||
const isScreenShare = videoTrack?.videoType === VIDEO_TYPE.DESKTOP;
|
const isScreenShare = videoTrack?.videoType === VIDEO_TYPE.DESKTOP;
|
||||||
const participantCount = getParticipantCount(state);
|
const participantCount = getParticipantCount(state);
|
||||||
const renderDominantSpeakerIndicator = participant && participant.dominantSpeaker && participantCount > 2;
|
const renderDominantSpeakerIndicator = participant && participant.dominantSpeaker && participantCount > 2;
|
||||||
|
@ -320,7 +332,9 @@ function _mapStateToProps(state, ownProps) {
|
||||||
_audioMuted: audioTrack?.muted ?? true,
|
_audioMuted: audioTrack?.muted ?? true,
|
||||||
_gifSrc: mode === 'chat' ? null : gifSrc,
|
_gifSrc: mode === 'chat' ? null : gifSrc,
|
||||||
_isFakeParticipant: participant?.isFakeParticipant,
|
_isFakeParticipant: participant?.isFakeParticipant,
|
||||||
|
_isMultiStreamSupportEnabled: isMultiStreamSupportEnabled,
|
||||||
_isScreenShare: isScreenShare,
|
_isScreenShare: isScreenShare,
|
||||||
|
_isVirtualScreenshare: isMultiStreamSupportEnabled && participant?.isVirtualScreenshareParticipant,
|
||||||
_local: participant?.local,
|
_local: participant?.local,
|
||||||
_localVideoOwner: Boolean(ownerId === localParticipantId),
|
_localVideoOwner: Boolean(ownerId === localParticipantId),
|
||||||
_participantId: id,
|
_participantId: id,
|
||||||
|
|
|
@ -108,7 +108,7 @@ function _mapStateToProps(state, ownProps) {
|
||||||
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 = isMultiStreamSupportEnabled
|
const track = isMultiStreamSupportEnabled && participant?.isVirtualScreenshareParticipant
|
||||||
? getVirtualScreenshareParticipantTrack(tracks, participantID)
|
? getVirtualScreenshareParticipantTrack(tracks, participantID)
|
||||||
: getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, participantID);
|
: getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, participantID);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue