Merge pull request #1440 from jitsi/iframe_api_race_condition

Fix executeCommand race condition
This commit is contained in:
Saúl Ibarra Corretgé 2017-03-31 16:48:50 +01:00 committed by GitHub
commit a10f040df6
8 changed files with 112 additions and 115 deletions

View File

@ -32,12 +32,10 @@ import {
isFatalJitsiConnectionError isFatalJitsiConnectionError
} from './react/features/base/lib-jitsi-meet'; } from './react/features/base/lib-jitsi-meet';
import { import {
changeParticipantAvatarID,
changeParticipantAvatarURL,
changeParticipantEmail,
participantJoined, participantJoined,
participantLeft, participantLeft,
participantRoleChanged participantRoleChanged,
participantUpdated
} from './react/features/base/participants'; } from './react/features/base/participants';
import { import {
showDesktopPicker showDesktopPicker
@ -174,6 +172,10 @@ function createInitialLocalTracksAndConnect(roomName) {
* @param {string} value new value * @param {string} value new value
*/ */
function sendData (command, value) { function sendData (command, value) {
if(!room) {
return;
}
room.removeCommand(command); room.removeCommand(command);
room.sendCommand(command, {value: value}); room.sendCommand(command, {value: value});
} }
@ -361,23 +363,6 @@ function createLocalTracks (options, checkForPermissionPrompt) {
}); });
} }
/**
* Changes the display name for the local user
* @param nickname {string} the new display name
*/
function changeLocalDisplayName(nickname = '') {
const formattedNickname
= nickname.trim().substr(0, MAX_DISPLAY_NAME_LENGTH);
if (formattedNickname === APP.settings.getDisplayName()) {
return;
}
APP.settings.setDisplayName(formattedNickname);
room.setDisplayName(formattedNickname);
APP.UI.changeDisplayName(APP.conference.getMyUserId(), formattedNickname);
}
class ConferenceConnector { class ConferenceConnector {
constructor(resolve, reject, invite) { constructor(resolve, reject, invite) {
this._resolve = resolve; this._resolve = resolve;
@ -1499,7 +1484,10 @@ export default {
APP.UI.addListener(UIEvents.EMAIL_CHANGED, this.changeLocalEmail); APP.UI.addListener(UIEvents.EMAIL_CHANGED, this.changeLocalEmail);
room.addCommandListener(this.commands.defaults.EMAIL, (data, from) => { room.addCommandListener(this.commands.defaults.EMAIL, (data, from) => {
APP.store.dispatch(changeParticipantEmail(from, data.value)); APP.store.dispatch(participantUpdated({
id: from,
email: data.value
}));
APP.UI.setUserEmail(from, data.value); APP.UI.setUserEmail(from, data.value);
}); });
@ -1507,18 +1495,25 @@ export default {
this.commands.defaults.AVATAR_URL, this.commands.defaults.AVATAR_URL,
(data, from) => { (data, from) => {
APP.store.dispatch( APP.store.dispatch(
changeParticipantAvatarURL(from, data.value)); participantUpdated({
id: from,
avatarURL: data.value
}));
APP.UI.setUserAvatarUrl(from, data.value); APP.UI.setUserAvatarUrl(from, data.value);
}); });
room.addCommandListener(this.commands.defaults.AVATAR_ID, room.addCommandListener(this.commands.defaults.AVATAR_ID,
(data, from) => { (data, from) => {
APP.store.dispatch( APP.store.dispatch(
changeParticipantAvatarID(from, data.value)); participantUpdated({
id: from,
avatarID: data.value
}));
APP.UI.setUserAvatarID(from, data.value); APP.UI.setUserAvatarID(from, data.value);
}); });
APP.UI.addListener(UIEvents.NICKNAME_CHANGED, changeLocalDisplayName); APP.UI.addListener(UIEvents.NICKNAME_CHANGED,
this.changeLocalDisplayName.bind(this));
APP.UI.addListener(UIEvents.START_MUTED_CHANGED, APP.UI.addListener(UIEvents.START_MUTED_CHANGED,
(startAudioMuted, startVideoMuted) => { (startAudioMuted, startVideoMuted) => {
@ -1925,10 +1920,17 @@ export default {
if (email === APP.settings.getEmail()) { if (email === APP.settings.getEmail()) {
return; return;
} }
APP.store.dispatch(changeParticipantEmail(room.myUserId(), email));
const localId = room ? room.myUserId() : undefined;
APP.store.dispatch(participantUpdated({
id: localId,
local: true,
email
}));
APP.settings.setEmail(email); APP.settings.setEmail(email);
APP.UI.setUserEmail(room.myUserId(), email); APP.UI.setUserEmail(localId, email);
sendData(commands.EMAIL, email); sendData(commands.EMAIL, email);
}, },
@ -1942,10 +1944,17 @@ export default {
if (url === APP.settings.getAvatarUrl()) { if (url === APP.settings.getAvatarUrl()) {
return; return;
} }
APP.store.dispatch(changeParticipantAvatarURL(room.myUserId(), url));
const localId = room ? room.myUserId() : undefined;
APP.store.dispatch(participantUpdated({
id: localId,
local: true,
avatarURL: url
}));
APP.settings.setAvatarUrl(url); APP.settings.setAvatarUrl(url);
APP.UI.setUserAvatarUrl(room.myUserId(), url); APP.UI.setUserAvatarUrl(localId, url);
sendData(commands.AVATAR_URL, url); sendData(commands.AVATAR_URL, url);
}, },
@ -1991,5 +2000,22 @@ export default {
*/ */
isInLastN (participantId) { isInLastN (participantId) {
return room.isInLastN(participantId); return room.isInLastN(participantId);
},
/**
* Changes the display name for the local user
* @param nickname {string} the new display name
*/
changeLocalDisplayName(nickname = '') {
const formattedNickname
= nickname.trim().substr(0, MAX_DISPLAY_NAME_LENGTH);
if (formattedNickname === APP.settings.getDisplayName()) {
return;
}
APP.settings.setDisplayName(formattedNickname);
room.setDisplayName(formattedNickname);
APP.UI.changeDisplayName(this.getMyUserId(),
formattedNickname);
} }
}; };

View File

@ -45,7 +45,8 @@ let enabled = false;
function initCommands() { function initCommands() {
commands = { commands = {
"display-name": APP.UI.inputDisplayNameHandler, "display-name":
APP.conference.changeLocalDisplayName.bind(APP.conference),
"toggle-audio": APP.conference.toggleAudioMuted.bind(APP.conference), "toggle-audio": APP.conference.toggleAudioMuted.bind(APP.conference),
"toggle-video": APP.conference.toggleVideoMuted.bind(APP.conference), "toggle-video": APP.conference.toggleVideoMuted.bind(APP.conference),
"toggle-film-strip": APP.UI.toggleFilmStrip, "toggle-film-strip": APP.UI.toggleFilmStrip,

View File

@ -762,6 +762,9 @@ UI.setUserEmail = function (id, email) {
Avatar.setUserEmail(id, email); Avatar.setUserEmail(id, email);
changeAvatar(id, Avatar.getAvatarUrl(id)); changeAvatar(id, Avatar.getAvatarUrl(id));
if (APP.conference.isLocalId(id)) {
Profile.changeEmail(email);
}
}; };
/** /**

View File

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

View File

@ -122,6 +122,14 @@ export default {
$('#avatar').attr('src', avatarUrl); $('#avatar').attr('src', avatarUrl);
}, },
/**
* Change the value of the field for the user email.
* @param {string} email the new value that will be displayed in the field.
*/
changeEmail (email) {
$('#setEmail').val(email);
},
/** /**
* Shows or hides authentication related buttons * Shows or hides authentication related buttons
* @param {boolean} show <tt>true</tt> to show or <tt>false</tt> to hide * @param {boolean} show <tt>true</tt> to show or <tt>false</tt> to hide

View File

@ -1,13 +1,11 @@
import { JitsiConferenceEvents } from '../lib-jitsi-meet'; import { JitsiConferenceEvents } from '../lib-jitsi-meet';
import { import {
changeParticipantAvatarID,
changeParticipantAvatarURL,
changeParticipantEmail,
dominantSpeakerChanged, dominantSpeakerChanged,
getLocalParticipant, getLocalParticipant,
participantJoined, participantJoined,
participantLeft, participantLeft,
participantRoleChanged participantRoleChanged,
participantUpdated
} from '../participants'; } from '../participants';
import { trackAdded, trackRemoved } from '../tracks'; import { trackAdded, trackRemoved } from '../tracks';
@ -81,13 +79,22 @@ function _addConferenceListeners(conference, dispatch) {
conference.addCommandListener( conference.addCommandListener(
AVATAR_ID_COMMAND, AVATAR_ID_COMMAND,
(data, id) => dispatch(changeParticipantAvatarID(id, data.value))); (data, id) => dispatch(participantUpdated({
id,
avatarID: data.value
})));
conference.addCommandListener( conference.addCommandListener(
AVATAR_URL_COMMAND, AVATAR_URL_COMMAND,
(data, id) => dispatch(changeParticipantAvatarURL(id, data.value))); (data, id) => dispatch(participantUpdated({
id,
avatarURL: data.value
})));
conference.addCommandListener( conference.addCommandListener(
EMAIL_COMMAND, EMAIL_COMMAND,
(data, id) => dispatch(changeParticipantEmail(id, data.value))); (data, id) => dispatch(participantUpdated({
id,
email: data.value
})));
} }
/** /**

View File

@ -8,75 +8,6 @@ import {
} from './actionTypes'; } from './actionTypes';
import { getLocalParticipant } from './functions'; import { getLocalParticipant } from './functions';
/**
* Action to update a participant's avatar ID.
*
* @param {string} id - Participant's ID.
* @param {string} avatarID - Participant's avatar ID.
* @returns {{
* type: PARTICIPANT_UPDATED,
* participant: {
* id: string,
* avatarID: string,
* }
* }}
*/
export function changeParticipantAvatarID(id, avatarID) {
return {
type: PARTICIPANT_UPDATED,
participant: {
id,
avatarID
}
};
}
/**
* Action to update a participant's avatar URL.
*
* @param {string} id - Participant's ID.
* @param {string} avatarURL - Participant's avatar URL.
* @returns {{
* type: PARTICIPANT_UPDATED,
* participant: {
* id: string,
* avatarURL: string,
* }
* }}
*/
export function changeParticipantAvatarURL(id, avatarURL) {
return {
type: PARTICIPANT_UPDATED,
participant: {
id,
avatarURL
}
};
}
/**
* Action to update a participant's email.
*
* @param {string} id - Participant's ID.
* @param {string} email - Participant's email.
* @returns {{
* type: PARTICIPANT_UPDATED,
* participant: {
* id: string,
* email: string
* }
* }}
*/
export function changeParticipantEmail(id, email) {
return {
type: PARTICIPANT_UPDATED,
participant: {
id,
email
}
};
}
/** /**
* Create an action for when dominant speaker changes. * Create an action for when dominant speaker changes.
* *
@ -203,12 +134,28 @@ export function participantLeft(id) {
* }} * }}
*/ */
export function participantRoleChanged(id, role) { export function participantRoleChanged(id, role) {
return { return participantUpdated({
type: PARTICIPANT_UPDATED,
participant: {
id, id,
role role
});
} }
/**
* Action to signal that some of participant properties has been changed.
*
* @param {Participant} participant={} - Information about participant. To
* identify the participant the object should contain either property id with
* value the id of the participant or property local with value true (if the
* local participant hasn't joined the conference yet).
* @returns {{
* type: PARTICIPANT_UPDATED,
* participant: Participant
* }}
*/
export function participantUpdated(participant = {}) {
return {
type: PARTICIPANT_UPDATED,
participant
}; };
} }

View File

@ -112,7 +112,12 @@ function _participant(state, action) {
case PARTICIPANT_UPDATED: { case PARTICIPANT_UPDATED: {
const participant = action.participant; // eslint-disable-line no-shadow const participant = action.participant; // eslint-disable-line no-shadow
const { id } = participant; const { local } = participant;
let { id } = participant;
if (!id && local) {
id = LOCAL_PARTICIPANT_DEFAULT_ID;
}
if (state.id === id) { if (state.id === id) {
const newState = { ...state }; const newState = { ...state };