瀏覽代碼

fix(TileView): not showing all participants.

master
Hristo Terezov 4 年之前
父節點
當前提交
88a11b9f3e

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

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
 // @flow
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
  * Sets the dimensions of the tile view grid. The action is only partially implemented on native as not all
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
 
5
 
6
 import {
6
 import {
7
     SET_HORIZONTAL_VIEW_DIMENSIONS,
7
     SET_HORIZONTAL_VIEW_DIMENSIONS,
8
-    SET_REMOTE_PARTICIPANTS,
9
     SET_TILE_VIEW_DIMENSIONS,
8
     SET_TILE_VIEW_DIMENSIONS,
10
     SET_VERTICAL_VIEW_DIMENSIONS,
9
     SET_VERTICAL_VIEW_DIMENSIONS,
11
     SET_VISIBLE_REMOTE_PARTICIPANTS,
10
     SET_VISIBLE_REMOTE_PARTICIPANTS,
26
     calculateThumbnailSizeForVerticalView
25
     calculateThumbnailSizeForVerticalView
27
 } from './functions';
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
  * Sets the dimensions of the tile view grid.
31
  * Sets the dimensions of the tile view grid.
192
         endIndex
176
         endIndex
193
     };
177
     };
194
 }
178
 }
195
-
196
-export * from './actions.native';

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

136
         tileView
136
         tileView
137
     } = props;
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
     const participantId = participant.id;
146
     const participantId = participant.id;
140
     const participantInLargeVideo
147
     const participantInLargeVideo
141
         = participantId === largeVideo.participantId;
148
         = participantId === largeVideo.participantId;

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

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

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

16
     isRemoteTrackMuted
16
     isRemoteTrackMuted
17
 } from '../base/tracks/functions';
17
 } from '../base/tracks/functions';
18
 
18
 
19
-import { setRemoteParticipants } from './actions.web';
20
 import {
19
 import {
21
     ASPECT_RATIO_BREAKPOINT,
20
     ASPECT_RATIO_BREAKPOINT,
22
     DISPLAY_AVATAR,
21
     DISPLAY_AVATAR,
33
     VERTICAL_FILMSTRIP_MIN_HORIZONTAL_MARGIN
32
     VERTICAL_FILMSTRIP_MIN_HORIZONTAL_MARGIN
34
 } from './constants';
33
 } from './constants';
35
 
34
 
35
+export * from './functions.any';
36
+
36
 declare var interfaceConfig: Object;
37
 declare var interfaceConfig: Object;
37
 
38
 
38
 /**
39
 /**
266
     // check hovering and change state to avatar with name
267
     // check hovering and change state to avatar with name
267
     return isHovered ? DISPLAY_AVATAR_WITH_NAME : DISPLAY_AVATAR;
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 查看文件

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
 
13
 import {
13
 import {
14
     setHorizontalViewDimensions,
14
     setHorizontalViewDimensions,
15
-    setRemoteParticipants,
16
     setTileViewDimensions,
15
     setTileViewDimensions,
17
     setVerticalViewDimensions
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
  * The middleware of the feature Filmstrip.
22
  * The middleware of the feature Filmstrip.
52
         break;
51
         break;
53
     }
52
     }
54
     case PARTICIPANT_LEFT: {
53
     case PARTICIPANT_LEFT: {
55
-        _updateRemoteParticipantsOnLeave(store, action.participant?.id);
54
+        updateRemoteParticipantsOnLeave(store, action.participant?.id);
56
         break;
55
         break;
57
     }
56
     }
58
     case SETTINGS_UPDATED: {
57
     case SETTINGS_UPDATED: {
66
 
65
 
67
     return result;
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
                 horizontalViewDimensions: action.dimensions
117
                 horizontalViewDimensions: action.dimensions
118
             };
118
             };
119
         case SET_REMOTE_PARTICIPANTS: {
119
         case SET_REMOTE_PARTICIPANTS: {
120
-            const { visibleParticipantsStartIndex: startIndex, visibleParticipantsEndIndex: endIndex } = state;
121
-
122
             state.remoteParticipants = action.participants;
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
             return { ...state };
129
             return { ...state };
126
         }
130
         }

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

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 查看文件

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

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

12
     setHorizontalViewDimensions,
12
     setHorizontalViewDimensions,
13
     setTileViewDimensions,
13
     setTileViewDimensions,
14
     setVerticalViewDimensions
14
     setVerticalViewDimensions
15
-} from './actions.web';
15
+} from './actions';
16
 import {
16
 import {
17
     ASPECT_RATIO_BREAKPOINT,
17
     ASPECT_RATIO_BREAKPOINT,
18
     DISPLAY_DRAWER_THRESHOLD,
18
     DISPLAY_DRAWER_THRESHOLD,
19
     SINGLE_COLUMN_BREAKPOINT,
19
     SINGLE_COLUMN_BREAKPOINT,
20
     TWO_COLUMN_BREAKPOINT
20
     TWO_COLUMN_BREAKPOINT
21
 } from './constants';
21
 } from './constants';
22
-import { updateRemoteParticipants } from './functions.web';
22
+import './subscriber.any';
23
+
23
 
24
 
24
 /**
25
 /**
25
  * Listens for changes in the number of participants to calculate the dimensions of the tile view grid and the tiles.
26
  * Listens for changes in the number of participants to calculate the dimensions of the tile view grid and the tiles.
158
             store.dispatch(setTileViewDimensions(gridDimensions));
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
-}

Loading…
取消
儲存