fix(rn,participants) fix not rendering connection info messages
Also move shouldRenderParticipantVideo to the only place it's used.
This commit is contained in:
parent
e8df8f75a8
commit
eda3e620d3
|
@ -1,19 +1,23 @@
|
|||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
|
||||
import {
|
||||
isParticipantConnectionStatusActive,
|
||||
isParticipantConnectionStatusInactive,
|
||||
isTrackStreamingStatusActive,
|
||||
isTrackStreamingStatusInactive
|
||||
} from '../../../connection-indicator/functions';
|
||||
import { SharedVideo } from '../../../shared-video/components/native';
|
||||
import { Avatar } from '../../avatar';
|
||||
import { translate } from '../../i18n';
|
||||
import { JitsiParticipantConnectionStatus } from '../../lib-jitsi-meet';
|
||||
import { VideoTrack } from '../../media';
|
||||
import { Container, TintedView } from '../../react';
|
||||
import { connect } from '../../redux';
|
||||
import Avatar from '../../avatar/components/Avatar';
|
||||
import { getSourceNameSignalingFeatureFlag } from '../../config/functions.any';
|
||||
import { translate } from '../../i18n/functions';
|
||||
import VideoTrack from '../../media/components/native/VideoTrack';
|
||||
import { shouldRenderVideoTrack } from '../../media/functions';
|
||||
import { Container } from '../../react';
|
||||
import { connect, toState } from '../../redux/functions';
|
||||
import { TestHint } from '../../testing/components';
|
||||
import { getVideoTrackByParticipant } from '../../tracks';
|
||||
import { getParticipantById, isSharedVideoParticipant, shouldRenderParticipantVideo } from '../functions';
|
||||
import { FakeParticipant } from '../types';
|
||||
import { getVideoTrackByParticipant } from '../../tracks/functions';
|
||||
import { getParticipantById, getParticipantDisplayName, isSharedVideoParticipant } from '../functions';
|
||||
|
||||
import styles from './styles';
|
||||
|
||||
|
@ -23,20 +27,11 @@ import styles from './styles';
|
|||
type Props = {
|
||||
|
||||
/**
|
||||
* The connection status of the participant. Her video will only be rendered
|
||||
* if the connection status is 'active'; otherwise, the avatar will be
|
||||
* rendered. If undefined, 'active' is presumed.
|
||||
* Whether the connection is inactive or not.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_connectionStatus: string,
|
||||
|
||||
/**
|
||||
* The type of participant if the participant which this component represents is fake.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_fakeParticipant?: FakeParticipant,
|
||||
_isConnectionInactive: boolean,
|
||||
|
||||
/**
|
||||
* Whether the participant is a shared video participant.
|
||||
|
@ -129,24 +124,12 @@ type Props = {
|
|||
class ParticipantView extends Component<Props> {
|
||||
|
||||
/**
|
||||
* Renders the connection status label, if appropriate.
|
||||
* Renders the inactive connection status label.
|
||||
*
|
||||
* @param {string} connectionStatus - The status of the participant's
|
||||
* connection.
|
||||
* @private
|
||||
* @returns {ReactElement|null}
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderConnectionInfo(connectionStatus) {
|
||||
let messageKey;
|
||||
|
||||
switch (connectionStatus) {
|
||||
case JitsiParticipantConnectionStatus.INACTIVE:
|
||||
messageKey = 'connection.LOW_BANDWIDTH';
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
_renderInactiveConnectionInfo() {
|
||||
const {
|
||||
avatarSize,
|
||||
_participantName: displayName,
|
||||
|
@ -165,7 +148,7 @@ class ParticipantView extends Component<Props> {
|
|||
pointerEvents = 'box-none'
|
||||
style = { containerStyle }>
|
||||
<Text style = { styles.connectionInfoText }>
|
||||
{ t(messageKey, { displayName }) }
|
||||
{ t('connection.LOW_BANDWIDTH', { displayName }) }
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
|
@ -179,8 +162,7 @@ class ParticipantView extends Component<Props> {
|
|||
*/
|
||||
render() {
|
||||
const {
|
||||
_connectionStatus: connectionStatus,
|
||||
_fakeParticipant,
|
||||
_isConnectionInactive,
|
||||
_isSharedVideoParticipant,
|
||||
_renderVideo: renderVideo,
|
||||
_videoTrack: videoTrack,
|
||||
|
@ -188,10 +170,6 @@ class ParticipantView extends Component<Props> {
|
|||
onPress
|
||||
} = this.props;
|
||||
|
||||
// If the connection has problems, we will "tint" the video / avatar.
|
||||
const connectionProblem
|
||||
= connectionStatus !== JitsiParticipantConnectionStatus.ACTIVE;
|
||||
|
||||
const testHintId
|
||||
= this.props.testHintId
|
||||
? this.props.testHintId
|
||||
|
@ -230,13 +208,8 @@ class ParticipantView extends Component<Props> {
|
|||
size = { this.props.avatarSize } />
|
||||
</View> }
|
||||
|
||||
{ connectionProblem
|
||||
|
||||
// If the connection has problems, tint the video / avatar.
|
||||
&& <TintedView /> }
|
||||
|
||||
{ this.props.useConnectivityInfoLabel
|
||||
&& this._renderConnectionInfo(connectionStatus) }
|
||||
{ _isConnectionInactive && this.props.useConnectivityInfoLabel
|
||||
&& this._renderInactiveConnectionInfo() }
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
@ -256,19 +229,69 @@ function _mapStateToProps(state, ownProps) {
|
|||
const { disableVideo, participantId } = ownProps;
|
||||
const participant = getParticipantById(state, participantId);
|
||||
const videoTrack = getVideoTrackByParticipant(state, participant);
|
||||
let connectionStatus;
|
||||
let participantName;
|
||||
|
||||
return {
|
||||
_connectionStatus:
|
||||
connectionStatus
|
||||
|| JitsiParticipantConnectionStatus.ACTIVE,
|
||||
_isConnectionInactive: getSourceNameSignalingFeatureFlag(state)
|
||||
? isTrackStreamingStatusInactive(videoTrack) : isParticipantConnectionStatusInactive(participant),
|
||||
_isSharedVideoParticipant: isSharedVideoParticipant(participant),
|
||||
_fakeParticipant: participant?.fakeParticipant,
|
||||
_participantName: participantName,
|
||||
_participantName: getParticipantDisplayName(state, participantId),
|
||||
_renderVideo: shouldRenderParticipantVideo(state, participantId) && !disableVideo,
|
||||
_videoTrack: videoTrack
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the video of the participant should be rendered.
|
||||
*
|
||||
* @param {Object|Function} stateful - Object or function that can be resolved
|
||||
* to the Redux state.
|
||||
* @param {string} id - The ID of the participant.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function shouldRenderParticipantVideo(stateful, id) {
|
||||
const state = toState(stateful);
|
||||
const participant = getParticipantById(state, id);
|
||||
|
||||
if (!participant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* First check if we have an unmuted video track. */
|
||||
const videoTrack = getVideoTrackByParticipant(state, participant);
|
||||
|
||||
if (!videoTrack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!shouldRenderVideoTrack(videoTrack, /* waitForVideoStarted */ false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Then check if the participant connection or track streaming status is active. */
|
||||
if (getSourceNameSignalingFeatureFlag(state)) {
|
||||
// Note that this will work only if a listener is registered for the track's TrackStreamingStatus.
|
||||
// The associated TrackStreamingStatusImpl instance is not created or disposed when there are zero listeners.
|
||||
if (!videoTrack.local && !isTrackStreamingStatusActive(videoTrack)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!isParticipantConnectionStatusActive(participant)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Then check if audio-only mode is not active. */
|
||||
const audioOnly = state['features/base/audio-only'].enabled;
|
||||
|
||||
if (!audioOnly) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Last, check if the participant is sharing their screen and they are on stage. */
|
||||
const remoteScreenShares = state['features/video-layout'].remoteScreenShares || [];
|
||||
const largeVideoParticipantId = state['features/large-video'].participantId;
|
||||
const participantIsInLargeVideoWithScreen
|
||||
= participant.id === largeVideoParticipantId && remoteScreenShares.includes(participant.id);
|
||||
|
||||
return participantIsInLargeVideoWithScreen;
|
||||
}
|
||||
|
||||
export default translate(connect(_mapStateToProps)(ParticipantView));
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
// @flow
|
||||
|
||||
export { default as ParticipantView } from './ParticipantView';
|
|
@ -8,12 +8,10 @@ import { isStageFilmstripAvailable } from '../../filmstrip/functions';
|
|||
import { IStateful } from '../app/types';
|
||||
import { GRAVATAR_BASE_URL } from '../avatar/constants';
|
||||
import { isCORSAvatarURL } from '../avatar/functions';
|
||||
import { getMultipleVideoSupportFeatureFlag, getSourceNameSignalingFeatureFlag } from '../config/functions.any';
|
||||
import { getMultipleVideoSupportFeatureFlag } from '../config/functions.any';
|
||||
import i18next from '../i18n/i18next';
|
||||
import { JitsiParticipantConnectionStatus, JitsiTrackStreamingStatus } from '../lib-jitsi-meet';
|
||||
import { shouldRenderVideoTrack } from '../media/functions';
|
||||
import { toState } from '../redux/functions';
|
||||
import { getScreenShareTrack, getVideoTrackByParticipant } from '../tracks/functions';
|
||||
import { getScreenShareTrack } from '../tracks/functions';
|
||||
import { createDeferred } from '../util/helpers';
|
||||
|
||||
import {
|
||||
|
@ -602,63 +600,6 @@ export function isLocalParticipantModerator(stateful: IStateful) {
|
|||
return isParticipantModerator(local);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the video of the participant should be rendered.
|
||||
* NOTE: This is currently only used on mobile.
|
||||
*
|
||||
* @param {Object|Function} stateful - Object or function that can be resolved
|
||||
* to the Redux state.
|
||||
* @param {string} id - The ID of the participant.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function shouldRenderParticipantVideo(stateful: IStateful, id: string) {
|
||||
const state = toState(stateful);
|
||||
const participant = getParticipantById(state, id);
|
||||
|
||||
if (!participant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* First check if we have an unmuted video track. */
|
||||
const videoTrack = getVideoTrackByParticipant(state, participant);
|
||||
|
||||
if (!shouldRenderVideoTrack(videoTrack, /* waitForVideoStarted */ false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Then check if the participant connection or track streaming status is active. */
|
||||
if (getSourceNameSignalingFeatureFlag(state)) {
|
||||
// Note that this will work only if a listener is registered for the track's TrackStreamingStatus.
|
||||
// The associated TrackStreamingStatusImpl instance is not created or disposed when there are zero listeners.
|
||||
if (videoTrack
|
||||
&& !videoTrack.local
|
||||
&& videoTrack.jitsiTrack?.getTrackStreamingStatus() !== JitsiTrackStreamingStatus.ACTIVE) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const connectionStatus = participant.connectionStatus || JitsiParticipantConnectionStatus.ACTIVE;
|
||||
|
||||
if (connectionStatus !== JitsiParticipantConnectionStatus.ACTIVE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then check if audio-only mode is not active. */
|
||||
const audioOnly = state['features/base/audio-only'].enabled;
|
||||
|
||||
if (!audioOnly) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Last, check if the participant is sharing their screen and they are on stage. */
|
||||
const remoteScreenShares = state['features/video-layout'].remoteScreenShares || [];
|
||||
const largeVideoParticipantId = state['features/large-video'].participantId;
|
||||
const participantIsInLargeVideoWithScreen
|
||||
= participant.id === largeVideoParticipantId && remoteScreenShares.includes(participant.id);
|
||||
|
||||
return participantIsInLargeVideoWithScreen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the first loadable avatar URL for a participant.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
export * from './actions';
|
||||
export * from './actionTypes';
|
||||
export * from './components';
|
||||
export * from './constants';
|
||||
export * from './functions';
|
||||
|
|
|
@ -9,7 +9,6 @@ import { JitsiTrackEvents } from '../../../base/lib-jitsi-meet';
|
|||
import { MEDIA_TYPE, VIDEO_TYPE } from '../../../base/media';
|
||||
import {
|
||||
PARTICIPANT_ROLE,
|
||||
ParticipantView,
|
||||
getLocalParticipant,
|
||||
getParticipantByIdOrUndefined,
|
||||
getParticipantCount,
|
||||
|
@ -18,6 +17,7 @@ import {
|
|||
isScreenShareParticipant,
|
||||
pinParticipant
|
||||
} from '../../../base/participants';
|
||||
import ParticipantView from '../../../base/participants/components/ParticipantView.native';
|
||||
import { FakeParticipant } from '../../../base/participants/types';
|
||||
import { Container } from '../../../base/react';
|
||||
import { connect } from '../../../base/redux';
|
||||
|
|
|
@ -5,7 +5,8 @@ import type { Dispatch } from 'redux';
|
|||
|
||||
import { getSourceNameSignalingFeatureFlag } from '../../base/config/functions.any';
|
||||
import { JitsiTrackEvents } from '../../base/lib-jitsi-meet';
|
||||
import { ParticipantView, getParticipantById } from '../../base/participants';
|
||||
import ParticipantView from '../../base/participants/components/ParticipantView.native';
|
||||
import { getParticipantById } from '../../base/participants/functions';
|
||||
import { connect } from '../../base/redux';
|
||||
import {
|
||||
getVideoTrackByParticipant,
|
||||
|
|
Loading…
Reference in New Issue