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.

ParticipantView.native.js 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // @flow
  2. import React, { Component } from 'react';
  3. import { Text, View } from 'react-native';
  4. import { YoutubeLargeVideo } from '../../../youtube-player/components';
  5. import { Avatar } from '../../avatar';
  6. import { translate } from '../../i18n';
  7. import { JitsiParticipantConnectionStatus } from '../../lib-jitsi-meet';
  8. import {
  9. MEDIA_TYPE,
  10. VideoTrack
  11. } from '../../media';
  12. import { Container, TintedView } from '../../react';
  13. import { connect } from '../../redux';
  14. import type { StyleType } from '../../styles';
  15. import { TestHint } from '../../testing/components';
  16. import { getTrackByMediaTypeAndParticipant } from '../../tracks';
  17. import { shouldRenderParticipantVideo, getParticipantById } from '../functions';
  18. import styles from './styles';
  19. /**
  20. * The type of the React {@link Component} props of {@link ParticipantView}.
  21. */
  22. type Props = {
  23. /**
  24. * The connection status of the participant. Her video will only be rendered
  25. * if the connection status is 'active'; otherwise, the avatar will be
  26. * rendered. If undefined, 'active' is presumed.
  27. *
  28. * @private
  29. */
  30. _connectionStatus: string,
  31. /**
  32. * True if the participant which this component represents is fake.
  33. *
  34. * @private
  35. */
  36. _isFakeParticipant: boolean,
  37. /**
  38. * The name of the participant which this component represents.
  39. *
  40. * @private
  41. */
  42. _participantName: string,
  43. /**
  44. * True if the video should be rendered, false otherwise.
  45. */
  46. _renderVideo: boolean,
  47. /**
  48. * The video Track of the participant with {@link #participantId}.
  49. */
  50. _videoTrack: Object,
  51. /**
  52. * The avatar size.
  53. */
  54. avatarSize: number,
  55. /**
  56. * Whether video should be disabled for his view.
  57. */
  58. disableVideo: ?boolean,
  59. /**
  60. * Callback to invoke when the {@code ParticipantView} is clicked/pressed.
  61. */
  62. onPress: Function,
  63. /**
  64. * The ID of the participant (to be) depicted by {@link ParticipantView}.
  65. *
  66. * @public
  67. */
  68. participantId: string,
  69. /**
  70. * The style, if any, to apply to {@link ParticipantView} in addition to its
  71. * default style.
  72. */
  73. style: Object,
  74. /**
  75. * The function to translate human-readable text.
  76. */
  77. t: Function,
  78. /**
  79. * If true, a tinting will be applied to the view, regardless of video or
  80. * avatar is rendered.
  81. */
  82. tintEnabled: boolean,
  83. /**
  84. * The style of the tinting when applied.
  85. */
  86. tintStyle: StyleType,
  87. /**
  88. * The test hint id which can be used to locate the {@code ParticipantView}
  89. * on the jitsi-meet-torture side. If not provided, the
  90. * {@code participantId} with the following format will be used:
  91. * {@code `org.jitsi.meet.Participant#${participantId}`}
  92. */
  93. testHintId: ?string,
  94. /**
  95. * Indicates if the connectivity info label should be shown, if appropriate.
  96. * It will be shown in case the connection is interrupted.
  97. */
  98. useConnectivityInfoLabel: boolean,
  99. /**
  100. * The z-order of the {@link Video} of {@link ParticipantView} in the
  101. * stacking space of all {@code Video}s. For more details, refer to the
  102. * {@code zOrder} property of the {@code Video} class for React Native.
  103. */
  104. zOrder: number,
  105. /**
  106. * Indicates whether zooming (pinch to zoom and/or drag) is enabled.
  107. */
  108. zoomEnabled: boolean
  109. };
  110. /**
  111. * Implements a React Component which depicts a specific participant's avatar
  112. * and video.
  113. *
  114. * @extends Component
  115. */
  116. class ParticipantView extends Component<Props> {
  117. /**
  118. * Renders the connection status label, if appropriate.
  119. *
  120. * @param {string} connectionStatus - The status of the participant's
  121. * connection.
  122. * @private
  123. * @returns {ReactElement|null}
  124. */
  125. _renderConnectionInfo(connectionStatus) {
  126. let messageKey;
  127. switch (connectionStatus) {
  128. case JitsiParticipantConnectionStatus.INACTIVE:
  129. messageKey = 'connection.LOW_BANDWIDTH';
  130. break;
  131. default:
  132. return null;
  133. }
  134. const {
  135. avatarSize,
  136. _participantName: displayName,
  137. t
  138. } = this.props;
  139. // XXX Consider splitting this component into 2: one for the large view
  140. // and one for the thumbnail. Some of these don't apply to both.
  141. const containerStyle = {
  142. ...styles.connectionInfoContainer,
  143. width: avatarSize * 1.5
  144. };
  145. return (
  146. <View
  147. pointerEvents = 'box-none'
  148. style = { containerStyle }>
  149. <Text style = { styles.connectionInfoText }>
  150. { t(messageKey, { displayName }) }
  151. </Text>
  152. </View>
  153. );
  154. }
  155. /**
  156. * Implements React's {@link Component#render()}.
  157. *
  158. * @inheritdoc
  159. * @returns {ReactElement}
  160. */
  161. render() {
  162. const {
  163. _connectionStatus: connectionStatus,
  164. _isFakeParticipant,
  165. _renderVideo: renderVideo,
  166. _videoTrack: videoTrack,
  167. disableVideo,
  168. onPress,
  169. tintStyle
  170. } = this.props;
  171. // If the connection has problems, we will "tint" the video / avatar.
  172. const connectionProblem
  173. = connectionStatus !== JitsiParticipantConnectionStatus.ACTIVE;
  174. const useTint
  175. = connectionProblem || this.props.tintEnabled;
  176. const testHintId
  177. = this.props.testHintId
  178. ? this.props.testHintId
  179. : `org.jitsi.meet.Participant#${this.props.participantId}`;
  180. const renderYoutubeLargeVideo = _isFakeParticipant && !disableVideo;
  181. return (
  182. <Container
  183. onClick = { renderVideo || renderYoutubeLargeVideo ? undefined : onPress }
  184. style = {{
  185. ...styles.participantView,
  186. ...this.props.style
  187. }}
  188. touchFeedback = { false }>
  189. <TestHint
  190. id = { testHintId }
  191. onPress = { renderYoutubeLargeVideo ? undefined : onPress }
  192. value = '' />
  193. { renderYoutubeLargeVideo && <YoutubeLargeVideo youtubeId = { this.props.participantId } /> }
  194. { !_isFakeParticipant && renderVideo
  195. && <VideoTrack
  196. onPress = { onPress }
  197. videoTrack = { videoTrack }
  198. waitForVideoStarted = { false }
  199. zOrder = { this.props.zOrder }
  200. zoomEnabled = { this.props.zoomEnabled } /> }
  201. { !renderYoutubeLargeVideo && !renderVideo
  202. && <View style = { styles.avatarContainer }>
  203. <Avatar
  204. participantId = { this.props.participantId }
  205. size = { this.props.avatarSize } />
  206. </View> }
  207. { useTint
  208. // If the connection has problems, tint the video / avatar.
  209. && <TintedView
  210. style = {
  211. connectionProblem ? undefined : tintStyle } /> }
  212. { this.props.useConnectivityInfoLabel
  213. && this._renderConnectionInfo(connectionStatus) }
  214. </Container>
  215. );
  216. }
  217. }
  218. /**
  219. * Maps (parts of) the redux state to the associated {@link ParticipantView}'s
  220. * props.
  221. *
  222. * @param {Object} state - The redux state.
  223. * @param {Object} ownProps - The React {@code Component} props passed to the
  224. * associated (instance of) {@code ParticipantView}.
  225. * @private
  226. * @returns {Props}
  227. */
  228. function _mapStateToProps(state, ownProps) {
  229. const { disableVideo, participantId } = ownProps;
  230. const participant = getParticipantById(state, participantId);
  231. let connectionStatus;
  232. let participantName;
  233. return {
  234. _connectionStatus:
  235. connectionStatus
  236. || JitsiParticipantConnectionStatus.ACTIVE,
  237. _isFakeParticipant: participant && participant.isFakeParticipant,
  238. _participantName: participantName,
  239. _renderVideo: shouldRenderParticipantVideo(state, participantId) && !disableVideo,
  240. _videoTrack:
  241. getTrackByMediaTypeAndParticipant(
  242. state['features/base/tracks'],
  243. MEDIA_TYPE.VIDEO,
  244. participantId)
  245. };
  246. }
  247. export default translate(connect(_mapStateToProps)(ParticipantView));