You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ConnectionIndicator.tsx 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import React from 'react';
  2. import { StyleProp, View, ViewStyle } from 'react-native';
  3. import { connect } from 'react-redux';
  4. import { IReduxState } from '../../../app/types';
  5. import { IconConnection } from '../../../base/icons/svg';
  6. import { MEDIA_TYPE } from '../../../base/media/constants';
  7. import {
  8. getLocalParticipant,
  9. getParticipantById,
  10. isScreenShareParticipant
  11. } from '../../../base/participants/functions';
  12. import BaseIndicator from '../../../base/react/components/native/BaseIndicator';
  13. import {
  14. getTrackByMediaTypeAndParticipant
  15. } from '../../../base/tracks/functions.native';
  16. import indicatorStyles from '../../../filmstrip/components/native/styles';
  17. import {
  18. isTrackStreamingStatusInactive,
  19. isTrackStreamingStatusInterrupted
  20. } from '../../functions';
  21. import AbstractConnectionIndicator, {
  22. IProps as AbstractProps,
  23. mapStateToProps as _abstractMapStateToProps
  24. } from '../AbstractConnectionIndicator';
  25. import {
  26. CONNECTOR_INDICATOR_COLORS,
  27. CONNECTOR_INDICATOR_LOST,
  28. CONNECTOR_INDICATOR_OTHER,
  29. iconStyle
  30. } from './styles';
  31. type IProps = AbstractProps & {
  32. /**
  33. * Whether connection indicators are disabled or not.
  34. */
  35. _connectionIndicatorDisabled: boolean;
  36. /**
  37. * Whether the inactive connection indicator is disabled or not.
  38. */
  39. _connectionIndicatorInactiveDisabled: boolean;
  40. /**
  41. * Whether the connection is inactive or not.
  42. */
  43. _isConnectionStatusInactive?: boolean;
  44. /**
  45. * Whether the connection is interrupted or not.
  46. */
  47. _isConnectionStatusInterrupted?: boolean;
  48. /**
  49. * Whether the current participant is a virtual screenshare.
  50. */
  51. _isVirtualScreenshareParticipant: boolean;
  52. /**
  53. * Redux dispatch function.
  54. */
  55. dispatch: Function;
  56. /**
  57. * Icon style override.
  58. */
  59. iconStyle?: any;
  60. };
  61. type IState = {
  62. autoHideTimeout: number | undefined;
  63. showIndicator: boolean;
  64. stats: any;
  65. };
  66. /**
  67. * Implements an indicator to show the quality of the connection of a participant.
  68. */
  69. class ConnectionIndicator extends AbstractConnectionIndicator<IProps, IState> {
  70. /**
  71. * Initializes a new {@code ConnectionIndicator} instance.
  72. *
  73. * @inheritdoc
  74. */
  75. constructor(props: IProps) {
  76. super(props);
  77. // @ts-ignore
  78. this.state = {
  79. autoHideTimeout: undefined,
  80. showIndicator: false,
  81. stats: {}
  82. };
  83. }
  84. /**
  85. * Get the icon configuration from CONNECTOR_INDICATOR_COLORS which has a percentage
  86. * that matches or exceeds the passed in percentage. The implementation
  87. * assumes CONNECTOR_INDICATOR_COLORS is already sorted by highest to lowest
  88. * percentage.
  89. *
  90. * @param {number} percent - The connection percentage, out of 100, to find
  91. * the closest matching configuration for.
  92. * @private
  93. * @returns {Object}
  94. */
  95. _getDisplayConfiguration(percent: number): any {
  96. return CONNECTOR_INDICATOR_COLORS.find(x => percent >= x.percent) || {};
  97. }
  98. /**
  99. * Implements React's {@link Component#render()}.
  100. *
  101. * @inheritdoc
  102. * @returns {ReactElement}
  103. */
  104. render() {
  105. const {
  106. _connectionIndicatorInactiveDisabled,
  107. _connectionIndicatorDisabled,
  108. _isVirtualScreenshareParticipant,
  109. _isConnectionStatusInactive,
  110. _isConnectionStatusInterrupted
  111. } = this.props;
  112. const {
  113. showIndicator,
  114. stats
  115. } = this.state;
  116. const { percent } = stats;
  117. if (!showIndicator || typeof percent === 'undefined'
  118. || _connectionIndicatorDisabled || _isVirtualScreenshareParticipant) {
  119. return null;
  120. }
  121. let indicatorColor;
  122. if (_isConnectionStatusInactive) {
  123. if (_connectionIndicatorInactiveDisabled) {
  124. return null;
  125. }
  126. indicatorColor = CONNECTOR_INDICATOR_OTHER;
  127. } else if (_isConnectionStatusInterrupted) {
  128. indicatorColor = CONNECTOR_INDICATOR_LOST;
  129. } else {
  130. const displayConfig = this._getDisplayConfiguration(percent);
  131. if (!displayConfig) {
  132. return null;
  133. }
  134. indicatorColor = displayConfig.color;
  135. }
  136. return (
  137. <View
  138. style = { [
  139. indicatorStyles.indicatorContainer as StyleProp<ViewStyle>,
  140. { backgroundColor: indicatorColor }
  141. ] }>
  142. <BaseIndicator
  143. icon = { IconConnection }
  144. iconStyle = { this.props.iconStyle || iconStyle } />
  145. </View>
  146. );
  147. }
  148. }
  149. /**
  150. * Maps part of the Redux state to the props of this component.
  151. *
  152. * @param {Object} state - The Redux state.
  153. * @param {IProps} ownProps - The own props of the component.
  154. * @returns {IProps}
  155. */
  156. export function _mapStateToProps(state: IReduxState, ownProps: any) {
  157. const { participantId } = ownProps;
  158. const tracks = state['features/base/tracks'];
  159. const participant = participantId ? getParticipantById(state, participantId) : getLocalParticipant(state);
  160. const _isVirtualScreenshareParticipant = isScreenShareParticipant(participant);
  161. let _isConnectionStatusInactive;
  162. let _isConnectionStatusInterrupted;
  163. if (!_isVirtualScreenshareParticipant) {
  164. const _videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, participantId);
  165. _isConnectionStatusInactive = isTrackStreamingStatusInactive(_videoTrack);
  166. _isConnectionStatusInterrupted = isTrackStreamingStatusInterrupted(_videoTrack);
  167. }
  168. return {
  169. ..._abstractMapStateToProps(state),
  170. _connectionIndicatorInactiveDisabled:
  171. Boolean(state['features/base/config'].connectionIndicators?.inactiveDisabled),
  172. _connectionIndicatorDisabled:
  173. Boolean(state['features/base/config'].connectionIndicators?.disabled),
  174. _isVirtualScreenshareParticipant,
  175. _isConnectionStatusInactive,
  176. _isConnectionStatusInterrupted
  177. };
  178. }
  179. export default connect(_mapStateToProps)(ConnectionIndicator);