浏览代码

fix(TileView): not showing all participants.

master
Hristo Terezov 4 年前
父节点
当前提交
88a11b9f3e

+ 52
- 0
react/features/filmstrip/actions.any.js 查看文件

@@ -0,0 +1,52 @@
1
+// @flow
2
+
3
+import { SET_FILMSTRIP_ENABLED, SET_FILMSTRIP_VISIBLE, SET_REMOTE_PARTICIPANTS } from './actionTypes';
4
+
5
+/**
6
+ * Sets whether the filmstrip is enabled.
7
+ *
8
+ * @param {boolean} enabled - Whether the filmstrip is enabled.
9
+ * @returns {{
10
+ *     type: SET_FILMSTRIP_ENABLED,
11
+ *     enabled: boolean
12
+ * }}
13
+ */
14
+export function setFilmstripEnabled(enabled: boolean) {
15
+    return {
16
+        type: SET_FILMSTRIP_ENABLED,
17
+        enabled
18
+    };
19
+}
20
+
21
+/**
22
+ * Sets whether the filmstrip is visible.
23
+ *
24
+ * @param {boolean} visible - Whether the filmstrip is visible.
25
+ * @returns {{
26
+ *     type: SET_FILMSTRIP_VISIBLE,
27
+ *     visible: boolean
28
+ * }}
29
+ */
30
+export function setFilmstripVisible(visible: boolean) {
31
+    return {
32
+        type: SET_FILMSTRIP_VISIBLE,
33
+        visible
34
+    };
35
+}
36
+
37
+/**
38
+ * Sets the list of the reordered remote participants based on which the visible participants in the filmstrip will be
39
+ * determined.
40
+ *
41
+ * @param {Array<string>} participants - The list of the remote participant endpoint IDs.
42
+ * @returns {{
43
+        type: SET_REMOTE_PARTICIPANTS,
44
+        participants: Array<string>
45
+    }}
46
+ */
47
+export function setRemoteParticipants(participants: Array<string>) {
48
+    return {
49
+        type: SET_REMOTE_PARTICIPANTS,
50
+        participants
51
+    };
52
+}

+ 2
- 36
react/features/filmstrip/actions.native.js 查看文件

@@ -1,42 +1,8 @@
1 1
 // @flow
2 2
 
3
-import {
4
-    SET_FILMSTRIP_ENABLED,
5
-    SET_FILMSTRIP_VISIBLE,
6
-    SET_TILE_VIEW_DIMENSIONS
7
-} from './actionTypes';
3
+import { SET_TILE_VIEW_DIMENSIONS } from './actionTypes';
8 4
 
9
-/**
10
- * Sets whether the filmstrip is enabled.
11
- *
12
- * @param {boolean} enabled - Whether the filmstrip is enabled.
13
- * @returns {{
14
- *     type: SET_FILMSTRIP_ENABLED,
15
- *     enabled: boolean
16
- * }}
17
- */
18
-export function setFilmstripEnabled(enabled: boolean) {
19
-    return {
20
-        type: SET_FILMSTRIP_ENABLED,
21
-        enabled
22
-    };
23
-}
24
-
25
-/**
26
- * Sets whether the filmstrip is visible.
27
- *
28
- * @param {boolean} visible - Whether the filmstrip is visible.
29
- * @returns {{
30
- *     type: SET_FILMSTRIP_VISIBLE,
31
- *     visible: boolean
32
- * }}
33
- */
34
-export function setFilmstripVisible(visible: boolean) {
35
-    return {
36
-        type: SET_FILMSTRIP_VISIBLE,
37
-        visible
38
-    };
39
-}
5
+export * from './actions.any';
40 6
 
