|
@@ -4,7 +4,8 @@ import React, { PureComponent } from 'react';
|
4
|
4
|
import { Image, View } from 'react-native';
|
5
|
5
|
import type { Dispatch } from 'redux';
|
6
|
6
|
|
7
|
|
-import { getMultipleVideoSupportFeatureFlag } from '../../../base/config';
|
|
7
|
+import { getMultipleVideoSupportFeatureFlag, getSourceNameSignalingFeatureFlag } from '../../../base/config';
|
|
8
|
+import { JitsiTrackEvents } from '../../../base/lib-jitsi-meet';
|
8
|
9
|
import { MEDIA_TYPE, VIDEO_TYPE } from '../../../base/media';
|
9
|
10
|
import {
|
10
|
11
|
PARTICIPANT_ROLE,
|
|
@@ -18,7 +19,11 @@ import {
|
18
|
19
|
} from '../../../base/participants';
|
19
|
20
|
import { Container } from '../../../base/react';
|
20
|
21
|
import { connect } from '../../../base/redux';
|
21
|
|
-import { getTrackByMediaTypeAndParticipant } from '../../../base/tracks';
|
|
22
|
+import {
|
|
23
|
+ getTrackByMediaTypeAndParticipant,
|
|
24
|
+ getVideoTrackByParticipant,
|
|
25
|
+ trackStreamingStatusChanged
|
|
26
|
+} from '../../../base/tracks';
|
22
|
27
|
import { ConnectionIndicator } from '../../../connection-indicator';
|
23
|
28
|
import { DisplayNameLabel } from '../../../display-name';
|
24
|
29
|
import { getGifDisplayMode, getGifForParticipant } from '../../../gifs/functions';
|
|
@@ -109,6 +114,16 @@ type Props = {
|
109
|
114
|
*/
|
110
|
115
|
_renderModeratorIndicator: boolean,
|
111
|
116
|
|
|
117
|
+ /**
|
|
118
|
+ * Whether source name signaling is enabled.
|
|
119
|
+ */
|
|
120
|
+ _sourceNameSignalingEnabled: boolean,
|
|
121
|
+
|
|
122
|
+ /**
|
|
123
|
+ * The video track that will be displayed in the thumbnail.
|
|
124
|
+ */
|
|
125
|
+ _videoTrack: ?Object,
|
|
126
|
+
|
112
|
127
|
/**
|
113
|
128
|
* Invoked to trigger state changes in Redux.
|
114
|
129
|
*/
|
|
@@ -151,6 +166,7 @@ class Thumbnail extends PureComponent<Props> {
|
151
|
166
|
|
152
|
167
|
this._onClick = this._onClick.bind(this);
|
153
|
168
|
this._onThumbnailLongPress = this._onThumbnailLongPress.bind(this);
|
|
169
|
+ this.handleTrackStreamingStatusChanged = this.handleTrackStreamingStatusChanged.bind(this);
|
154
|
170
|
}
|
155
|
171
|
|
156
|
172
|
_onClick: () => void;
|
|
@@ -245,6 +261,86 @@ class Thumbnail extends PureComponent<Props> {
|
245
|
261
|
return indicators;
|
246
|
262
|
}
|
247
|
263
|
|
|
264
|
+ /**
|
|
265
|
+ * Starts listening for track streaming status updates after the initial render.
|
|
266
|
+ *
|
|
267
|
+ * @inheritdoc
|
|
268
|
+ * @returns {void}
|
|
269
|
+ */
|
|
270
|
+ componentDidMount() {
|
|
271
|
+ // Listen to track streaming status changed event to keep it updated.
|
|
272
|
+ // TODO: after converting this component to a react function component,
|
|
273
|
+ // use a custom hook to update local track streaming status.
|
|
274
|
+ const { _videoTrack, dispatch, _sourceNameSignalingEnabled } = this.props;
|
|
275
|
+
|
|
276
|
+ if (_sourceNameSignalingEnabled && _videoTrack && !_videoTrack.local) {
|
|
277
|
+ _videoTrack.jitsiTrack.on(JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED,
|
|
278
|
+ this.handleTrackStreamingStatusChanged);
|
|
279
|
+ dispatch(trackStreamingStatusChanged(_videoTrack.jitsiTrack,
|
|
280
|
+ _videoTrack.jitsiTrack.getTrackStreamingStatus()));
|
|
281
|
+ }
|
|
282
|
+ }
|
|
283
|
+
|
|
284
|
+ /**
|
|
285
|
+ * Stops listening for track streaming status updates on the old track and starts listening instead on the new
|
|
286
|
+ * track.
|
|
287
|
+ *
|
|
288
|
+ * @inheritdoc
|
|
289
|
+ * @returns {void}
|
|
290
|
+ */
|
|
291
|
+ componentDidUpdate(prevProps: Props) {
|
|
292
|
+ // TODO: after converting this component to a react function component,
|
|
293
|
+ // use a custom hook to update local track streaming status.
|
|
294
|
+ const { _videoTrack, dispatch, _sourceNameSignalingEnabled } = this.props;
|
|
295
|
+
|
|
296
|
+ if (_sourceNameSignalingEnabled
|
|
297
|
+ && prevProps._videoTrack?.jitsiTrack?.getSourceName() !== _videoTrack?.jitsiTrack?.getSourceName()) {
|
|
298
|
+ if (prevProps._videoTrack && !prevProps._videoTrack.local) {
|
|
299
|
+ prevProps._videoTrack.jitsiTrack.off(JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED,
|
|
300
|
+ this.handleTrackStreamingStatusChanged);
|
|
301
|
+ dispatch(trackStreamingStatusChanged(prevProps._videoTrack.jitsiTrack,
|
|
302
|
+ prevProps._videoTrack.jitsiTrack.getTrackStreamingStatus()));
|
|
303
|
+ }
|
|
304
|
+ if (_videoTrack && !_videoTrack.local) {
|
|
305
|
+ _videoTrack.jitsiTrack.on(JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED,
|
|
306
|
+ this.handleTrackStreamingStatusChanged);
|
|
307
|
+ dispatch(trackStreamingStatusChanged(_videoTrack.jitsiTrack,
|
|
308
|
+ _videoTrack.jitsiTrack.getTrackStreamingStatus()));
|
|
309
|
+ }
|
|
310
|
+ }
|
|
311
|
+ }
|
|
312
|
+
|
|
313
|
+ /**
|
|
314
|
+ * Remove listeners for track streaming status update.
|
|
315
|
+ *
|
|
316
|
+ * @inheritdoc
|
|
317
|
+ * @returns {void}
|
|
318
|
+ */
|
|
319
|
+ componentWillUnmount() {
|
|
320
|
+ // TODO: after converting this component to a react function component,
|
|
321
|
+ // use a custom hook to update local track streaming status.
|
|
322
|
+ const { _videoTrack, dispatch, _sourceNameSignalingEnabled } = this.props;
|
|
323
|
+
|
|
324
|
+ if (_sourceNameSignalingEnabled && _videoTrack && !_videoTrack.local) {
|
|
325
|
+ _videoTrack.jitsiTrack.off(JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED,
|
|
326
|
+ this.handleTrackStreamingStatusChanged);
|
|
327
|
+ dispatch(trackStreamingStatusChanged(_videoTrack.jitsiTrack,
|
|
328
|
+ _videoTrack.jitsiTrack.getTrackStreamingStatus()));
|
|
329
|
+ }
|
|
330
|
+ }
|
|
331
|
+
|
|
332
|
+ /**
|
|
333
|
+ * Handle track streaming status change event by by dispatching an action to update track streaming status for the
|
|
334
|
+ * given track in app state.
|
|
335
|
+ *
|
|
336
|
+ * @param {JitsiTrack} jitsiTrack - The track with streaming status updated.
|
|
337
|
+ * @param {JitsiTrackStreamingStatus} streamingStatus - The updated track streaming status.
|
|
338
|
+ * @returns {void}
|
|
339
|
+ */
|
|
340
|
+ handleTrackStreamingStatusChanged(jitsiTrack, streamingStatus) {
|
|
341
|
+ this.props.dispatch(trackStreamingStatusChanged(jitsiTrack, streamingStatus));
|
|
342
|
+ }
|
|
343
|
+
|
248
|
344
|
/**
|
249
|
345
|
* Implements React's {@link Component#render()}.
|
250
|
346
|
*
|
|
@@ -289,7 +385,7 @@ class Thumbnail extends PureComponent<Props> {
|
289
|
385
|
: <>
|
290
|
386
|
<ParticipantView
|
291
|
387
|
avatarSize = { tileView ? AVATAR_SIZE * 1.5 : AVATAR_SIZE }
|
292
|
|
- disableVideo = { isScreenShare || _isFakeParticipant }
|
|
388
|
+ disableVideo = { (isScreenShare && !_isVirtualScreenshare) || _isFakeParticipant }
|
293
|
389
|
participantId = { participantId }
|
294
|
390
|
zOrder = { 1 } />
|
295
|
391
|
{
|
|
@@ -317,7 +413,7 @@ function _mapStateToProps(state, ownProps) {
|
317
|
413
|
const localParticipantId = getLocalParticipant(state).id;
|
318
|
414
|
const id = participant?.id;
|
319
|
415
|
const audioTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.AUDIO, id);
|
320
|
|
- const videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, id);
|
|
416
|
+ const videoTrack = getVideoTrackByParticipant(tracks, participant);
|
321
|
417
|
const isMultiStreamSupportEnabled = getMultipleVideoSupportFeatureFlag(state);
|
322
|
418
|
const isScreenShare = videoTrack?.videoType === VIDEO_TYPE.DESKTOP;
|
323
|
419
|
const participantCount = getParticipantCount(state);
|
|
@@ -341,7 +437,9 @@ function _mapStateToProps(state, ownProps) {
|
341
|
437
|
_pinned: participant?.pinned,
|
342
|
438
|
_raisedHand: hasRaisedHand(participant),
|
343
|
439
|
_renderDominantSpeakerIndicator: renderDominantSpeakerIndicator,
|
344
|
|
- _renderModeratorIndicator: renderModeratorIndicator
|
|
440
|
+ _renderModeratorIndicator: renderModeratorIndicator,
|
|
441
|
+ _sourceNameSignalingEnabled: getSourceNameSignalingFeatureFlag(state),
|
|
442
|
+ _videoTrack: videoTrack
|
345
|
443
|
};
|
346
|
444
|
}
|
347
|
445
|
|