Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

ParticipantView.native.js 8.5KB

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