41 7
 /**
42 8
  * Sets the dimensions of the tile view grid. The action is only partially implemented on native as not all

+ 1
- 19
react/features/filmstrip/actions.web.js 查看文件

@@ -5,7 +5,6 @@ import { getLocalParticipant, getRemoteParticipants, pinParticipant } from '../b
5 5
 
6 6
 import {
7 7
     SET_HORIZONTAL_VIEW_DIMENSIONS,
8
-    SET_REMOTE_PARTICIPANTS,
9 8
     SET_TILE_VIEW_DIMENSIONS,
10 9
     SET_VERTICAL_VIEW_DIMENSIONS,
11 10
     SET_VISIBLE_REMOTE_PARTICIPANTS,
@@ -26,22 +25,7 @@ import {
26 25
     calculateThumbnailSizeForVerticalView
27 26
 } from './functions';
28 27
 
29
-/**
30
- * Sets the list of the reordered remote participants based on which the visible participants in the filmstrip will be
31
- * determined.
32
- *
33
- * @param {Array<string>} participants - The list of the remote participant endpoint IDs.
34
- * @returns {{
35
-        type: SET_REMOTE_PARTICIPANTS,
36
-        participants: Array<string>
37
-    }}
38
- */
39
-export function setRemoteParticipants(participants: Array<string>) {
40
-    return {
41
-        type: SET_REMOTE_PARTICIPANTS,
42
-        participants
43
-    };
44
-}
28
+export * from './actions.any';
45 29
 
46 30
 /**
47 31
  * Sets the dimensions of the tile view grid.
@@ -192,5 +176,3 @@ export function setVisibleRemoteParticipants(startIndex: number, endIndex: numbe
192 176
         endIndex
193 177
     };
194 178
 }
195
-
196
-export * from './actions.native';

+ 7
- 0
react/features/filmstrip/components/native/Thumbnail.js 查看文件

@@ -136,6 +136,13 @@ function Thumbnail(props: Props) {
136 136
         tileView
137 137
     } = props;
138 138
 
139
+    // It seems that on leave the Thumbnail for the left participant can be re-rendered.
140
+    // This will happen when mapStateToProps is executed before the remoteParticipants list in redux is updated.
141
+    if (typeof participant === 'undefined') {
142
+
143
+        return null;
144
+    }
145
+
139 146
     const participantId = participant.id;
140 147
     const participantInLargeVideo
141 148
         = participantId === largeVideo.participantId;

+ 56
- 0
react/features/filmstrip/functions.any.js 查看文件

@@ -0,0 +1,56 @@
1
+// @flow
2
+
3
+import { setRemoteParticipants } from './actions';
4
+
5
+/**
6
+ * Computes the reorderd list of the remote participants.
7
+ *
8
+ * @param {*} store - The redux store.
9
+ * @returns {void}
10
+ * @private
11
+ */
12
+export function updateRemoteParticipants(store: Object) {
13
+    const state = store.getState();
14
+    const { fakeParticipants, sortedRemoteParticipants, speakersList } = state['features/base/participants'];
15
+    const { remoteScreenShares } = state['features/video-layout'];
16
+    const screenShares = (remoteScreenShares || []).slice();
17
+    let speakers = (speakersList || []).slice();
18
+    const remoteParticipants = new Map(sortedRemoteParticipants);
19
+    const sharedVideos = fakeParticipants ? Array.from(fakeParticipants.keys()) : [];
20
+
21
+    for (const screenshare of screenShares) {
22
+        remoteParticipants.delete(screenshare);
23
+        speakers = speakers.filter(speaker => speaker !== screenshare);
24
+    }
25
+    for (const sharedVideo of sharedVideos) {
26
+        remoteParticipants.delete(sharedVideo);
27
+        speakers = speakers.filter(speaker => speaker !== sharedVideo);
28
+    }
29
+    for (const speaker of speakers) {
30
+        remoteParticipants.delete(speaker);
31
+    }
32
+    const reorderedParticipants
33
+        = [ ...screenShares.reverse(), ...sharedVideos, ...speakers, ...Array.from(remoteParticipants.keys()) ];
34
+
35
+    store.dispatch(setRemoteParticipants(reorderedParticipants));
36
+}
37
+
38
+/**
39
+ * Private helper to calculate the reordered list of remote participants when a participant leaves.
40
+ *
41
+ * @param {*} store - The redux store.
42
+ * @param {string} participantId - The endpoint id of the participant leaving the call.
43
+ * @returns {void}
44
+ * @private
45
+ */
46
+export function updateRemoteParticipantsOnLeave(store: Object, participantId: ?string = null) {
47
+    if (!participantId) {
48
+        return;
49
+    }
50
+    const state = store.getState();
51
+    const { remoteParticipants } = state['features/filmstrip'];
52
+    const reorderedParticipants = new Set(remoteParticipants);
53
+
54
+    reorderedParticipants.delete(participantId)
55
+        && store.dispatch(setRemoteParticipants(Array.from(reorderedParticipants)));
56
+}

