|
|
|
@ -7,6 +7,7 @@ import { translate } from '../../../base/i18n'; |
|
|
|
|
import { Icon, IconConnectionActive, IconConnectionInactive } from '../../../base/icons'; |
|
|
|
|
import { JitsiParticipantConnectionStatus } from '../../../base/lib-jitsi-meet'; |
|
|
|
|
import { MEDIA_TYPE } from '../../../base/media'; |
|
|
|
|
import { getLocalParticipant, getParticipantById } from '../../../base/participants'; |
|
|
|
|
import { Popover } from '../../../base/popover'; |
|
|
|
|
import { connect } from '../../../base/redux'; |
|
|
|
|
import { getTrackByMediaTypeAndParticipant } from '../../../base/tracks'; |
|
|
|
@ -61,6 +62,12 @@ const QUALITY_TO_WIDTH: Array<Object> = [ |
|
|
|
|
*/ |
|
|
|
|
type Props = AbstractProps & { |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* The current condition of the user's connection, matching one of the |
|
|
|
|
* enumerated values in the library. |
|
|
|
|
*/ |
|
|
|
|
_connectionStatus: string, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Whether or not the component should ignore setting a visibility class for |
|
|
|
|
* hiding the component when the connection quality is not strong. |
|
|
|
@ -72,12 +79,6 @@ type Props = AbstractProps & { |
|
|
|
|
*/ |
|
|
|
|
audioSsrc: number, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* The current condition of the user's connection, matching one of the |
|
|
|
|
* enumerated values in the library. |
|
|
|
|
*/ |
|
|
|
|
connectionStatus: string, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* The Redux dispatch function. |
|
|
|
|
*/ |
|
|
|
@ -200,13 +201,13 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> { |
|
|
|
|
* @returns {string} |
|
|
|
|
*/ |
|
|
|
|
_getConnectionColorClass() { |
|
|
|
|
const { connectionStatus } = this.props; |
|
|
|
|
const { _connectionStatus } = this.props; |
|
|
|
|
const { percent } = this.state.stats; |
|
|
|
|
const { INACTIVE, INTERRUPTED } = JitsiParticipantConnectionStatus; |
|
|
|
|
|
|
|
|
|
if (connectionStatus === INACTIVE) { |
|
|
|
|
if (_connectionStatus === INACTIVE) { |
|
|
|
|
return 'status-other'; |
|
|
|
|
} else if (connectionStatus === INTERRUPTED) { |
|
|
|
|
} else if (_connectionStatus === INTERRUPTED) { |
|
|
|
|
return 'status-lost'; |
|
|
|
|
} else if (typeof percent === 'undefined') { |
|
|
|
|
return 'status-high'; |
|
|
|
@ -224,7 +225,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> { |
|
|
|
|
_getConnectionStatusTip() { |
|
|
|
|
let tipKey; |
|
|
|
|
|
|
|
|
|
switch (this.props.connectionStatus) { |
|
|
|
|
switch (this.props._connectionStatus) { |
|
|
|
|
case JitsiParticipantConnectionStatus.INTERRUPTED: |
|
|
|
|
tipKey = 'connectionindicator.quality.lost'; |
|
|
|
|
break; |
|
|
|
@ -275,12 +276,12 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> { |
|
|
|
|
* @returns {string} |
|
|
|
|
*/ |
|
|
|
|
_getVisibilityClass() { |
|
|
|
|
const { connectionStatus } = this.props; |
|
|
|
|
const { _connectionStatus } = this.props; |
|
|
|
|
|
|
|
|
|
return this.state.showIndicator |
|
|
|
|
|| this.props.alwaysVisible |
|
|
|
|
|| connectionStatus === JitsiParticipantConnectionStatus.INTERRUPTED |
|
|
|
|
|| connectionStatus === JitsiParticipantConnectionStatus.INACTIVE |
|
|
|
|
|| _connectionStatus === JitsiParticipantConnectionStatus.INTERRUPTED |
|
|
|
|
|| _connectionStatus === JitsiParticipantConnectionStatus.INACTIVE |
|
|
|
|
? 'show-connection-indicator' : 'hide-connection-indicator'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -304,7 +305,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> { |
|
|
|
|
* @returns {ReactElement} |
|
|
|
|
*/ |
|
|
|
|
_renderIcon() { |
|
|
|
|
if (this.props.connectionStatus |
|
|
|
|
if (this.props._connectionStatus |
|
|
|
|
=== JitsiParticipantConnectionStatus.INACTIVE) { |
|
|
|
|
return ( |
|
|
|
|
<span className = 'connection_ninja'> |
|
|
|
@ -319,7 +320,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> { |
|
|
|
|
let iconWidth; |
|
|
|
|
let emptyIconWrapperClassName = 'connection_empty'; |
|
|
|
|
|
|
|
|
|
if (this.props.connectionStatus |
|
|
|
|
if (this.props._connectionStatus |
|
|
|
|
=== JitsiParticipantConnectionStatus.INTERRUPTED) { |
|
|
|
|
|
|
|
|
|
// emptyIconWrapperClassName is used by the torture tests to
|
|
|
|
@ -434,21 +435,29 @@ export function _mapDispatchToProps(dispatch: Dispatch<any>) { |
|
|
|
|
* @returns {Props} |
|
|
|
|
*/ |
|
|
|
|
export function _mapStateToProps(state: Object, ownProps: Props) { |
|
|
|
|
|
|
|
|
|
const { participantId } = ownProps; |
|
|
|
|
const conference = state['features/base/conference'].conference; |
|
|
|
|
const participant |
|
|
|
|
= typeof participantId === 'undefined' ? getLocalParticipant(state) : getParticipantById(state, participantId); |
|
|
|
|
const props = { |
|
|
|
|
_connectionStatus: participant?.connectionStatus |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
if (conference) { |
|
|
|
|
const firstVideoTrack = getTrackByMediaTypeAndParticipant( |
|
|
|
|
state['features/base/tracks'], MEDIA_TYPE.VIDEO, ownProps.participantId); |
|
|
|
|
state['features/base/tracks'], MEDIA_TYPE.VIDEO, participantId); |
|
|
|
|
const firstAudioTrack = getTrackByMediaTypeAndParticipant( |
|
|
|
|
state['features/base/tracks'], MEDIA_TYPE.AUDIO, ownProps.participantId); |
|
|
|
|
state['features/base/tracks'], MEDIA_TYPE.AUDIO, participantId); |
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
...props, |
|
|
|
|
audioSsrc: firstAudioTrack ? conference.getSsrcByTrack(firstAudioTrack.jitsiTrack) : undefined, |
|
|
|
|
videoSsrc: firstVideoTrack ? conference.getSsrcByTrack(firstVideoTrack.jitsiTrack) : undefined |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return {}; |
|
|
|
|
return { |
|
|
|
|
...props |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
export default translate(connect(_mapStateToProps, _mapDispatchToProps)(ConnectionIndicator)); |
|
|
|
|