Browse Source

Flow, coding style

master
Lyubo Marinov 7 years ago
parent
commit
003eb68e28

+ 8
- 6
conference.js View File

@@ -27,11 +27,11 @@ import {
27 27
     conferenceJoined,
28 28
     conferenceLeft,
29 29
     dataChannelOpened,
30
-    toggleAudioOnly,
31 30
     EMAIL_COMMAND,
32 31
     lockStateChanged,
33 32
     p2pStatusChanged,
34
-    setLocalParticipantData
33
+    sendLocalParticipant,
34
+    toggleAudioOnly
35 35
 } from './react/features/base/conference';
36 36
 import { updateDeviceList } from './react/features/base/devices';
37 37
 import {
@@ -1138,13 +1138,15 @@ export default {
1138 1138
         }
1139 1139
     },
1140 1140
 
1141
-    _createRoom (localTracks) {
1142
-        room = connection.initJitsiConference(APP.conference.roomName,
1143
-            this._getConferenceOptions());
1141
+    _createRoom(localTracks) {
1142
+        room
1143
+            = connection.initJitsiConference(
1144
+                APP.conference.roomName,
1145
+                this._getConferenceOptions());
1144 1146
         this._setLocalAudioVideoStreams(localTracks);
1145 1147
         this._room = room; // FIXME do not use this
1146 1148
 
1147
-        setLocalParticipantData(room, APP.store.getState());
1149
+        sendLocalParticipant(APP.store, room);
1148 1150
 
1149 1151
         this._setupListeners();
1150 1152
     },

+ 10
- 10
modules/UI/UI.js View File

@@ -20,12 +20,17 @@ import Filmstrip from "./videolayout/Filmstrip";
20 20
 import SettingsMenu from "./side_pannels/settings/SettingsMenu";
21 21
 import Profile from "./side_pannels/profile/Profile";
22 22
 
23
-import { updateDeviceList } from '../../react/features/base/devices';
24
-import { JitsiTrackErrors } from '../../react/features/base/lib-jitsi-meet';
25 23
 import {
26 24
     openDeviceSelectionDialog
27 25
 } from '../../react/features/device-selection';
26
+import { updateDeviceList } from '../../react/features/base/devices';
27
+import { JitsiTrackErrors } from '../../react/features/base/lib-jitsi-meet';
28
+import { getLocalParticipant } from '../../react/features/base/participants';
28 29
 import { openDisplayNamePrompt } from '../../react/features/display-name';
30
+import {
31
+    maybeShowNotificationWithDoNotDisplay,
32
+    setNotificationsEnabled
33
+} from '../../react/features/notifications';
29 34
 import {
30 35
     checkAutoEnableDesktopSharing,
31 36
     clearButtonPopup,
@@ -37,11 +42,6 @@ import {
37 42
     showSharedVideoButton,
38 43
     showToolbox
39 44
 } from '../../react/features/toolbox';
40
-import {
41
-    maybeShowNotificationWithDoNotDisplay,
42
-    setNotificationsEnabled
43
-} from '../../react/features/notifications';
44
-import { getLocalParticipant } from '../../react/features/base/participants';
45 45
 
46 46
 var EventEmitter = require("events");
47 47
 UI.messageHandler = messageHandler;
@@ -199,8 +199,8 @@ UI.setLocalRaisedHandStatus
199 199
  * Initialize conference UI.
200 200
  */
201 201
 UI.initConference = function () {
202
-    const { id, avatarID, email, name }
203
-        = getLocalParticipant(APP.store.getState());
202
+    const { dispatch, getState } = APP.store;
203
+    const { avatarID, email, id, name } = getLocalParticipant(getState);
204 204
 
205 205
     // Update default button states before showing the toolbar
206 206
     // if local role changes buttons state will be again updated.
@@ -221,7 +221,7 @@ UI.initConference = function () {
221 221
         UI.setUserAvatarID(id, avatarID);
222 222
     }
223 223
 
224
-    APP.store.dispatch(checkAutoEnableDesktopSharing());
224
+    dispatch(checkAutoEnableDesktopSharing());
225 225
 
226 226
     // FollowMe attempts to copy certain aspects of the moderator's UI into the
227 227
     // other participants' UI. Consequently, it needs (1) read and write access

+ 4
- 4
modules/UI/side_pannels/chat/Chat.js View File

@@ -244,10 +244,10 @@ var Chat = {
244 244
 
245 245
                 // if we are in conversation mode focus on the text input
246 246
                 // if we are not, focus on the display name input
247
-                if (APP.conference.getLocalDisplayName())
248
-                    deferredFocus('usermsg');
249
-                else
250
-                    deferredFocus('nickinput');
247
+                deferredFocus(
248
+                    APP.conference.getLocalDisplayName()
249
+                        ? 'usermsg'
250
+                        : 'nickinput');
251 251
             });
252 252
 
253 253
         addSmileys();

+ 2
- 2
react/features/base/conference/actions.js View File

@@ -37,7 +37,7 @@ import {
37 37
 } from './constants';
38 38
 import {
39 39
     _addLocalTracksToConference,
40
-    setLocalParticipantData
40
+    sendLocalParticipant
41 41
 } from './functions';
42 42
 
43 43
 import type { Dispatch } from 'redux';
@@ -288,7 +288,7 @@ export function createConference() {
288 288
 
289 289
         _addConferenceListeners(conference, dispatch);
290 290
 
291
-        setLocalParticipantData(conference, state);
291
+        sendLocalParticipant(state, conference);
292 292
 
293 293
         conference.join(password);
294 294
     };

+ 26
- 14
react/features/base/conference/functions.js View File

@@ -1,11 +1,14 @@
1
+// @flow
2
+
3
+import { JitsiTrackErrors } from '../lib-jitsi-meet';
4
+import { getLocalParticipant } from '../participants';
5
+import { toState } from '../redux';
6
+
1 7
 import {
2 8
     AVATAR_ID_COMMAND,
3 9
     AVATAR_URL_COMMAND,
4 10
     EMAIL_COMMAND
5 11
 } from './constants';
6
-import { JitsiTrackErrors } from '../lib-jitsi-meet';
7
-import { getLocalParticipant } from '../participants';
8
-import { toState } from '../redux';
9 12
 
10 13
 /**
11 14
  * Attach a set of local tracks to a conference.
@@ -15,7 +18,9 @@ import { toState } from '../redux';
15 18
  * @protected
16 19
  * @returns {Promise}
17 20
  */
18
-export function _addLocalTracksToConference(conference, localTracks) {
21
+export function _addLocalTracksToConference(
22
+        conference: { addTrack: Function, getLocalTracks: Function },
23
+        localTracks: Array<Object>) {
19 24
     const conferenceLocalTracks = conference.getLocalTracks();
20 25
     const promises = [];
21 26
 
@@ -45,7 +50,7 @@ export function _addLocalTracksToConference(conference, localTracks) {
45 50
  * {@code getState} function.
46 51
  * @returns {JitsiConference|undefined}
47 52
  */
48
-export function getCurrentConference(stateful) {
53
+export function getCurrentConference(stateful: Function | Object) {
49 54
     const { conference, joining, leaving }
50 55
         = toState(stateful)['features/base/conference'];
51 56
 
@@ -64,7 +69,7 @@ export function getCurrentConference(stateful) {
64 69
  * @protected
65 70
  * @returns {void}
66 71
  */
67
-export function _handleParticipantError(err) {
72
+export function _handleParticipantError(err: { message: ?string }) {
68 73
     // XXX DataChannels are initialized at some later point when the conference
69 74
     // has multiple participants, but code that pins or selects a participant
70 75
     // might be executed before. So here we're swallowing a particular error.
@@ -83,7 +88,7 @@ export function _handleParticipantError(err) {
83 88
  * @returns {boolean} If the specified room name is valid, then true; otherwise,
84 89
  * false.
85 90
  */
86
-export function isRoomValid(room) {
91
+export function isRoomValid(room: ?string) {
87 92
     return typeof room === 'string' && room !== '';
88 93
 }
89 94
 
@@ -95,7 +100,9 @@ export function isRoomValid(room) {
95 100
  * @protected
96 101
  * @returns {Promise}
97 102
  */
98
-export function _removeLocalTracksFromConference(conference, localTracks) {
103
+export function _removeLocalTracksFromConference(
104
+        conference: { removeTrack: Function },
105
+        localTracks: Array<Object>) {
99 106
     return Promise.all(localTracks.map(track =>
100 107
         conference.removeTrack(track)
101 108
             .catch(err => {
@@ -129,15 +136,20 @@ function _reportError(msg, err) {
129 136
 }
130 137
 
131 138
 /**
132
- * Sets the data like avatar URL, email and display name for the local
133
- * participant to the conference.
139
+ * Sends a representation of the local participant such as her avatar (URL),
140
+ * e-mail address, and display name to (the remote participants of) a specific
141
+ * conference.
134 142
  *
135
- * @param {JitsiConference} conference - The JitsiConference instance.
136
- * @param {Object} state - The whole Redux state.
143
+ * @param {Function|Object} stateful - The redux store, state, or
144
+ * {@code getState} function.
145
+ * @param {JitsiConference} conference - The {@code JitsiConference} to which
146
+ * the representation of the local participant is to be sent.
137 147
  * @returns {void}
138 148
  */
139
-export function setLocalParticipantData(conference, state) {
140
-    const { avatarID, avatarURL, email, name } = getLocalParticipant(state);
149
+export function sendLocalParticipant(
150
+        stateful: Function | Object,
151
+        conference: { sendCommand: Function, setDisplayName: Function }) {
152
+    const { avatarID, avatarURL, email, name } = getLocalParticipant(stateful);
141 153
 
142 154
     avatarID && conference.sendCommand(AVATAR_ID_COMMAND, {
143 155
         value: avatarID

+ 7
- 7
react/features/base/jwt/actions.js View File

@@ -1,19 +1,19 @@
1
-/* @flow */
1
+// @flow
2 2
 
3 3
 import { SET_CALL_OVERLAY_VISIBLE, SET_JWT } from './actionTypes';
4 4
 
5 5
 /**
6 6
  * Sets the visibility of {@code CallOverlay}.
7 7
  *
8
- * @param {boolean|undefined} callOverlayVisible - If {@code CallOverlay} is to
9
- * be displayed/visible, then {@code true}; otherwise, {@code false} or
8
+ * @param {boolean|undefined} [callOverlayVisible] - If {@code CallOverlay} is
9
+ * to be displayed/visible, then {@code true}; otherwise, {@code false} or
10 10
  * {@code undefined}.
11 11
  * @returns {{
12 12
  *     type: SET_CALL_OVERLAY_VISIBLE,
13 13
  *     callOverlayVisible: (boolean|undefined)
14 14
  * }}
15 15
  */
16
-export function setCallOverlayVisible(callOverlayVisible: boolean) {
16
+export function setCallOverlayVisible(callOverlayVisible: ?boolean) {
17 17
     return (dispatch: Dispatch<*>, getState: Function) => {
18 18
         getState()['features/base/jwt']
19 19
             .callOverlayVisible === callOverlayVisible
@@ -27,13 +27,13 @@ export function setCallOverlayVisible(callOverlayVisible: boolean) {
27 27
 /**
28 28
  * Stores a specific JSON Web Token (JWT) into the redux store.
29 29
  *
30
- * @param {string} jwt - The JSON Web Token (JWT) to store.
30
+ * @param {string} [jwt] - The JSON Web Token (JWT) to store.
31 31
  * @returns {{
32 32
  *     type: SET_TOKEN_DATA,
33
- *     jwt: string
33
+ *     jwt: (string|undefined)
34 34
  * }}
35 35
  */
36
-export function setJWT(jwt: string) {
36
+export function setJWT(jwt: ?string) {
37 37
     return {
38 38
         type: SET_JWT,
39 39
         jwt

+ 116
- 108
react/features/base/jwt/middleware.js View File

@@ -1,3 +1,5 @@
1
+// @flow
2
+
1 3
 import jwtDecode from 'jwt-decode';
2 4
 
3 5
 import {
@@ -22,6 +24,8 @@ import { setCallOverlayVisible, setJWT } from './actions';
22 24
 import { SET_JWT } from './actionTypes';
23 25
 import { parseJWTFromURLParams } from './functions';
24 26
 
27
+declare var APP: Object;
28
+
25 29
 /**
26 30
  * Middleware to parse token data upon setting a new room URL.
27 31
  *
@@ -80,8 +84,8 @@ function _maybeSetCallOverlayVisible({ dispatch, getState }, next, action) {
80 84
     if (stateFeaturesJWT.callee) {
81 85
         const { conference, leaving, room } = state['features/base/conference'];
82 86
 
83
-        // XXX The CallOverlay is to be displayed/visible as soon as
84
-        // possible including even before the conference is joined.
87
+        // XXX The CallOverlay is to be displayed/visible as soon as possible
88
+        // including even before the conference is joined.
85 89
         if (room && (!conference || conference !== leaving)) {
86 90
             switch (action.type) {
87 91
             case CONFERENCE_FAILED:
@@ -100,10 +104,11 @@ function _maybeSetCallOverlayVisible({ dispatch, getState }, next, action) {
100 104
                 break;
101 105
 
102 106
             default: {
103
-                // The CallOverlay it to no longer be displayed/visible as soon
107
+                // The CallOverlay is to no longer be displayed/visible as soon
104 108
                 // as another participant joins.
105
-                callOverlayVisible = getParticipantCount(state) === 1
106
-                    && Boolean(getLocalParticipant(state));
109
+                callOverlayVisible
110
+                    = getParticipantCount(state) === 1
111
+                        && Boolean(getLocalParticipant(state));
107 112
 
108 113
                 // However, the CallDialog is not to be displayed/visible again
109 114
                 // after all remote participants leave.
@@ -122,53 +127,24 @@ function _maybeSetCallOverlayVisible({ dispatch, getState }, next, action) {
122 127
 }
123 128
 
124 129
 /**
125
- * Converts 'context.user' JWT token structure to the format compatible with the
126
- * corresponding fields overridden in base/participants.
127
- *
128
- * @param {Object} user - The 'jwt.context.user' structure parsed from the JWT
129
- * token.
130
- * @returns {({
131
- *      avatarURL: string?,
132
- *      email: string?,
133
- *      name: string?
134
- * })}
135
- * @private
136
- */
137
-function _normalizeCallerFields(user) {
138
-    const { avatar, avatarUrl, email, name } = user;
139
-    const caller = { };
140
-
141
-    if (typeof (avatarUrl || avatar) === 'string') {
142
-        caller.avatarURL = (avatarUrl || avatar).trim();
143
-    }
144
-    if (typeof email === 'string') {
145
-        caller.email = email.trim();
146
-    }
147
-    if (typeof name === 'string') {
148
-        caller.name = name.trim();
149
-    }
150
-
151
-    return Object.keys(caller).length ? caller : undefined;
152
-}
153
-
154
-/**
155
- * Eventually overwrites 'avatarURL', 'email' and 'name' fields with the values
156
- * from JWT token for the local participant stored in the 'base/participants'
157
- * Redux store by dispatching the participant updated action.
130
+ * Overwrites the properties {@code avatarURL}, {@code email}, and {@code name}
131
+ * of the local participant stored in the redux state base/participants.
158 132
  *
159 133
  * @param {Store} store - The redux store.
160
- * @param {Object} caller - The "caller" structure parsed from 'context.user'
161
- * part of the JWT token and then normalized using
162
- * {@link _normalizeCallerFields}.
163
- * @returns {void}
134
+ * @param {Object} localParticipant - The {@code Participant} structure to
135
+ * overwrite the local participant stored in the redux store base/participants
136
+ * with.
164 137
  * @private
138
+ * @returns {void}
165 139
  */
166
-function _overwriteLocalParticipant({ dispatch, getState }, caller) {
167
-    const { avatarURL, email, name } = caller;
168
-    const localParticipant = getLocalParticipant(getState());
140
+function _overwriteLocalParticipant(
141
+        { dispatch, getState },
142
+        { avatarURL, email, name }) {
143
+    let localParticipant;
169 144
 
170
-    if (localParticipant && (avatarURL || email || name)) {
171
-        const newProperties = { id: localParticipant.id };
145
+    if ((avatarURL || email || name)
146
+            && (localParticipant = getLocalParticipant(getState))) {
147
+        const newProperties: Object = { id: localParticipant.id };
172 148
 
173 149
         if (avatarURL) {
174 150
             newProperties.avatarURL = avatarURL;
@@ -183,41 +159,6 @@ function _overwriteLocalParticipant({ dispatch, getState }, caller) {
183 159
     }
184 160
 }
185 161
 
186
-/**
187
- * Will reset the values overridden by {@link _overwriteLocalParticipant}
188
- * by either clearing them or setting to default values. Only the values that
189
- * have not changed since the override happened will be restored.
190
- *
191
- * NOTE Once there is the possibility to edit and save participant properties,
192
- * this method should restore values from the storage instead.
193
- *
194
- * @param {Store} store - The Redux store.
195
- * @param {Object} caller - The 'caller' part of the JWT Redux state which tells
196
- * which local participant's fields's been overridden when the JWT token was
197
- * set.
198
- * @returns {void}
199
- * @private
200
- */
201
-function _resetLocalParticipantOverrides({ dispatch, getState }, caller) {
202
-    const { avatarURL, name, email } = caller;
203
-    const localParticipant = getLocalParticipant(getState());
204
-
205
-    if (localParticipant && (avatarURL || name || email)) {
206
-        const newProperties = { id: localParticipant.id };
207
-
208
-        if (avatarURL === localParticipant.avatarURL) {
209
-            newProperties.avatarURL = undefined;
210
-        }
211
-        if (name === localParticipant.name) {
212
-            newProperties.name = LOCAL_PARTICIPANT_DEFAULT_NAME;
213
-        }
214
-        if (email === localParticipant.email) {
215
-            newProperties.email = undefined;
216
-        }
217
-        dispatch(participantUpdated(newProperties));
218
-    }
219
-}
220
-
221 162
 /**
222 163
  * Notifies the feature jwt that the action {@link SET_CONFIG} or
223 164
  * {@link SET_LOCATION_URL} is being dispatched within a specific redux
@@ -266,41 +207,108 @@ function _setJWT(store, next, action) {
266 207
     // eslint-disable-next-line no-unused-vars
267 208
     const { jwt, type, ...actionPayload } = action;
268 209
 
269
-    if (jwt && !Object.keys(actionPayload).length) {
270
-        const {
271
-            enableUserRolesBasedOnToken
272
-        } = store.getState()['features/base/config'];
210
+    if (!Object.keys(actionPayload).length) {
211
+        if (jwt) {
212
+            const {
213
+                enableUserRolesBasedOnToken
214
+            } = store.getState()['features/base/config'];
215
+
216
+            action.isGuest = !enableUserRolesBasedOnToken;
273 217
 
274
-        action.isGuest = !enableUserRolesBasedOnToken;
218
+            const jwtPayload = jwtDecode(jwt);
275 219
 
276
-        const jwtPayload = jwtDecode(jwt);
220
+            if (jwtPayload) {
221
+                const { context, iss } = jwtPayload;
277 222
 
278
-        if (jwtPayload) {
279
-            const { context, iss } = jwtPayload;
223
+                action.jwt = jwt;
224
+                action.issuer = iss;
225
+                if (context) {
226
+                    const user = _user2participant(context.user);
280 227
 
281
-            action.jwt = jwt;
282
-            action.issuer = iss;
283
-            if (context) {
284
-                action.callee = context.callee;
285
-                action.caller = _normalizeCallerFields(context.user);
286
-                action.group = context.group;
287
-                action.server = context.server;
228
+                    action.callee = context.callee;
229
+                    action.group = context.group;
230
+                    action.server = context.server;
231
+                    action.user = user;
288 232
 
289
-                if (action.caller) {
290
-                    _overwriteLocalParticipant(store, action.caller);
233
+                    user && _overwriteLocalParticipant(store, user);
291 234
                 }
292 235
             }
293
-        }
294
-    } else if (!jwt && !Object.keys(actionPayload).length) {
295
-        const jwtState = store.getState()['features/base/jwt'];
296
-
297
-        // The logic of restoring JWT overrides make sense only on mobile. On
298
-        // web it should eventually be restored from storage, but there's no
299
-        // such use case yet.
300
-        if (jwtState.caller && typeof APP === 'undefined') {
301
-            _resetLocalParticipantOverrides(store, jwtState.caller);
236
+        } else if (typeof APP === 'undefined') {
237
+            // The logic of restoring JWT overrides make sense only on mobile.
238
+            // On Web it should eventually be restored from storage, but there's
239
+            // no such use case yet.
240
+
241
+            const { user } = store.getState()['features/base/jwt'];
242
+
243
+            user && _undoOverwriteLocalParticipant(store, user);
302 244
         }
303 245
     }
304 246
 
305 247
     return _maybeSetCallOverlayVisible(store, next, action);
306 248
 }
249
+
250
+/**
251
+ * Undoes/resets the values overwritten by {@link _overwriteLocalParticipant}
252
+ * by either clearing them or setting to default values. Only the values that
253
+ * have not changed since the overwrite happened will be restored.
254
+ *
255
+ * NOTE Once it is possible to edit and save participant properties, this
256
+ * function should restore values from the storage instead.
257
+ *
258
+ * @param {Store} store - The redux store.
259
+ * @param {Object} localParticipant - The {@code Participant} structure used
260
+ * previously to {@link _overwriteLocalParticipant}.
261
+ * @private
262
+ * @returns {void}
263
+ */
264
+function _undoOverwriteLocalParticipant(
265
+        { dispatch, getState },
266
+        { avatarURL, name, email }) {
267
+    let localParticipant;
268
+
269
+    if ((avatarURL || name || email)
270
+            && (localParticipant = getLocalParticipant(getState))) {
271
+        const newProperties: Object = { id: localParticipant.id };
272
+
273
+        if (avatarURL === localParticipant.avatarURL) {
274
+            newProperties.avatarURL = undefined;
275
+        }
276
+        if (email === localParticipant.email) {
277
+            newProperties.email = undefined;
278
+        }
279
+        if (name === localParticipant.name) {
280
+            newProperties.name = LOCAL_PARTICIPANT_DEFAULT_NAME;
281
+        }
282
+        dispatch(participantUpdated(newProperties));
283
+    }
284
+}
285
+
286
+/**
287
+ * Converts the JWT {@code context.user} structure to the {@code Participant}
288
+ * structure stored in the redux state base/participants.
289
+ *
290
+ * @param {Object} user - The JWT {@code context.user} structure to convert.
291
+ * @private
292
+ * @returns {{
293
+ *     avatarURL: ?string,
294
+ *     email: ?string,
295
+ *     name: ?string
296
+ * }}
297
+ */
298
+function _user2participant({ avatar, avatarUrl, email, name }) {
299
+    const participant = {};
300
+
301
+    if (typeof avatarUrl === 'string') {
302
+        participant.avatarURL = avatarUrl.trim();
303
+    } else if (typeof avatar === 'string') {
304
+        participant.avatarURL = avatar.trim();
305
+    }
306
+    if (typeof email === 'string') {
307
+        participant.email = email.trim();
308
+    }
309
+    if (typeof name === 'string') {
310
+        participant.name = name.trim();
311
+    }
312
+
313
+    return Object.keys(participant).length ? participant : undefined;
314
+}

+ 6
- 4
react/features/base/participants/constants.js View File

@@ -14,16 +14,18 @@
14 14
 export const DEFAULT_AVATAR_RELATIVE_PATH = 'images/avatar.png';
15 15
 
16 16
 /**
17
- * Local participant might not have real ID until he joins a conference,
18
- * so use 'local' as its default ID.
17
+ * The local participant might not have real ID until she joins a conference,
18
+ * so use 'local' as her default ID.
19 19
  *
20 20
  * @type {string}
21 21
  */
22 22
 export const LOCAL_PARTICIPANT_DEFAULT_ID = 'local';
23 23
 
24 24
 /**
25
- * The default display name for the local participant.
26
- * TODO Get the from config and/or localized.
25
+ * The default display name of the local participant.
26
+ *
27
+ * TODO Get the display name from config and/or localized.
28
+ *
27 29
  * @type {string}
28 30
  */
29 31
 export const LOCAL_PARTICIPANT_DEFAULT_NAME = 'me';

+ 33
- 33
react/features/base/participants/functions.js View File

@@ -1,4 +1,4 @@
1
-/* @flow */
1
+// @flow
2 2
 
3 3
 import { toState } from '../redux';
4 4
 
@@ -77,14 +77,14 @@ export function getAvatarURL({ avatarID, avatarURL, email, id }: {
77 77
 /**
78 78
  * Returns local participant from Redux state.
79 79
  *
80
- * @param {(Function|Object|Participant[])} stateOrGetState - The redux state
80
+ * @param {(Function|Object|Participant[])} stateful - The redux state
81 81
  * features/base/participants, the (whole) redux state, or redux's
82
- * {@code getState} function to be used to retrieve the
83
- * features/base/participants state.
82
+ * {@code getState} function to be used to retrieve the state
83
+ * features/base/participants.
84 84
  * @returns {(Participant|undefined)}
85 85
  */
86
-export function getLocalParticipant(stateOrGetState: Object | Function) {
87
-    const participants = _getAllParticipants(stateOrGetState);
86
+export function getLocalParticipant(stateful: Object | Function) {
87
+    const participants = _getAllParticipants(stateful);
88 88
 
89 89
     return participants.find(p => p.local);
90 90
 }
@@ -92,18 +92,18 @@ export function getLocalParticipant(stateOrGetState: Object | Function) {
92 92
 /**
93 93
  * Returns participant by ID from Redux state.
94 94
  *
95
- * @param {(Function|Object|Participant[])} stateOrGetState - The redux state
95
+ * @param {(Function|Object|Participant[])} stateful - The redux state
96 96
  * features/base/participants, the (whole) redux state, or redux's
97
- * {@code getState} function to be used to retrieve the
98
- * features/base/participants state.
97
+ * {@code getState} function to be used to retrieve the state
98
+ * features/base/participants.
99 99
  * @param {string} id - The ID of the participant to retrieve.
100 100
  * @private
101 101
  * @returns {(Participant|undefined)}
102 102
  */
103 103
 export function getParticipantById(
104
-        stateOrGetState: Object | Function,
104
+        stateful: Object | Function,
105 105
         id: string) {
106
-    const participants = _getAllParticipants(stateOrGetState);
106
+    const participants = _getAllParticipants(stateful);
107 107
 
108 108
     return participants.find(p => p.id === id);
109 109
 }
@@ -112,14 +112,14 @@ export function getParticipantById(
112 112
  * Returns a count of the known participants in the passed in redux state,
113 113
  * excluding any fake participants.
114 114
  *
115
- * @param {(Function|Object|Participant[])} stateOrGetState - The redux state
115
+ * @param {(Function|Object|Participant[])} stateful - The redux state
116 116
  * features/base/participants, the (whole) redux state, or redux's
117
- * {@code getState} function to be used to retrieve the
118
- * features/base/participants state.
117
+ * {@code getState} function to be used to retrieve the state
118
+ * features/base/participants.
119 119
  * @returns {number}
120 120
  */
121
-export function getParticipantCount(stateOrGetState: Object | Function) {
122
-    return getParticipants(stateOrGetState).length;
121
+export function getParticipantCount(stateful: Object | Function) {
122
+    return getParticipants(stateful).length;
123 123
 }
124 124
 
125 125
 
@@ -127,42 +127,42 @@ export function getParticipantCount(stateOrGetState: Object | Function) {
127 127
  * Selectors for getting all known participants with fake participants filtered
128 128
  * out.
129 129
  *
130
- * @param {(Function|Object|Participant[])} stateOrGetState - The redux state
130
+ * @param {(Function|Object|Participant[])} stateful - The redux state
131 131
  * features/base/participants, the (whole) redux state, or redux's
132
- * {@code getState} function to be used to retrieve the
133
- * features/base/participants state.
132
+ * {@code getState} function to be used to retrieve the state
133
+ * features/base/participants.
134 134
  * @returns {Participant[]}
135 135
  */
136
-export function getParticipants(stateOrGetState: Object | Function) {
137
-    return _getAllParticipants(stateOrGetState).filter(p => !p.isBot);
136
+export function getParticipants(stateful: Object | Function) {
137
+    return _getAllParticipants(stateful).filter(p => !p.isBot);
138 138
 }
139 139
 
140 140
 /**
141 141
  * Returns the participant which has its pinned state set to truthy.
142 142
  *
143
- * @param {(Function|Object|Participant[])} stateOrGetState - The redux state
143
+ * @param {(Function|Object|Participant[])} stateful - The redux state
144 144
  * features/base/participants, the (whole) redux state, or redux's
145
- * {@code getState} function to be used to retrieve the
146
- * features/base/participants state.
145
+ * {@code getState} function to be used to retrieve the state
146
+ * features/base/participants.
147 147
  * @returns {(Participant|undefined)}
148 148
  */
149
-export function getPinnedParticipant(stateOrGetState: Object | Function) {
150
-    return _getAllParticipants(stateOrGetState).find(p => p.pinned);
149
+export function getPinnedParticipant(stateful: Object | Function) {
150
+    return _getAllParticipants(stateful).find(p => p.pinned);
151 151
 }
152 152
 
153 153
 /**
154 154
  * Returns array of participants from Redux state.
155 155
  *
156
- * @param {(Function|Object|Participant[])} stateOrGetState - The redux state
156
+ * @param {(Function|Object|Participant[])} stateful - The redux state
157 157
  * features/base/participants, the (whole) redux state, or redux's
158
- * {@code getState} function to be used to retrieve the
159
- * features/base/participants state.
158
+ * {@code getState} function to be used to retrieve the state
159
+ * features/base/participants.
160 160
  * @private
161 161
  * @returns {Participant[]}
162 162
  */
163
-function _getAllParticipants(stateOrGetState) {
163
+function _getAllParticipants(stateful) {
164 164
     return (
165
-        Array.isArray(stateOrGetState)
166
-            ? stateOrGetState
167
-            : toState(stateOrGetState)['features/base/participants'] || []);
165
+        Array.isArray(stateful)
166
+            ? stateful
167
+            : toState(stateful)['features/base/participants'] || []);
168 168
 }

+ 15
- 11
react/features/base/participants/reducer.js View File

@@ -1,3 +1,5 @@
1
+// @flow
2
+
1 3
 import { ReducerRegistry, set } from '../redux';
2 4
 import { randomHexString } from '../util';
3 5
 
@@ -31,6 +33,8 @@ import {
31 33
  * @property {string} email - Participant email.
32 34
  */
33 35
 
36
+declare var APP: Object;
37
+
34 38
 /**
35 39
  * These properties should not be bulk assigned when updating a particular
36 40
  * @see Participant.
@@ -49,9 +53,9 @@ const PARTICIPANT_PROPS_TO_OMIT_WHEN_UPDATE
49 53
  * added/modified.
50 54
  * @param {JitsiConference} action.conference - Conference instance.
51 55
  * @private
52
- * @returns {Participant|undefined}
56
+ * @returns {Participant}
53 57
  */
54
-function _participant(state, action) {
58
+function _participant(state: Object = {}, action) {
55 59
     switch (action.type) {
56 60
     case DOMINANT_SPEAKER_CHANGED:
57 61
         // Only one dominant speaker is allowed.
@@ -99,9 +103,9 @@ function _participant(state, action) {
99 103
 
100 104
         // name
101 105
         if (!name) {
102
-            // TODO Get the from config and/or localized.
103
-            // On web default value is handled in:
104
-            // conference.js getParticipantDisplayName
106
+            // TODO Get the display name from config and/or localized.
107
+            // XXX On Web the default value is handled in conference.js by
108
+            // getParticipantDisplayName.
105 109
             if (typeof APP === 'undefined') {
106 110
                 name
107 111
                     = local ? LOCAL_PARTICIPANT_DEFAULT_NAME : 'Fellow Jitster';
@@ -169,18 +173,18 @@ function _participant(state, action) {
169 173
  */
170 174
 ReducerRegistry.register('features/base/participants', (state = [], action) => {
171 175
     switch (action.type) {
172
-    case PARTICIPANT_JOINED:
173
-        return [ ...state, _participant(undefined, action) ];
174
-
175
-    case PARTICIPANT_LEFT:
176
-        return state.filter(p => p.id !== action.participant.id);
177
-
178 176
     case DOMINANT_SPEAKER_CHANGED:
179 177
     case PARTICIPANT_ID_CHANGED:
180 178
     case PARTICIPANT_UPDATED:
181 179
     case PIN_PARTICIPANT:
182 180
         return state.map(p => _participant(p, action));
183 181
 
182
+    case PARTICIPANT_JOINED:
183
+        return [ ...state, _participant(undefined, action) ];
184
+
185
+    case PARTICIPANT_LEFT:
186
+        return state.filter(p => p.id !== action.participant.id);
187
+
184 188
     default:
185 189
         return state;
186 190
     }

+ 5
- 3
react/features/conference/route.js View File

@@ -1,4 +1,4 @@
1
-/* global APP, config */
1
+// @flow
2 2
 
3 3
 import ConferenceUrl from '../../../modules/URL/ConferenceUrl';
4 4
 
@@ -7,6 +7,9 @@ import { RouteRegistry } from '../base/react';
7 7
 
8 8
 import { Conference } from './components';
9 9
 
10
+declare var APP: Object;
11
+declare var config: Object;
12
+
10 13
 const logger = require('jitsi-meet-logger').getLogger(__filename);
11 14
 
12 15
 /**
@@ -29,7 +32,6 @@ RouteRegistry.register({
29 32
  * @returns {void}
30 33
  */
31 34
 function _initConference() {
32
-    // Initialize the conference URL handler
33 35
     APP.ConferenceUrl = new ConferenceUrl(window.location);
34 36
 }
35 37
 
@@ -43,7 +45,7 @@ function _initConference() {
43 45
  * @private
44 46
  * @returns {Promise}
45 47
  */
46
-function _obtainConfig(location, room) {
48
+function _obtainConfig(location: string, room: string) {
47 49
     return new Promise((resolve, reject) =>
48 50
         obtainConfig(location, room, (success, error) => {
49 51
             success ? resolve() : reject(error);

+ 8
- 8
react/features/feedback/actions.js View File

@@ -1,6 +1,6 @@
1 1
 // @flow
2 2
 
3
-import { openDialog } from '../../features/base/dialog';
3
+import { openDialog } from '../base/dialog';
4 4
 import { FEEDBACK_REQUEST_IN_PROGRESS } from '../../../modules/UI/UIErrors';
5 5
 
6 6
 import { CANCEL_FEEDBACK, SUBMIT_FEEDBACK } from './actionTypes';
@@ -55,8 +55,8 @@ export function maybeOpenFeedbackDialog(conference: Object) {
55 55
             // Feedback has been submitted already.
56 56
 
57 57
             return Promise.resolve({
58
-                thankYouDialogVisible: true,
59
-                feedbackSubmitted: true
58
+                feedbackSubmitted: true,
59
+                thankYouDialogVisible: true
60 60
             });
61 61
         } else if (conference.isCallstatsEnabled()) {
62 62
             return new Promise(resolve => {
@@ -71,12 +71,12 @@ export function maybeOpenFeedbackDialog(conference: Object) {
71 71
             });
72 72
         }
73 73
 
74
-        // If the feedback functionality isn't enabled we show a thank
75
-        // you dialog. Signaling it (true), so the caller
76
-        // of requestFeedback can act on it
74
+        // If the feedback functionality isn't enabled we show a "thank you"
75
+        // dialog. Signaling it (true), so the caller of requestFeedback can act
76
+        // on it.
77 77
         return Promise.resolve({
78
-            thankYouDialogVisible: true,
79
-            feedbackSubmitted: false
78
+            feedbackSubmitted: false,
79
+            thankYouDialogVisible: true
80 80
         });
81 81
     };
82 82
 }

+ 22
- 23
react/features/filmstrip/functions.js View File

@@ -1,37 +1,36 @@
1
-/* @flow */
1
+// @flow
2 2
 
3
-declare var interfaceConfig: Object;
3
+import { getPinnedParticipant } from '../base/participants';
4 4
 
5
-import {
6
-    getPinnedParticipant
7
-} from '../base/participants';
5
+declare var interfaceConfig: Object;
8 6
 
9 7
 /**
10
- * A selector for determining whether or not remote video thumbnails should be
11
- * displayed in the filmstrip.
8
+ * Determines whether the remote video thumbnails should be displayed/visible in
9
+ * the filmstrip.
12 10
  *
13 11
  * @param {Object} state - The full redux state.
14
- * @returns {boolean} - True if remote video thumbnails should be displayed.
12
+ * @returns {boolean} - If remote video thumbnails should be displayed/visible
13
+ * in the filmstrip, then {@code true}; otherwise, {@code false}.
15 14
  */
16 15
 export function shouldRemoteVideosBeVisible(state: Object) {
17 16
     const participants = state['features/base/participants'];
18
-    const participantsCount = participants.length;
19
-    const pinnedParticipant = getPinnedParticipant(state);
20
-
21
-    const shouldShowVideos
22
-        = participantsCount > 2
17
+    const participantCount = participants.length;
18
+    let pinnedParticipant;
23 19
 
24
-        // Always show the filmstrip when there is another participant to show
25
-        // and the filmstrip is hovered, or local video is pinned, or the
26
-        // toolbar is displayed.
27
-        || (participantsCount > 1
28
-            && (state['features/filmstrip'].hovered
29
-                || state['features/toolbox'].visible
30
-                || (pinnedParticipant && pinnedParticipant.local)))
20
+    return Boolean(
21
+        participantCount > 2
31 22
 
32
-        || interfaceConfig.filmStripOnly
23
+            // Always show the filmstrip when there is another participant to
24
+            // show and the filmstrip is hovered, or local video is pinned, or
25
+            // the toolbar is displayed.
26
+            || (participantCount > 1
27
+                && (state['features/filmstrip'].hovered
28
+                    || state['features/toolbox'].visible
29
+                    || ((pinnedParticipant = getPinnedParticipant(participants))
30
+                        && pinnedParticipant.local)))
33 31
 
34
-        || state['features/base/config'].disable1On1Mode;
32
+            || (typeof interfaceConfig === 'object'
33
+                && interfaceConfig.filmStripOnly)
35 34
 
36
-    return Boolean(shouldShowVideos);
35
+            || state['features/base/config'].disable1On1Mode);
37 36
 }

+ 35
- 26
react/features/speaker-stats/components/SpeakerStats.js View File

@@ -1,4 +1,4 @@
1
-/* global interfaceConfig */
1
+// @flow
2 2
 
3 3
 import PropTypes from 'prop-types';
4 4
 import React, { Component } from 'react';
@@ -10,6 +10,8 @@ import { getLocalParticipant } from '../../base/participants';
10 10
 import SpeakerStatsItem from './SpeakerStatsItem';
11 11
 import SpeakerStatsLabels from './SpeakerStatsLabels';
12 12
 
13
+declare var interfaceConfig: Object;
14
+
13 15
 /**
14 16
  * React component for displaying a list of speaker stats.
15 17
  *
@@ -23,7 +25,7 @@ class SpeakerStats extends Component {
23 25
      */
24 26
     static propTypes = {
25 27
         /**
26
-         * The display name for the local participant obtained from the Redux
28
+         * The display name for the local participant obtained from the redux
27 29
          * store.
28 30
          */
29 31
         _localDisplayName: PropTypes.string,
@@ -39,6 +41,12 @@ class SpeakerStats extends Component {
39 41
         t: PropTypes.func
40 42
     };
41 43
 
44
+    state = {
45
+        stats: {}
46
+    };
47
+
48
+    _updateInterval: number;
49
+
42 50
     /**
43 51
      * Initializes a new SpeakerStats instance.
44 52
      *
@@ -48,10 +56,7 @@ class SpeakerStats extends Component {
48 56
     constructor(props) {
49 57
         super(props);
50 58
 
51
-        this.state = {
52
-            stats: {}
53
-        };
54
-        this._updateInterval = null;
59
+        // Bind event handlers so they are only bound once per instance.
55 60
         this._updateStats = this._updateStats.bind(this);
56 61
     }
57 62
 
@@ -100,18 +105,6 @@ class SpeakerStats extends Component {
100 105
         );
101 106
     }
102 107
 
103
-    /**
104
-     * Update the internal state with the latest speaker stats.
105
-     *
106
-     * @returns {void}
107
-     * @private
108
-     */
109
-    _updateStats() {
110
-        const stats = this.props.conference.getSpeakerStats();
111
-
112
-        this.setState({ stats });
113
-    }
114
-
115 108
     /**
116 109
      * Create a SpeakerStatsItem instance for the passed in user id.
117 110
      *
@@ -131,18 +124,19 @@ class SpeakerStats extends Component {
131 124
         const dominantSpeakerTime = statsModel.getTotalDominantSpeakerTime();
132 125
         const hasLeft = statsModel.hasLeft();
133 126
 
134
-        let displayName = '';
127
+        let displayName;
135 128
 
136 129
         if (statsModel.isLocalStats()) {
137 130
             const { t } = this.props;
138 131
             const meString = t('me');
139 132
 
140 133
             displayName = this.props._localDisplayName;
141
-            displayName = displayName ? `${displayName} (${meString})`
142
-                : meString;
134
+            displayName
135
+                = displayName ? `${displayName} (${meString})` : meString;
143 136
         } else {
144
-            displayName = this.state.stats[userId].getDisplayName()
145
-                || interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME;
137
+            displayName
138
+                = this.state.stats[userId].getDisplayName()
139
+                    || interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME;
146 140
         }
147 141
 
148 142
         return (
@@ -154,15 +148,29 @@ class SpeakerStats extends Component {
154 148
                 key = { userId } />
155 149
         );
156 150
     }
151
+
152
+    _updateStats: () => void;
153
+
154
+    /**
155
+     * Update the internal state with the latest speaker stats.
156
+     *
157
+     * @returns {void}
158
+     * @private
159
+     */
160
+    _updateStats() {
161
+        const stats = this.props.conference.getSpeakerStats();
162
+
163
+        this.setState({ stats });
164
+    }
157 165
 }
158 166
 
159 167
 /**
160
- * Maps (parts of) the Redux state to the associated SpeakerStats's props.
168
+ * Maps (parts of) the redux state to the associated SpeakerStats's props.
161 169
  *
162
- * @param {Object} state - The Redux state.
170
+ * @param {Object} state - The redux state.
163 171
  * @private
164 172
  * @returns {{
165
- *     _localDisplayName: string?
173
+ *     _localDisplayName: ?string
166 174
  * }}
167 175
  */
168 176
 function _mapStateToProps(state) {
@@ -171,6 +179,7 @@ function _mapStateToProps(state) {
171 179
     return {
172 180
         /**
173 181
          * The local display name.
182
+         *
174 183
          * @private
175 184
          * @type {string|undefined}
176 185
          */

+ 1
- 1
react/features/welcome/components/WelcomePage.web.js View File

@@ -31,7 +31,7 @@ class WelcomePage extends AbstractWelcomePage {
31 31
                 interfaceConfig.GENERATE_ROOMNAMES_ON_WELCOME_PAGE
32 32
         };
33 33
 
34
-        // Bind event handlers so they are only bound once for every instance.
34
+        // Bind event handlers so they are only bound once per instance.
35 35
         this._onDisableWelcomeChange = this._onDisableWelcomeChange.bind(this);
36 36
         this._onKeyDown = this._onKeyDown.bind(this);
37 37
         this._onRoomChange = this._onRoomChange.bind(this);

Loading…
Cancel
Save