+ 2
- 0
react/features/filmstrip/functions.native.js 查看文件

@@ -4,6 +4,8 @@ import { getFeatureFlag, FILMSTRIP_ENABLED } from '../base/flags';
4 4
 import { getParticipantCountWithFake, getPinnedParticipant } from '../base/participants';
5 5
 import { toState } from '../base/redux';
6 6
 
7
+export * from './functions.any';
8
+
7 9
 /**
8 10
  * Returns true if the filmstrip on mobile is visible, false otherwise.
9 11
  *

+ 2
- 34
react/features/filmstrip/functions.web.js 查看文件

@@ -16,7 +16,6 @@ import {
16 16
     isRemoteTrackMuted
17 17
 } from '../base/tracks/functions';
18 18
 
19
-import { setRemoteParticipants } from './actions.web';
20 19
 import {
21 20
     ASPECT_RATIO_BREAKPOINT,
22 21
     DISPLAY_AVATAR,
@@ -33,6 +32,8 @@ import {
33 32
     VERTICAL_FILMSTRIP_MIN_HORIZONTAL_MARGIN
34 33
 } from './constants';
35 34
 
35
+export * from './functions.any';
36
+
36 37
 declare var interfaceConfig: Object;
37 38
 
38 39
 /**
@@ -266,36 +267,3 @@ export function computeDisplayMode(input: Object) {
266 267
     // check hovering and change state to avatar with name
267 268
     return isHovered ? DISPLAY_AVATAR_WITH_NAME : DISPLAY_AVATAR;
268 269
 }
269
-
270
-/**
271
- * Computes the reorderd list of the remote participants.
272
- *
273
- * @param {*} store - The redux store.
274
- * @returns {void}
275
- * @private
276
- */
277
-export function updateRemoteParticipants(store: Object) {
278
-    const state = store.getState();
279
-    const { fakeParticipants, sortedRemoteParticipants, speakersList } = state['features/base/participants'];
280
-    const { remoteScreenShares } = state['features/video-layout'];
281
-    const screenShares = (remoteScreenShares || []).slice();
282
-    let speakers = (speakersList || []).slice();
283
-    const remoteParticipants = new Map(sortedRemoteParticipants);
284
-    const sharedVideos = fakeParticipants ? Array.from(fakeParticipants.keys()) : [];
285
-
286
-    for (const screenshare of screenShares) {
287
-        remoteParticipants.delete(screenshare);
288
-        speakers = speakers.filter(speaker => speaker !== screenshare);
289
-    }
290
-    for (const sharedVideo of sharedVideos) {
291
-        remoteParticipants.delete(sharedVideo);
292
-        speakers = speakers.filter(speaker => speaker !== sharedVideo);
293
-    }
294
-    for (const speaker of speakers) {
295
-        remoteParticipants.delete(speaker);
296
-    }
297
-    const reorderedParticipants
298
-        = [ ...screenShares.reverse(), ...sharedVideos, ...speakers, ...Array.from(remoteParticipants.keys()) ];
299
-
300
-    store.dispatch(setRemoteParticipants(reorderedParticipants));
301
-}

+ 28
- 0
react/features/filmstrip/middleware.native.js 查看文件

