Переглянути джерело

fix: Fixes selecting screen share when shared video stopped.

master
damencho 4 роки тому
джерело
коміт
5f657a7d6c

+ 61
- 3
react/features/video-layout/functions.js Переглянути файл

@@ -1,7 +1,12 @@
1 1
 // @flow
2
+import type { Dispatch } from 'redux';
2 3
 
3 4
 import { getFeatureFlag, TILE_VIEW_ENABLED } from '../base/flags';
4
-import { getPinnedParticipant, getParticipantCount } from '../base/participants';
5
+import {
6
+    getPinnedParticipant,
7
+    getParticipantCount,
8
+    pinParticipant
9
+} from '../base/participants';
5 10
 import {
6 11
     ASPECT_RATIO_BREAKPOINT,
7 12
     DEFAULT_MAX_COLUMNS,
@@ -15,6 +20,21 @@ import { LAYOUTS } from './constants';
15 20
 
16 21
 declare var interfaceConfig: Object;
17 22
 
23
+/**
24
+ * A selector for retrieving the current automatic pinning setting.
25
+ *
26
+ * @private
27
+ * @returns {string|undefined} The string "remote-only" is returned if only
28
+ * remote screen sharing should be automatically pinned, any other truthy value
29
+ * means automatically pin all screen shares. Falsy means do not automatically
30
+ * pin any screen shares.
31
+ */
32
+export function getAutoPinSetting() {
33
+    return typeof interfaceConfig === 'object'
34
+        ? interfaceConfig.AUTO_PIN_LATEST_SCREEN_SHARE
35
+        : 'remote-only';
36
+}
37
+
18 38
 /**
19 39
  * Returns the {@code LAYOUTS} constant associated with the layout
20 40
  * the application should currently be in.
@@ -72,8 +92,6 @@ export function getMaxColumnCount(state: Object) {
72 92
  * which rows will be added but no more columns.
73 93
  *
74 94
  * @param {Object} state - The redux store state.
75
- * @param {number} maxColumns - The maximum number of columns that can be
76
- * displayed.
77 95
  * @returns {Object} An object is return with the desired number of columns,
78 96
  * rows, and visible rows (the rest should overflow) for the tile view layout.
79 97
  */
@@ -148,3 +166,43 @@ export function shouldDisplayTileView(state: Object = {}) {
148 166
 
149 167
     return !shouldDisplayNormalMode;
150 168
 }
169
+
170
+/**
171
+ * Private helper to automatically pin the latest screen share stream or unpin
172
+ * if there are no more screen share streams.
173
+ *
174
+ * @param {Array<string>} screenShares - Array containing the list of all the screen sharing endpoints
175
+ * before the update was triggered (including the ones that have been removed from redux because of the update).
176
+ * @param {Store} store - The redux store.
177
+ * @returns {void}
178
+ */
179
+export function updateAutoPinnedParticipant(
180
+        screenShares: Array<string>, { dispatch, getState }: { dispatch: Dispatch<any>, getState: Function }) {
181
+    const state = getState();
182
+    const remoteScreenShares = state['features/video-layout'].remoteScreenShares;
183
+    const pinned = getPinnedParticipant(getState);
184
+
185
+    // if the pinned participant is shared video or some other fake participant we want to skip auto-pinning
186
+    if (pinned?.isFakeParticipant) {
187
+        return;
188
+    }
189
+
190
+    // Unpin the screen share when the screen sharing participant leaves. Switch to tile view if no other
191
+    // participant was pinned before screen share was auto-pinned, pin the previously pinned participant otherwise.
192
+    if (!remoteScreenShares?.length) {
193
+        let participantId = null;
194
+
195
+        if (pinned && !screenShares.find(share => share === pinned.id)) {
196
+            participantId = pinned.id;
197
+        }
198
+        dispatch(pinParticipant(participantId));
199
+
200
+        return;
201
+    }
202
+
203
+    const latestScreenShareParticipantId = remoteScreenShares[remoteScreenShares.length - 1];
204
+
205
+    if (latestScreenShareParticipantId) {
206
+        dispatch(pinParticipant(latestScreenShareParticipantId));
207
+    }
208
+}

+ 29
- 2
react/features/video-layout/middleware.any.js Переглянути файл

@@ -1,12 +1,20 @@
1 1
 // @flow
2 2
 
3 3
 import { getCurrentConference } from '../base/conference';
4
-import { PIN_PARTICIPANT, pinParticipant, getPinnedParticipant } from '../base/participants';
4
+import {
5
+    PARTICIPANT_LEFT,
6
+    PIN_PARTICIPANT,
7
+    pinParticipant,
8
+    getParticipantById,
9
+    getPinnedParticipant
10
+} from '../base/participants';
5 11
 import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
6 12
 import { SET_DOCUMENT_EDITING_STATUS } from '../etherpad';
13
+import { isFollowMeActive } from '../follow-me';
7 14
 
8 15
 import { SET_TILE_VIEW } from './actionTypes';
9 16
 import { setTileView } from './actions';
17
+import { getAutoPinSetting, updateAutoPinnedParticipant } from './functions';
10 18
 
11 19
 import './subscriber';
12 20
 
@@ -19,6 +27,20 @@ let previousTileViewEnabled;
19 27
  * @returns {Function}
20 28
  */
21 29
 MiddlewareRegistry.register(store => next => action => {
30
+
31
+    // we want to extract the leaving participant and check its type before actually the participant being removed.
32
+    let shouldUpdateAutoPin = false;
33
+
34
+    switch (action.type) {
35
+    case PARTICIPANT_LEFT: {
36
+        if (!getAutoPinSetting() || isFollowMeActive(store)) {
37
+            break;
38
+        }
39
+        shouldUpdateAutoPin = getParticipantById(store.getState(), action.participant.id)?.isFakeParticipant;
40
+        break;
41
+    }
42
+    }
43
+
22 44
     const result = next(action);
23 45
 
24 46
     switch (action.type) {
@@ -50,6 +72,11 @@ MiddlewareRegistry.register(store => next => action => {
50 72
         }
51 73
     }
52 74
 
75
+    if (shouldUpdateAutoPin) {
76
+        const screenShares = store.getState()['features/video-layout'].remoteScreenShares || [];
77
+
78
+        updateAutoPinnedParticipant(screenShares, store);
79
+    }
53 80
 
54 81
     return result;
55 82
 });
@@ -69,7 +96,7 @@ StateListenerRegistry.register(
69 96
     });
70 97
 
71 98
 /**
72
- * Respores tile view state, if it wasn't updated since then.
99
+ * Restores tile view state, if it wasn't updated since then.
73 100
  *
74 101
  * @param {Object} store - The Redux Store.
75 102
  * @returns {void}

+ 5
- 62
react/features/video-layout/subscriber.js Переглянути файл

@@ -2,15 +2,12 @@
2 2
 
3 3
 import debounce from 'lodash/debounce';
4 4
 
5
-import { pinParticipant, getPinnedParticipant } from '../base/participants';
6 5
 import { StateListenerRegistry, equals } from '../base/redux';
7 6
 import { isFollowMeActive } from '../follow-me';
8
-import { selectParticipant } from '../large-video/actions';
7
+import { selectParticipant } from '../large-video/actions.any';
9 8
 
10 9
 import { setRemoteParticipantsWithScreenShare } from './actions';
11
-
12
-declare var APP: Object;
13
-declare var interfaceConfig: Object;
10
+import { getAutoPinSetting, updateAutoPinnedParticipant } from './functions';
14 11
 
15 12
 /**
16 13
  * StateListenerRegistry provides a reliable way of detecting changes to
@@ -33,14 +30,14 @@ StateListenerRegistry.register(
33 30
 StateListenerRegistry.register(
34 31
     /* selector */ state => state['features/base/tracks'],
35 32
     /* listener */ debounce((tracks, store) => {
36
-        if (!_getAutoPinSetting() || isFollowMeActive(store)) {
33
+        if (!getAutoPinSetting() || isFollowMeActive(store)) {
37 34
             return;
38 35
         }
39 36
 
40 37
         const oldScreenSharesOrder = store.getState()['features/video-layout'].remoteScreenShares || [];
41 38
         const knownSharingParticipantIds = tracks.reduce((acc, track) => {
42 39
             if (track.mediaType === 'video' && track.videoType === 'desktop') {
43
-                const skipTrack = _getAutoPinSetting() === 'remote-only' && track.local;
40
+                const skipTrack = getAutoPinSetting() === 'remote-only' && track.local;
44 41
 
45 42
                 if (!skipTrack) {
46 43
                     acc.push(track.participantId);
@@ -68,60 +65,6 @@ StateListenerRegistry.register(
68 65
             store.dispatch(
69 66
                 setRemoteParticipantsWithScreenShare(newScreenSharesOrder));
70 67
 
71
-            _updateAutoPinnedParticipant(oldScreenSharesOrder, store);
68
+            updateAutoPinnedParticipant(oldScreenSharesOrder, store);
72 69
         }
73 70
     }, 100));
74
-
75
-/**
76
- * A selector for retrieving the current automatic pinning setting.
77
- *
78
- * @private
79
- * @returns {string|undefined} The string "remote-only" is returned if only
80
- * remote screensharing should be automatically pinned, any other truthy value
81
- * means automatically pin all screenshares. Falsy means do not automatically
82
- * pin any screenshares.
83
- */
84
-function _getAutoPinSetting() {
85
-    return typeof interfaceConfig === 'object'
86
-        ? interfaceConfig.AUTO_PIN_LATEST_SCREEN_SHARE
87
-        : 'remote-only';
88
-}
89
-
90
-/**
91
- * Private helper to automatically pin the latest screen share stream or unpin
92
- * if there are no more screen share streams.
93
- *
94
- * @param {Array<string>} screenShares - Array containing the list of all the screensharing endpoints
95
- * before the update was triggered (including the ones that have been removed from redux because of the update).
96
- * @param {Store} store - The redux store.
97
- * @returns {void}
98
- */
99
-function _updateAutoPinnedParticipant(screenShares, { dispatch, getState }) {
100
-    const state = getState();
101
-    const remoteScreenShares = state['features/video-layout'].remoteScreenShares;
102
-    const pinned = getPinnedParticipant(getState);
103
-
104
-    // if the pinned participant is shared video or some other fake participant we want to skip auto-pinning
105
-    if (pinned?.isFakeParticipant) {
106
-        return;
107
-    }
108
-
109
-    // Unpin the screenshare when the screensharing participant leaves. Switch to tile view if no other
110
-    // participant was pinned before screenshare was auto-pinned, pin the previously pinned participant otherwise.
111
-    if (!remoteScreenShares?.length) {
112
-        let participantId = null;
113
-
114
-        if (pinned && !screenShares.find(share => share === pinned.id)) {
115
-            participantId = pinned.id;
116
-        }
117
-        dispatch(pinParticipant(participantId));
118
-
119
-        return;
120
-    }
121
-
122
-    const latestScreenshareParticipantId = remoteScreenShares[remoteScreenShares.length - 1];
123
-
124
-    if (latestScreenshareParticipantId) {
125
-        dispatch(pinParticipant(latestScreenshareParticipantId));
126
-    }
127
-}

Завантаження…
Відмінити
Зберегти