Browse Source

Merge pull request #1440 from jitsi/iframe_api_race_condition

Fix executeCommand race condition
master
Saúl Ibarra Corretgé 8 years ago
parent
commit
a10f040df6

+ 55
- 29
conference.js View File

32
     isFatalJitsiConnectionError
32
     isFatalJitsiConnectionError
33
 } from './react/features/base/lib-jitsi-meet';
33
 } from './react/features/base/lib-jitsi-meet';
34
 import {
34
 import {
35
-    changeParticipantAvatarID,
36
-    changeParticipantAvatarURL,
37
-    changeParticipantEmail,
38
     participantJoined,
35
     participantJoined,
39
     participantLeft,
36
     participantLeft,
40
-    participantRoleChanged
37
+    participantRoleChanged,
38
+    participantUpdated
41
 } from './react/features/base/participants';
39
 } from './react/features/base/participants';
42
 import {
40
 import {
43
     showDesktopPicker
41
     showDesktopPicker
174
  * @param {string} value new value
172
  * @param {string} value new value
175
  */
173
  */
176
 function sendData (command, value) {
174
 function sendData (command, value) {
175
+    if(!room) {
176
+        return;
177
+    }
178
+
177
     room.removeCommand(command);
179
     room.removeCommand(command);
178
     room.sendCommand(command, {value: value});
180
     room.sendCommand(command, {value: value});
179
 }
181
 }
361
         });
363
         });
362
 }
364
 }
363
 
365
 