@@ -0,0 +1,28 @@
1
+// @flow
2
+
3
+import { PARTICIPANT_JOINED, PARTICIPANT_LEFT } from '../base/participants';
4
+import { MiddlewareRegistry } from '../base/redux';
5
+
6
+import { updateRemoteParticipants, updateRemoteParticipantsOnLeave } from './functions';
7
+import './subscriber';
8
+
9
+/**
10
+ * The middleware of the feature Filmstrip.
11
+ */
12
+MiddlewareRegistry.register(store => next => action => {
13
+    const result = next(action);
14
+
15
+    switch (action.type) {
16
+    case PARTICIPANT_JOINED: {
17
+        updateRemoteParticipants(store);
18
+        break;
19
+    }
20
+    case PARTICIPANT_LEFT: {
21
+        updateRemoteParticipantsOnLeave(store, action.participant?.id);
22
+        break;
23
+    }
24
+    }
25
+
26
+    return result;
27
+});
28
+

+ 4
- 25
react/features/filmstrip/middleware.web.js 查看文件

@@ -12,12 +12,11 @@ import {
12 12
 
13 13
 import {
14 14
     setHorizontalViewDimensions,
15
-    setRemoteParticipants,
16 15
     setTileViewDimensions,
17 16
     setVerticalViewDimensions
18
-} from './actions.web';
19
-import { updateRemoteParticipants } from './functions.web';
20
-import './subscriber.web';
17
+} from './actions';
18
+import { updateRemoteParticipants, updateRemoteParticipantsOnLeave } from './functions';
19
+import './subscriber';
21 20
 
22 21
 /**
23 22
  * The middleware of the feature Filmstrip.
@@ -52,7 +51,7 @@ MiddlewareRegistry.register(store => next => action => {
52 51
         break;
53 52
     }
54 53
     case PARTICIPANT_LEFT: {
55
-        _updateRemoteParticipantsOnLeave(store, action.participant?.id);
54
+        updateRemoteParticipantsOnLeave(store, action.participant?.id);
56 55
         break;
57 56
     }
58 57
     case SETTINGS_UPDATED: {
@@ -66,23 +65,3 @@ MiddlewareRegistry.register(store => next => action => {
66 65
 
67 66
     return result;
68 67
 });
69
-
70
-/**
71
- * Private helper to calculate the reordered list of remote participants when a participant leaves.
72
- *
73
- * @param {*} store - The redux store.
74
- * @param {string} participantId - The endpoint id of the participant leaving the call.
75
- * @returns {void}
76
- * @private
77
- */
78
-function _updateRemoteParticipantsOnLeave(store, participantId = null) {
79
-    if (!participantId) {
80
-        return;
81
-    }
82
-    const state = store.getState();
83
-    const { remoteParticipants } = state['features/filmstrip'];
84
-    const reorderedParticipants = new Set(remoteParticipants);
85
-
86
-    reorderedParticipants.delete(participantId)
87
-        && store.dispatch(setRemoteParticipants(Array.from(reorderedParticipants)));
88
-}

+ 7
- 3
react/features/filmstrip/reducer.js 查看文件

@@ -117,10 +117,14 @@ ReducerRegistry.register(
117 117
                 horizontalViewDimensions: action.dimensions
118 118
             };
119 119
         case SET_REMOTE_PARTICIPANTS: {
120
-            const { visibleParticipantsStartIndex: startIndex, visibleParticipantsEndIndex: endIndex } = state;
121
-
122 120
             state.remoteParticipants = action.participants;
123
-            state.visibleRemoteParticipants = new Set(state.remoteParticipants.slice(startIndex, endIndex));
121
+
122
+            // TODO: implement this on mobile.
123
+            if (navigator.product !== 'ReactNative') {
124
+                const { visibleParticipantsStartIndex: startIndex, visibleParticipantsEndIndex: endIndex } = state;
125
+
126
+                state.visibleRemoteParticipants = new Set(state.remoteParticipants.slice(startIndex, endIndex));
127
+            }
124 128
 
125 129
             return { ...state };
126 130
         }

+ 38
- 0
react/features/filmstrip/subscriber.any.js 查看文件

