浏览代码

Associate remote participant w/ JitsiConference (_JOINED)

The plan set in motion here is to associate remote participants with the
JitsiConference instances that created them in order to be able to
remove remote participants when a JitsiConference is no longer the
primary focus of the jitsi-meet app. And that's supposed to alleviate a
problem with multiplying remote thumbnails.

Doing all of the above in a single commit is a bit of a high order. So
I'm splitting the whole into multiple successive commits for the
purposes of observability, comprehension. Each commit is supposed to be
safe even if subsequent commits are not accepted, are reverted,
whatever. Obviously, without the successive commits, a commit may be
"unused".

One of the important pieces of the multiplying remote thumbnails "fix"
offered is removing remote participants who are no longer of interest
i.e. PARTICIPANT_LEFT. But in order for _LEFT to be implemented, _JOINED
must be implemented first.
j8
Lyubo Marinov 7 年前
父节点
当前提交
983e62ffe9

+ 1
- 0
conference.js 查看文件

1688
             const displayName = user.getDisplayName();
1688
             const displayName = user.getDisplayName();
1689
 
1689
 
1690
             APP.store.dispatch(participantJoined({
1690
             APP.store.dispatch(participantJoined({
1691
+                conference: room,
1691
                 id,
1692
                 id,
1692
                 name: displayName,
1693
                 name: displayName,
1693
                 role: user.getRole()
1694
                 role: user.getRole()

+ 1
- 0
modules/UI/shared_video/SharedVideo.js 查看文件

306
                 SHARED_VIDEO_CONTAINER_TYPE, self.sharedVideo);
306
                 SHARED_VIDEO_CONTAINER_TYPE, self.sharedVideo);
307
 
307
 
308
             APP.store.dispatch(participantJoined({
308
             APP.store.dispatch(participantJoined({
309
+                conference: APP.conference,
309
                 id: self.url,
310
                 id: self.url,
310
                 isBot: true,
311
                 isBot: true,
311
                 name: 'YouTube'
312
                 name: 'YouTube'

+ 1
- 0
react/features/base/conference/actions.js 查看文件

140
     conference.on(
140
     conference.on(
141
         JitsiConferenceEvents.USER_JOINED,
141
         JitsiConferenceEvents.USER_JOINED,
142
         (id, user) => dispatch(participantJoined({
142
         (id, user) => dispatch(participantJoined({
143
+            conference,
143
             id,
144
             id,
144
             name: user.getDisplayName(),
145
             name: user.getDisplayName(),
145
             role: user.getRole()
146
             role: user.getRole()

+ 8
- 5
react/features/base/participants/actions.js 查看文件

214
  *
214
  *
215
  * @param {Participant} participant - Information about participant.
215
  * @param {Participant} participant - Information about participant.
216
  * @returns {{
216
  * @returns {{
217
- *      type: PARTICIPANT_JOINED,
218
- *      participant: Participant
217
+ *     type: PARTICIPANT_JOINED,
218
+ *     participant: Participant
219
  * }}
219
  * }}
220
  */
220
  */
221
 export function participantJoined(participant) {
221
 export function participantJoined(participant) {
222
+    if (!participant.local && !participant.conference) {
223
+        throw Error(
224
+            'A remote participant must be associated with a JitsiConference!');
225
+    }
226
+
222
     return {
227
     return {
223
         type: PARTICIPANT_JOINED,
228
         type: PARTICIPANT_JOINED,
224
         participant
229
         participant
393
     joinedParticipantsNames.push(
398
     joinedParticipantsNames.push(
394
         displayName || interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME);
399
         displayName || interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME);
395
 
400
 
396
-    return dispatch => {
397
-        _throttledNotifyParticipantConnected(dispatch);
398
-    };
401
+    return dispatch => _throttledNotifyParticipantConnected(dispatch);
399
 }
402
 }

+ 8
- 5
react/features/base/participants/middleware.js 查看文件

139
  */
139
  */
140
 function _localParticipantJoined({ getState, dispatch }, next, action) {
140
 function _localParticipantJoined({ getState, dispatch }, next, action) {
141
     const result = next(action);
141
     const result = next(action);
142
+
142
     const settings = getState()['features/base/settings'];
143
     const settings = getState()['features/base/settings'];
143
-    const localParticipant = {
144
+
145
+    dispatch(localParticipantJoined({
144
         avatarID: settings.avatarID,
146
         avatarID: settings.avatarID,
145
         avatarURL: settings.avatarURL,
147
         avatarURL: settings.avatarURL,
146
         email: settings.email,
148
         email: settings.email,
147
         name: settings.displayName
149
         name: settings.displayName
148
-    };
149
-
150
-    dispatch(localParticipantJoined(localParticipant));
150
+    }));
151
 
151
 
152
     return result;
152
     return result;
153
 }
153
 }
204
         if (local) {
204
         if (local) {
205
             const { conference } = getState()['features/base/conference'];
205
             const { conference } = getState()['features/base/conference'];
206
 
206
 
207
-            conference.setLocalParticipantProperty('raisedHand', raisedHand);
207
+            conference
208
+                && conference.setLocalParticipantProperty(
209
+                    'raisedHand',
210
+                    raisedHand);
208
         }
211
         }
209
 
212
 
210
         if (typeof APP === 'object') {
213
         if (typeof APP === 'object') {

+ 81
- 69
react/features/base/participants/reducer.js 查看文件

39
 const PARTICIPANT_PROPS_TO_OMIT_WHEN_UPDATE
39
 const PARTICIPANT_PROPS_TO_OMIT_WHEN_UPDATE
40
     = [ 'dominantSpeaker', 'id', 'local', 'pinned' ];
40
     = [ 'dominantSpeaker', 'id', 'local', 'pinned' ];
41
 
41
 
42
+/**
43
+ * Listen for actions which add, remove, or update the set of participants in
44
+ * the conference.
45
+ *
46
+ * @param {Participant[]} state - List of participants to be modified.
47
+ * @param {Object} action - Action object.
48
+ * @param {string} action.type - Type of action.
49
+ * @param {Participant} action.participant - Information about participant to be
50
+ * added/removed/modified.
51
+ * @returns {Participant[]}
52
+ */
53
+ReducerRegistry.register('features/base/participants', (state = [], action) => {
54
+    switch (action.type) {
55
+    case DOMINANT_SPEAKER_CHANGED:
56
+    case PARTICIPANT_ID_CHANGED:
57
+    case PARTICIPANT_UPDATED:
58
+    case PIN_PARTICIPANT:
59
+        return state.map(p => _participant(p, action));
60
+
61
+    case PARTICIPANT_JOINED:
62
+        return [ ...state, _participantJoined(action) ];
63
+
64
+    case PARTICIPANT_LEFT:
65
+        return state.filter(p => p.id !== action.participant.id);
66
+    }
67
+
68
+    return state;
69
+});
70
+
42
 /**
71
 /**
43
  * Reducer function for a single participant.
72
  * Reducer function for a single participant.
44
  *
73
  *
67
         }
96
         }
68
         break;
97
         break;
69
 
98
 
70
-    case PARTICIPANT_JOINED: {
71
-        const { participant } = action; // eslint-disable-line no-shadow
72
-        const {
73
-            avatarURL,
74
-            connectionStatus,
75
-            dominantSpeaker,
76
-            email,
77
-            isBot,
78
-            local,
79
-            name,
80
-            pinned,
81
-            role
82
-        } = participant;
83
-        let { avatarID, id } = participant;
84
-
85
-        // avatarID
86
-        //
87
-        // TODO Get the avatarID of the local participant from localStorage.
88
-        if (!avatarID && local) {
89
-            avatarID = randomHexString(32);
90
-        }
91
-
92
-        // id
93
-        //
94
-        // XXX The situation of not having an ID for a remote participant should
95
-        // not happen. Maybe we should raise an error in this case or generate a
96
-        // random ID.
97
-        if (!id && local) {
98
-            id = LOCAL_PARTICIPANT_DEFAULT_ID;
99
-        }
100
-
101
-        return {
102
-            avatarID,
103
-            avatarURL,
104
-            connectionStatus,
105
-            dominantSpeaker: dominantSpeaker || false,
106
-            email,
107
-            id,
108
-            isBot,
109
-            local: local || false,
110
-            name,
111
-            pinned: pinned || false,
112
-            role: role || PARTICIPANT_ROLE.NONE
113
-        };
114
-    }
115
-
116
     case PARTICIPANT_UPDATED: {
99
     case PARTICIPANT_UPDATED: {
117
         const { participant } = action; // eslint-disable-line no-shadow
100
         const { participant } = action; // eslint-disable-line no-shadow
118
         let { id } = participant;
101
         let { id } = participant;
147
 }
130
 }
148
 
131
 
149
 /**
132
 /**
150
- * Listen for actions which add, remove, or update the set of participants in
151
- * the conference.
133
+ * Reduces a specific redux action of type {@link PARTICIPANT_JOINED} in the
134
+ * feature base/participants.
152
  *
135
  *
153
- * @param {Participant[]} state - List of participants to be modified.
154
- * @param {Object} action - Action object.
155
- * @param {string} action.type - Type of action.
156
- * @param {Participant} action.participant - Information about participant to be
157
- * added/removed/modified.
158
- * @returns {Participant[]}
136
+ * @param {Action} action - The redux action of type {@code PARTICIPANT_JOINED}
137
+ * to reduce.
138
+ * @private
139
+ * @returns {Object} The new participant derived from the payload of the
140
+ * specified {@code action} to be added into the redux state of the feature
141
+ * base/participants after the reduction of the specified
142
+ * {@code action}.
159
  */
143
  */
160
-ReducerRegistry.register('features/base/participants', (state = [], action) => {
161
-    switch (action.type) {
162
-    case DOMINANT_SPEAKER_CHANGED:
163
-    case PARTICIPANT_ID_CHANGED:
164
-    case PARTICIPANT_UPDATED:
165
-    case PIN_PARTICIPANT:
166
-        return state.map(p => _participant(p, action));
167
-
168
-    case PARTICIPANT_JOINED:
169
-        return [ ...state, _participant(undefined, action) ];
144
+function _participantJoined({ participant }) {
145
+    const {
146
+        avatarURL,
147
+        connectionStatus,
148
+        dominantSpeaker,
149
+        email,
150
+        isBot,
151
+        local,
152
+        name,
153
+        pinned,
154
+        role
155
+    } = participant;
156
+    let { avatarID, conference, id } = participant;
157
+
158
+    if (local) {
159
+        // avatarID
160
+        //
161
+        // TODO Get the avatarID of the local participant from localStorage.
162
+        avatarID || (avatarID = randomHexString(32));
170
 
163
 
171
-    case PARTICIPANT_LEFT:
172
-        return state.filter(p => p.id !== action.participant.id);
164
+        // conference
165
+        //
166
+        // XXX The local participant is not identified in association with a
167
+        // JitsiConference because it is identified by the very fact that it is
168
+        // the local participant.
169
+        conference = undefined;
173
 
170
 
174
-    default:
175
-        return state;
171
+        // id
172
+        id || (id = LOCAL_PARTICIPANT_DEFAULT_ID);
176
     }
173
     }
177
-});
174
+
175
+    return {
176
+        avatarID,
177
+        avatarURL,
178
+        conference,
179
+        connectionStatus,
180
+        dominantSpeaker: dominantSpeaker || false,
181
+        email,
182
+        id,
183
+        isBot,
184
+        local: local || false,
185
+        name,
186
+        pinned: pinned || false,
187
+        role: role || PARTICIPANT_ROLE.NONE
188
+    };
189
+}

正在加载...
取消
保存