|
@@ -1,13 +1,9 @@
|
1
|
1
|
// @flow
|
2
|
2
|
|
3
|
|
-import UIEvents from '../../../../service/UI/UIEvents';
|
4
|
|
-
|
5
|
3
|
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../app';
|
6
|
|
-import {
|
7
|
|
- CONFERENCE_WILL_JOIN,
|
8
|
|
- CONFERENCE_LEFT
|
9
|
|
-} from '../conference';
|
|
4
|
+import { CONFERENCE_LEFT, CONFERENCE_WILL_JOIN } from '../conference';
|
10
|
5
|
import { MiddlewareRegistry } from '../redux';
|
|
6
|
+import UIEvents from '../../../../service/UI/UIEvents';
|
11
|
7
|
import { playSound, registerSound, unregisterSound } from '../sounds';
|
12
|
8
|
|
13
|
9
|
import {
|
|
@@ -43,17 +39,10 @@ declare var APP: Object;
|
43
|
39
|
* Middleware that captures CONFERENCE_JOINED and CONFERENCE_LEFT actions and
|
44
|
40
|
* updates respectively ID of local participant.
|
45
|
41
|
*
|
46
|
|
- * @param {Store} store - Redux store.
|
|
42
|
+ * @param {Store} store - The redux store.
|
47
|
43
|
* @returns {Function}
|
48
|
44
|
*/
|
49
|
45
|
MiddlewareRegistry.register(store => next => action => {
|
50
|
|
- const { conference } = store.getState()['features/base/conference'];
|
51
|
|
-
|
52
|
|
- if (action.type === PARTICIPANT_JOINED
|
53
|
|
- || action.type === PARTICIPANT_LEFT) {
|
54
|
|
- _maybePlaySounds(store, action);
|
55
|
|
- }
|
56
|
|
-
|
57
|
46
|
switch (action.type) {
|
58
|
47
|
case APP_WILL_MOUNT:
|
59
|
48
|
_registerSounds(store);
|
|
@@ -77,29 +66,34 @@ MiddlewareRegistry.register(store => next => action => {
|
77
|
66
|
const participant = getLocalParticipant(store.getState());
|
78
|
67
|
|
79
|
68
|
if (participant) {
|
80
|
|
- const local = participant.id === action.participant.id;
|
|
69
|
+ const { id } = action.participant;
|
81
|
70
|
|
82
|
71
|
store.dispatch(participantUpdated({
|
83
|
|
- id: action.participant.id,
|
84
|
|
- local,
|
|
72
|
+ id,
|
|
73
|
+ local: participant.id === id,
|
85
|
74
|
raisedHand: false
|
86
|
75
|
}));
|
87
|
76
|
}
|
88
|
77
|
|
89
|
|
- if (typeof APP === 'object') {
|
90
|
|
- APP.UI.markDominantSpeaker(action.participant.id);
|
91
|
|
- }
|
|
78
|
+ typeof APP === 'object'
|
|
79
|
+ && APP.UI.markDominantSpeaker(action.participant.id);
|
92
|
80
|
|
93
|
81
|
break;
|
94
|
82
|
}
|
95
|
83
|
|
96
|
|
- case KICK_PARTICIPANT:
|
|
84
|
+ case KICK_PARTICIPANT: {
|
|
85
|
+ const { conference } = store.getState()['features/base/conference'];
|
|
86
|
+
|
97
|
87
|
conference.kickParticipant(action.id);
|
98
|
88
|
break;
|
|
89
|
+ }
|
|
90
|
+
|
|
91
|
+ case MUTE_REMOTE_PARTICIPANT: {
|
|
92
|
+ const { conference } = store.getState()['features/base/conference'];
|
99
|
93
|
|
100
|
|
- case MUTE_REMOTE_PARTICIPANT:
|
101
|
94
|
conference.muteParticipant(action.id);
|
102
|
95
|
break;
|
|
96
|
+ }
|
103
|
97
|
|
104
|
98
|
// TODO Remove this middleware when the local display name update flow is
|
105
|
99
|
// fully brought into redux.
|
|
@@ -116,63 +110,16 @@ MiddlewareRegistry.register(store => next => action => {
|
116
|
110
|
}
|
117
|
111
|
|
118
|
112
|
case PARTICIPANT_JOINED:
|
119
|
|
- case PARTICIPANT_UPDATED: {
|
120
|
|
- const { participant } = action;
|
121
|
|
- const { id, local, raisedHand } = participant;
|
122
|
|
-
|
123
|
|
- // Send an external update of the local participant's raised hand state
|
124
|
|
- // if a new raised hand state is defined in the action.
|
125
|
|
- if (typeof raisedHand !== 'undefined') {
|
126
|
|
- if (local) {
|
127
|
|
- conference.setLocalParticipantProperty(
|
128
|
|
- 'raisedHand',
|
129
|
|
- raisedHand);
|
130
|
|
- }
|
131
|
|
-
|
132
|
|
- if (typeof APP === 'object') {
|
133
|
|
- if (local) {
|
134
|
|
- APP.UI.onLocalRaiseHandChanged(raisedHand);
|
135
|
|
- APP.UI.setLocalRaisedHandStatus(raisedHand);
|
136
|
|
- } else {
|
137
|
|
- const remoteParticipant
|
138
|
|
- = getParticipantById(store.getState(), id);
|
139
|
|
-
|
140
|
|
- remoteParticipant
|
141
|
|
- && APP.UI.setRaisedHandStatus(
|
142
|
|
- remoteParticipant.id,
|
143
|
|
- remoteParticipant.name,
|
144
|
|
- raisedHand);
|
145
|
|
- }
|
146
|
|
- }
|
147
|
|
- }
|
148
|
|
-
|
149
|
|
- // Notify external listeners of potential avatarURL changes.
|
150
|
|
- if (typeof APP === 'object') {
|
151
|
|
- const preUpdateAvatarURL
|
152
|
|
- = getAvatarURLByParticipantId(store.getState(), id);
|
153
|
|
-
|
154
|
|
- // Allow the redux update to go through and compare the old avatar
|
155
|
|
- // to the new avatar and emit out change events if necessary.
|
156
|
|
- const result = next(action);
|
157
|
|
-
|
158
|
|
- const postUpdateAvatarURL
|
159
|
|
- = getAvatarURLByParticipantId(store.getState(), id);
|
160
|
|
-
|
161
|
|
- if (preUpdateAvatarURL !== postUpdateAvatarURL) {
|
162
|
|
- const currentKnownId = local
|
163
|
|
- ? APP.conference.getMyUserId() : id;
|
164
|
|
-
|
165
|
|
- APP.UI.refreshAvatarDisplay(
|
166
|
|
- currentKnownId, postUpdateAvatarURL);
|
167
|
|
- APP.API.notifyAvatarChanged(
|
168
|
|
- currentKnownId, postUpdateAvatarURL);
|
169
|
|
- }
|
|
113
|
+ _maybePlaySounds(store, action);
|
170
|
114
|
|
171
|
|
- return result;
|
172
|
|
- }
|
|
115
|
+ return _participantJoinedOrUpdated(store, next, action);
|
173
|
116
|
|
|
117
|
+ case PARTICIPANT_LEFT:
|
|
118
|
+ _maybePlaySounds(store, action);
|
174
|
119
|
break;
|
175
|
|
- }
|
|
120
|
+
|
|
121
|
+ case PARTICIPANT_UPDATED:
|
|
122
|
+ return _participantJoinedOrUpdated(store, next, action);
|
176
|
123
|
}
|
177
|
124
|
|
178
|
125
|
return next(action);
|
|
@@ -182,7 +129,7 @@ MiddlewareRegistry.register(store => next => action => {
|
182
|
129
|
* Initializes the local participant and signals that it joined.
|
183
|
130
|
*
|
184
|
131
|
* @private
|
185
|
|
- * @param {Store} store - The Redux store.
|
|
132
|
+ * @param {Store} store - The redux store.
|
186
|
133
|
* @param {Dispatch} next - The redux dispatch function to dispatch the
|
187
|
134
|
* specified action to the specified store.
|
188
|
135
|
* @param {Action} action - The redux action which is being dispatched
|
|
@@ -208,8 +155,8 @@ function _localParticipantJoined({ getState, dispatch }, next, action) {
|
208
|
155
|
/**
|
209
|
156
|
* Plays sounds when participants join/leave conference.
|
210
|
157
|
*
|
211
|
|
- * @param {Store} store - The Redux store.
|
212
|
|
- * @param {Action} action - The Redux action. Should be either
|
|
158
|
+ * @param {Store} store - The redux store.
|
|
159
|
+ * @param {Action} action - The redux action. Should be either
|
213
|
160
|
* {@link PARTICIPANT_JOINED} or {@link PARTICIPANT_LEFT}.
|
214
|
161
|
* @private
|
215
|
162
|
* @returns {void}
|
|
@@ -223,8 +170,8 @@ function _maybePlaySounds({ getState, dispatch }, action) {
|
223
|
170
|
// The intention there was to not play user joined notification in big
|
224
|
171
|
// conferences where 100th person is joining.
|
225
|
172
|
if (!action.participant.local
|
226
|
|
- && (!startAudioMuted
|
227
|
|
- || getParticipantCount(state) < startAudioMuted)) {
|
|
173
|
+ && (!startAudioMuted
|
|
174
|
+ || getParticipantCount(state) < startAudioMuted)) {
|
228
|
175
|
if (action.type === PARTICIPANT_JOINED) {
|
229
|
176
|
dispatch(playSound(PARTICIPANT_JOINED_SOUND_ID));
|
230
|
177
|
} else if (action.type === PARTICIPANT_LEFT) {
|
|
@@ -233,30 +180,92 @@ function _maybePlaySounds({ getState, dispatch }, action) {
|
233
|
180
|
}
|
234
|
181
|
}
|
235
|
182
|
|
|
183
|
+/**
|
|
184
|
+ * Notifies the feature base/participants that the action
|
|
185
|
+ * {@code PARTICIPANT_JOINED} or {@code PARTICIPANT_UPDATED} is being dispatched
|
|
186
|
+ * within a specific redux store.
|
|
187
|
+ *
|
|
188
|
+ * @param {Store} store - The redux store in which the specified {@code action}
|
|
189
|
+ * is being dispatched.
|
|
190
|
+ * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
|
|
191
|
+ * specified {@code action} in the specified {@code store}.
|
|
192
|
+ * @param {Action} action - The redux action {@code PARTICIPANT_JOINED} or
|
|
193
|
+ * {@code PARTICIPANT_UPDATED} which is being dispatched in the specified
|
|
194
|
+ * {@code store}.
|
|
195
|
+ * @private
|
|
196
|
+ * @returns {Object} The value returned by {@code next(action)}.
|
|
197
|
+ */
|
|
198
|
+function _participantJoinedOrUpdated({ getState }, next, action) {
|
|
199
|
+ const { participant: { id, local, raisedHand } } = action;
|
|
200
|
+
|
|
201
|
+ // Send an external update of the local participant's raised hand state
|
|
202
|
+ // if a new raised hand state is defined in the action.
|
|
203
|
+ if (typeof raisedHand !== 'undefined') {
|
|
204
|
+ if (local) {
|
|
205
|
+ const { conference } = getState()['features/base/conference'];
|
|
206
|
+
|
|
207
|
+ conference.setLocalParticipantProperty('raisedHand', raisedHand);
|
|
208
|
+ }
|
|
209
|
+
|
|
210
|
+ if (typeof APP === 'object') {
|
|
211
|
+ if (local) {
|
|
212
|
+ APP.UI.onLocalRaiseHandChanged(raisedHand);
|
|
213
|
+ APP.UI.setLocalRaisedHandStatus(raisedHand);
|
|
214
|
+ } else {
|
|
215
|
+ const remoteParticipant = getParticipantById(getState(), id);
|
|
216
|
+
|
|
217
|
+ remoteParticipant
|
|
218
|
+ && APP.UI.setRaisedHandStatus(
|
|
219
|
+ remoteParticipant.id,
|
|
220
|
+ remoteParticipant.name,
|
|
221
|
+ raisedHand);
|
|
222
|
+ }
|
|
223
|
+ }
|
|
224
|
+ }
|
|
225
|
+
|
|
226
|
+ // Notify external listeners of potential avatarURL changes.
|
|
227
|
+ if (typeof APP === 'object') {
|
|
228
|
+ const oldAvatarURL = getAvatarURLByParticipantId(getState(), id);
|
|
229
|
+
|
|
230
|
+ // Allow the redux update to go through and compare the old avatar
|
|
231
|
+ // to the new avatar and emit out change events if necessary.
|
|
232
|
+ const result = next(action);
|
|
233
|
+ const newAvatarURL = getAvatarURLByParticipantId(getState(), id);
|
|
234
|
+
|
|
235
|
+ if (oldAvatarURL !== newAvatarURL) {
|
|
236
|
+ const currentKnownId = local ? APP.conference.getMyUserId() : id;
|
|
237
|
+
|
|
238
|
+ APP.UI.refreshAvatarDisplay(currentKnownId, newAvatarURL);
|
|
239
|
+ APP.API.notifyAvatarChanged(currentKnownId, newAvatarURL);
|
|
240
|
+ }
|
|
241
|
+
|
|
242
|
+ return result;
|
|
243
|
+ }
|
|
244
|
+
|
|
245
|
+ return next(action);
|
|
246
|
+}
|
|
247
|
+
|
236
|
248
|
/**
|
237
|
249
|
* Registers sounds related with the participants feature.
|
238
|
250
|
*
|
239
|
|
- * @param {Store} store - The Redux store.
|
|
251
|
+ * @param {Store} store - The redux store.
|
240
|
252
|
* @private
|
241
|
253
|
* @returns {void}
|
242
|
254
|
*/
|
243
|
255
|
function _registerSounds({ dispatch }) {
|
244
|
256
|
dispatch(
|
245
|
257
|
registerSound(PARTICIPANT_JOINED_SOUND_ID, PARTICIPANT_JOINED_FILE));
|
246
|
|
- dispatch(
|
247
|
|
- registerSound(PARTICIPANT_LEFT_SOUND_ID, PARTICIPANT_LEFT_FILE));
|
|
258
|
+ dispatch(registerSound(PARTICIPANT_LEFT_SOUND_ID, PARTICIPANT_LEFT_FILE));
|
248
|
259
|
}
|
249
|
260
|
|
250
|
261
|
/**
|
251
|
262
|
* Unregisters sounds related with the participants feature.
|
252
|
263
|
*
|
253
|
|
- * @param {Store} store - The Redux store.
|
|
264
|
+ * @param {Store} store - The redux store.
|
254
|
265
|
* @private
|
255
|
266
|
* @returns {void}
|
256
|
267
|
*/
|
257
|
268
|
function _unregisterSounds({ dispatch }) {
|
258
|
|
- dispatch(
|
259
|
|
- unregisterSound(PARTICIPANT_JOINED_SOUND_ID));
|
260
|
|
- dispatch(
|
261
|
|
- unregisterSound(PARTICIPANT_LEFT_SOUND_ID));
|
|
269
|
+ dispatch(unregisterSound(PARTICIPANT_JOINED_SOUND_ID));
|
|
270
|
+ dispatch(unregisterSound(PARTICIPANT_LEFT_SOUND_ID));
|
262
|
271
|
}
|