@@ -0,0 +1,38 @@
1
+// @flow
2
+
3
+import { StateListenerRegistry } from '../base/redux';
4
+
5
+import { updateRemoteParticipants } from './functions';
6
+
7
+/**
8
+ * Listens for changes to the screensharing status of the remote participants to recompute the reordered list of the
9
+ * remote endpoints.
10
+ */
11
+StateListenerRegistry.register(
12
+    /* selector */ state => state['features/video-layout'].remoteScreenShares,
13
+    /* listener */ (remoteScreenShares, store) => updateRemoteParticipants(store));
14
+
15
+/**
16
+ * Listens for changes to the dominant speaker to recompute the reordered list of the remote endpoints.
17
+ */
18
+StateListenerRegistry.register(
19
+    /* selector */ state => state['features/base/participants'].dominantSpeaker,
20
+    /* listener */ (dominantSpeaker, store) => _reorderDominantSpeakers(store));
21
+
22
+/**
23
+ * Private helper function that reorders the remote participants based on dominant speaker changes.
24
+ *
25
+ * @param {*} store - The redux store.
26
+ * @returns {void}
27
+ * @private
28
+ */
29
+function _reorderDominantSpeakers(store) {
30
+    const state = store.getState();
31
+    const { dominantSpeaker, local } = state['features/base/participants'];
32
+    const { visibleRemoteParticipants } = state['features/filmstrip'];
33
+
34
+    // Reorder the participants if the new dominant speaker is currently not visible.
35
+    if (dominantSpeaker !== local?.id && !visibleRemoteParticipants.has(dominantSpeaker)) {
36
+        updateRemoteParticipants(store);
37
+    }
38
+}

+ 3
- 0
react/features/filmstrip/subscriber.native.js 查看文件

@@ -0,0 +1,3 @@
1
+// @flow
2
+
3
+import './subscriber.any';

+ 3
- 35
react/features/filmstrip/subscriber.web.js 查看文件

@@ -12,14 +12,15 @@ import {
12 12
     setHorizontalViewDimensions,
13 13
     setTileViewDimensions,
14 14
     setVerticalViewDimensions
15
-} from './actions.web';
15
+} from './actions';
16 16
 import {
17 17
     ASPECT_RATIO_BREAKPOINT,
18 18
     DISPLAY_DRAWER_THRESHOLD,
19 19
     SINGLE_COLUMN_BREAKPOINT,
20 20
     TWO_COLUMN_BREAKPOINT
21 21
 } from './constants';
22
-import { updateRemoteParticipants } from './functions.web';
22
+import './subscriber.any';
23
+
23 24
 
24 25
 /**
25 26
  * Listens for changes in the number of participants to calculate the dimensions of the tile view grid and the tiles.
@@ -158,36 +159,3 @@ StateListenerRegistry.register(
158 159
             store.dispatch(setTileViewDimensions(gridDimensions));
159 160
         }
160 161
     });
161
-
162
-/**
163
- * Listens for changes to the screensharing status of the remote participants to recompute the reordered list of the
164
- * remote endpoints.
165
- */
166
-StateListenerRegistry.register(
167
-    /* selector */ state => state['features/video-layout'].remoteScreenShares,
168
-    /* listener */ (remoteScreenShares, store) => updateRemoteParticipants(store));
169
-
170
-/**
171
- * Listens for changes to the dominant speaker to recompute the reordered list of the remote endpoints.
172
- */
173
-StateListenerRegistry.register(
174
-    /* selector */ state => state['features/base/participants'].dominantSpeaker,
175
-    /* listener */ (dominantSpeaker, store) => _reorderDominantSpeakers(store));
176
-
177
-/**
178
- * Private helper function that reorders the remote participants based on dominant speaker changes.
179
- *
180
- * @param {*} store - The redux store.
181
- * @returns {void}
182
- * @private
183
- */
184
-function _reorderDominantSpeakers(store) {
185
-    const state = store.getState();
186
-    const { dominantSpeaker, local } = state['features/base/participants'];
187
-    const { visibleRemoteParticipants } = state['features/filmstrip'];
188
-
189
-    // Reorder the participants if the new dominant speaker is currently not visible.
190
-    if (dominantSpeaker !== local?.id && !visibleRemoteParticipants.has(dominantSpeaker)) {
191
-        updateRemoteParticipants(store);
192
-    }
193
-}

正在加载...
取消
保存