364
-/**
365
- * Changes the display name for the local user
366
- * @param nickname {string} the new display name
367
- */
368
-function changeLocalDisplayName(nickname = '') {
369
-    const formattedNickname
370
-        = nickname.trim().substr(0, MAX_DISPLAY_NAME_LENGTH);
371
-
372
-    if (formattedNickname === APP.settings.getDisplayName()) {
373
-        return;
374
-    }
375
-
376
-    APP.settings.setDisplayName(formattedNickname);
377
-    room.setDisplayName(formattedNickname);
378
-    APP.UI.changeDisplayName(APP.conference.getMyUserId(), formattedNickname);
379
-}
380
-
381
 class ConferenceConnector {
366
 class ConferenceConnector {
382
     constructor(resolve, reject, invite) {
367
     constructor(resolve, reject, invite) {
383
         this._resolve = resolve;
368
         this._resolve = resolve;
1499
 
1484
 
1500
         APP.UI.addListener(UIEvents.EMAIL_CHANGED, this.changeLocalEmail);
1485
         APP.UI.addListener(UIEvents.EMAIL_CHANGED, this.changeLocalEmail);
1501
         room.addCommandListener(this.commands.defaults.EMAIL, (data, from) => {
1486
         room.addCommandListener(this.commands.defaults.EMAIL, (data, from) => {
1502
-            APP.store.dispatch(changeParticipantEmail(from, data.value));
1487
+            APP.store.dispatch(participantUpdated({
1488
+                id: from,
1489
+                email: data.value
1490
+            }));
1503
             APP.UI.setUserEmail(from, data.value);
1491
             APP.UI.setUserEmail(from, data.value);
1504
         });
1492
         });
1505
 
1493
 
1507
             this.commands.defaults.AVATAR_URL,
1495
             this.commands.defaults.AVATAR_URL,
1508
             (data, from) => {
1496
             (data, from) => {
1509
                 APP.store.dispatch(
1497
                 APP.store.dispatch(
1510
-                    changeParticipantAvatarURL(from, data.value));
1498
+                    participantUpdated({
1499
+                        id: from,
1500
+                        avatarURL: data.value
1501
+                    }));
1511
                 APP.UI.setUserAvatarUrl(from, data.value);
1502
                 APP.UI.setUserAvatarUrl(from, data.value);
1512
         });
1503
         });
1513
 
1504
 
1514
         room.addCommandListener(this.commands.defaults.AVATAR_ID,
1505
         room.addCommandListener(this.commands.defaults.AVATAR_ID,
1515
             (data, from) => {
1506
             (data, from) => {
1516
                 APP.store.dispatch(
1507
                 APP.store.dispatch(
1517
-                    changeParticipantAvatarID(from, data.value));
1508
+                    participantUpdated({
1509
+                        id: from,
1510
+                        avatarID: data.value
1511
+                    }));
1518
                 APP.UI.setUserAvatarID(from, data.value);
1512
                 APP.UI.setUserAvatarID(from, data.value);
1519
             });
1513
             });
1520
 
1514
 
1521
-        APP.UI.addListener(UIEvents.NICKNAME_CHANGED, changeLocalDisplayName);
1515
+        APP.UI.addListener(UIEvents.NICKNAME_CHANGED,
1516
+            this.changeLocalDisplayName.bind(this));
1522
 
1517
 
1523
         APP.UI.addListener(UIEvents.START_MUTED_CHANGED,
1518
         APP.UI.addListener(UIEvents.START_MUTED_CHANGED,
1524
             (startAudioMuted, startVideoMuted) => {
1519
             (startAudioMuted, startVideoMuted) => {
1925
         if (email === APP.settings.getEmail()) {
1920
         if (email === APP.settings.getEmail()) {
1926
             return;
1921
             return;
1927
         }
1922
         }
1928
-        APP.store.dispatch(changeParticipantEmail(room.myUserId(), email));
1923
+
1924
+        const localId = room ? room.myUserId() : undefined;
1925
+
1926
+        APP.store.dispatch(participantUpdated({
1927
+            id: localId,
1928
+            local: true,
1929
+            email
1930
+        }));
1929
 
1931
 
1930
         APP.settings.setEmail(email);
1932
         APP.settings.setEmail(email);
1931
-        APP.UI.setUserEmail(room.myUserId(), email);
1933
+        APP.UI.setUserEmail(localId, email);
1932
         sendData(commands.EMAIL, email);
1934
         sendData(commands.EMAIL, email);
1933
     },
1935
     },
1934
 
1936
 
1942
         if (url === APP.settings.getAvatarUrl()) {
1944
         if (url === APP.settings.getAvatarUrl()) {
1943
             return;
1945
             return;
1944
         }
1946
         }
1945
-        APP.store.dispatch(changeParticipantAvatarURL(room.myUserId(), url));
1947
+
1948
+        const localId = room ? room.myUserId() : undefined;
1949
+
1950
+        APP.store.dispatch(participantUpdated({
1951
+            id: localId,
1952
+            local: true,
1953
+            avatarURL: url
1954
+        }));
1946
 
1955
 
1947
         APP.settings.setAvatarUrl(url);
1956
         APP.settings.setAvatarUrl(url);
1948
-        APP.UI.setUserAvatarUrl(room.myUserId(), url);
1957
+        APP.UI.setUserAvatarUrl(localId, url);
1949
         sendData(commands.AVATAR_URL, url);
1958
         sendData(commands.AVATAR_URL, url);
1950
     },
1959
     },
1951
 
1960
 
1991
      */
2000
      */
1992
     isInLastN (participantId) {
2001
     isInLastN (participantId) {
1993
         return room.isInLastN(participantId);
2002
         return room.isInLastN(participantId);
2003
+    },
2004
+    /**
2005
+     * Changes the display name for the local user
2006
+     * @param nickname {string} the new display name
2007
+     */
2008
+    changeLocalDisplayName(nickname = '') {
2009
+        const formattedNickname
2010
+            = nickname.trim().substr(0, MAX_DISPLAY_NAME_LENGTH);
2011
+
2012
+        if (formattedNickname === APP.settings.getDisplayName()) {
2013
+            return;
2014
+        }
2015
+
2016
+        APP.settings.setDisplayName(formattedNickname);
2017
+        room.setDisplayName(formattedNickname);
2018
+        APP.UI.changeDisplayName(this.getMyUserId(),
2019
+            formattedNickname);
1994
     }
2020
     }
1995
 };
2021
 };

+ 2
- 1
modules/API/API.js View File

45
 
45
 
46
 function initCommands() {
46
 function initCommands() {
47
     commands = {
47
     commands = {
48
-        "display-name": APP.UI.inputDisplayNameHandler,
48
+        "display-name":
49
+            APP.conference.changeLocalDisplayName.bind(APP.conference),
49
         "toggle-audio": APP.conference.toggleAudioMuted.bind(APP.conference),
50
         "toggle-audio": APP.conference.toggleAudioMuted.bind(APP.conference),
50
         "toggle-video": APP.conference.toggleVideoMuted.bind(APP.conference),
51
         "toggle-video": APP.conference.toggleVideoMuted.bind(APP.conference),
51
         "toggle-film-strip": APP.UI.toggleFilmStrip,
52
         "toggle-film-strip": APP.UI.toggleFilmStrip,

+ 3
- 0
modules/UI/UI.js View File

762
     Avatar.setUserEmail(id, email);
762
     Avatar.setUserEmail(id, email);
763
 
763
 
764
     changeAvatar(id, Avatar.getAvatarUrl(id));
764
     changeAvatar(id, Avatar.getAvatarUrl(id));
765
+    if (APP.conference.isLocalId(id)) {
766
+        Profile.changeEmail(email);
767
+    }
765
 };
768
 };
766
 
769
 
767
 /**
770
 /**

+ 2
- 2
modules/UI/avatar/Avatar.js View File

30
 export default {
30
 export default {
31
     /**
31
     /**
32
      * Sets prop in users object.
32
      * Sets prop in users object.
33
-     * @param id {string} user id
33
+     * @param id {string} user id or undefined for the local user.
34
      * @param prop {string} name of the prop
34
      * @param prop {string} name of the prop
35
      * @param val {string} value to be set
35
      * @param val {string} value to be set
36
      */
36
      */
38
         // FIXME: Fixes the issue with not be able to return avatar for the
38
         // FIXME: Fixes the issue with not be able to return avatar for the
39
         // local user when the conference has been left. Maybe there is beter
39
         // local user when the conference has been left. Maybe there is beter
40
         // way to solve it.
40
         // way to solve it.
41
-        if(APP.conference.isLocalId(id)) {
41
+        if(!id || APP.conference.isLocalId(id)) {
42
             id = "local";
42
             id = "local";
43
         }
43
         }
44
         if(!val || (users[id] && users[id][prop] === val))
44
         if(!val || (users[id] && users[id][prop] === val))

+ 10
- 2
modules/UI/side_pannels/profile/Profile.js View File

15
         </div>
15
         </div>
16
         <div class="sideToolbarBlock">
16
         <div class="sideToolbarBlock">
17
             <label data-i18n="profile.setEmailLabel"></label>
17
             <label data-i18n="profile.setEmailLabel"></label>
18
-            <input id="setEmail" type="text" class="input-control" 
18
+            <input id="setEmail" type="text" class="input-control"
19
                 data-i18n="[placeholder]profile.setEmailInput">
19
                 data-i18n="[placeholder]profile.setEmailInput">
20
         </div>
20
         </div>
21
-        <div id="profile_auth_container" 
21
+        <div id="profile_auth_container"
22
              class="sideToolbarBlock auth_container">
22
              class="sideToolbarBlock auth_container">
23
             <p data-i18n="toolbar.authenticate"></p>
23
             <p data-i18n="toolbar.authenticate"></p>
24
             <ul>
24
             <ul>
122
         $('#avatar').attr('src', avatarUrl);
122
         $('#avatar').attr('src', avatarUrl);
123
     },
123
     },
124
 
124
 
125
+    /**
126
+     * Change the value of the field for the user email.
127
+     * @param {string} email the new value that will be displayed in the field.
128
+     */
129
+    changeEmail (email) {
130
+        $('#setEmail').val(email);
131
+    },
132
+
125
     /**
133
     /**
126
      * Shows or hides authentication related buttons
134
      * Shows or hides authentication related buttons
127
      * @param {boolean} show <tt>true</tt> to show or <tt>false</tt> to hide
135
      * @param {boolean} show <tt>true</tt> to show or <tt>false</tt> to hide

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

1
 import { JitsiConferenceEvents } from '../lib-jitsi-meet';
1
 import { JitsiConferenceEvents } from '../lib-jitsi-meet';
2
 import {
2
 import {
3
-    changeParticipantAvatarID,
4
-    changeParticipantAvatarURL,
5
-    changeParticipantEmail,
6
     dominantSpeakerChanged,
3
     dominantSpeakerChanged,
7
     getLocalParticipant,
4
     getLocalParticipant,
8
     participantJoined,
5
     participantJoined,
9
     participantLeft,
6
     participantLeft,
10
-    participantRoleChanged
7
+    participantRoleChanged,
8
+    participantUpdated
11
 } from '../participants';
9
 } from '../participants';
12
 import { trackAdded, trackRemoved } from '../tracks';
10
 import { trackAdded, trackRemoved } from '../tracks';
13
 
11
 
81
 
79
 
82
     conference.addCommandListener(
80
     conference.addCommandListener(
83
             AVATAR_ID_COMMAND,
81
             AVATAR_ID_COMMAND,
84
-            (data, id) => dispatch(changeParticipantAvatarID(id, data.value)));
82
+            (data, id) => dispatch(participantUpdated({
83
+                id,
84
+                avatarID: data.value
85
+            })));
85
     conference.addCommandListener(
86
     conference.addCommandListener(
86
             AVATAR_URL_COMMAND,
87
             AVATAR_URL_COMMAND,
87
-            (data, id) => dispatch(changeParticipantAvatarURL(id, data.value)));
88
+            (data, id) => dispatch(participantUpdated({
89
+                id,
90
+                avatarURL: data.value
91
+            })));
88
     conference.addCommandListener(
92
     conference.addCommandListener(
89
             EMAIL_COMMAND,
93
             EMAIL_COMMAND,
90
-            (data, id) => dispatch(changeParticipantEmail(id, data.value)));
94
+            (data, id) => dispatch(participantUpdated({
95
+                id,
96
+                email: data.value
97
+            })));
91
 }
98
 }
92
 
99
 
93
 /**
100
 /**

+ 20
- 73
react/features/base/participants/actions.js View File

8
 } from './actionTypes';
8
 } from './actionTypes';
9
 import { getLocalParticipant } from './functions';
9
 import { getLocalParticipant } from './functions';
10
 
10
 
11
-/**
12
- * Action to update a participant's avatar ID.
13
- *
14
- * @param {string} id - Participant's ID.
15
- * @param {string} avatarID - Participant's avatar ID.
16
- * @returns {{
17
- *     type: PARTICIPANT_UPDATED,
18
- *     participant: {
19
- *         id: string,
20
- *         avatarID: string,
21
- *     }
22
- * }}
23
- */
24
-export function changeParticipantAvatarID(id, avatarID) {
25
-    return {
26
-        type: PARTICIPANT_UPDATED,
27
-        participant: {
28
-            id,
29
-            avatarID
30
-        }
31
-    };
32
-}
33
-
34
-/**
35
- * Action to update a participant's avatar URL.
36
- *
37
- * @param {string} id - Participant's ID.
38
- * @param {string} avatarURL - Participant's avatar URL.
39
- * @returns {{
40
- *     type: PARTICIPANT_UPDATED,
41
- *     participant: {
42
- *         id: string,
43
- *         avatarURL: string,
44
- *     }
45
- * }}
46
- */
47
-export function changeParticipantAvatarURL(id, avatarURL) {
48
-    return {
49
-        type: PARTICIPANT_UPDATED,
50
-        participant: {
51
-            id,
52
-            avatarURL
53
-        }
54
-    };
55
-}
56
-
57
-/**
58
- * Action to update a participant's email.
59
- *
60
- * @param {string} id - Participant's ID.
61
- * @param {string} email - Participant's email.
62
- * @returns {{
63
- *     type: PARTICIPANT_UPDATED,
64
- *     participant: {
65
- *         id: string,
66
- *         email: string
67
- *     }
68
- * }}
69
- */
70
-export function changeParticipantEmail(id, email) {
71
-    return {
72
-        type: PARTICIPANT_UPDATED,
73
-        participant: {
74
-            id,
75
-            email
76
-        }
77
-    };
78
-}
79
-
80
 /**
11
 /**
81
  * Create an action for when dominant speaker changes.
12
  * Create an action for when dominant speaker changes.
82
  *
13
  *
203
  * }}
134
  * }}
204
  */
135
  */
205
 export function participantRoleChanged(id, role) {
136
 export function participantRoleChanged(id, role) {
137
+    return participantUpdated({
138
+        id,
139
+        role
140
+    });
141
+}
142
+
143
+/**
144
+ * Action to signal that some of participant properties has been changed.
145
+ *
146
+ * @param {Participant} participant={} - Information about participant. To
147
+ * identify the participant the object should contain either property id with
148
+ * value the id of the participant or property local with value true (if the
149
+ * local participant hasn't joined the conference yet).
150
+ * @returns {{
151
+ *     type: PARTICIPANT_UPDATED,
152
+ *     participant: Participant
153
+ * }}
154
+ */
155
+export function participantUpdated(participant = {}) {
206
     return {
156
     return {
207
         type: PARTICIPANT_UPDATED,
157
         type: PARTICIPANT_UPDATED,
208
-        participant: {
209
-            id,
210
-            role
211
-        }
158
+        participant
212
     };
159
     };
213
 }
160
 }
214
 
161
 

+ 6
- 1
react/features/base/participants/reducer.js View File

112
 
112
 
113
     case PARTICIPANT_UPDATED: {
113
     case PARTICIPANT_UPDATED: {
114
         const participant = action.participant; // eslint-disable-line no-shadow
114
         const participant = action.participant; // eslint-disable-line no-shadow
115
-        const { id } = participant;
115
+        const { local } = participant;
116
+        let { id } = participant;
117
+
118
+        if (!id && local) {
119
+            id = LOCAL_PARTICIPANT_DEFAULT_ID;
120
+        }
116
 
121
 
117
         if (state.id === id) {
122
         if (state.id === id) {
118
             const newState = { ...state };
123
             const newState = { ...state };

Loading…
Cancel
Save