2018-03-07 00:28:19 +00:00
|
|
|
// @flow
|
2017-10-02 23:08:07 +00:00
|
|
|
|
2017-06-29 03:35:43 +00:00
|
|
|
import UIEvents from '../../../../service/UI/UIEvents';
|
|
|
|
|
2018-02-26 19:37:12 +00:00
|
|
|
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../app';
|
2016-10-05 14:36:59 +00:00
|
|
|
import {
|
|
|
|
CONFERENCE_JOINED,
|
|
|
|
CONFERENCE_LEFT
|
|
|
|
} from '../conference';
|
|
|
|
import { MiddlewareRegistry } from '../redux';
|
2018-02-26 19:37:12 +00:00
|
|
|
import { playSound, registerSound, unregisterSound } from '../sounds';
|
2016-10-05 14:36:59 +00:00
|
|
|
|
2017-08-14 15:02:58 +00:00
|
|
|
import {
|
2018-03-07 00:28:19 +00:00
|
|
|
localParticipantIdChanged,
|
|
|
|
participantUpdated
|
|
|
|
} from './actions';
|
|
|
|
import {
|
|
|
|
DOMINANT_SPEAKER_CHANGED,
|
2017-08-14 15:02:58 +00:00
|
|
|
KICK_PARTICIPANT,
|
|
|
|
MUTE_REMOTE_PARTICIPANT,
|
2017-12-19 23:11:54 +00:00
|
|
|
PARTICIPANT_DISPLAY_NAME_CHANGED,
|
|
|
|
PARTICIPANT_JOINED,
|
2018-02-26 19:37:12 +00:00
|
|
|
PARTICIPANT_LEFT,
|
2017-12-19 23:11:54 +00:00
|
|
|
PARTICIPANT_UPDATED
|
2017-08-14 15:02:58 +00:00
|
|
|
} from './actionTypes';
|
2018-02-26 19:37:12 +00:00
|
|
|
import {
|
|
|
|
LOCAL_PARTICIPANT_DEFAULT_ID,
|
|
|
|
PARTICIPANT_JOINED_SOUND_ID,
|
|
|
|
PARTICIPANT_LEFT_SOUND_ID
|
|
|
|
} from './constants';
|
2017-12-19 23:11:54 +00:00
|
|
|
import {
|
|
|
|
getAvatarURLByParticipantId,
|
2018-02-26 19:37:12 +00:00
|
|
|
getLocalParticipant,
|
2018-03-07 00:28:19 +00:00
|
|
|
getParticipantById,
|
2018-02-26 19:37:12 +00:00
|
|
|
getParticipantCount
|
2017-12-19 23:11:54 +00:00
|
|
|
} from './functions';
|
2018-02-26 19:37:12 +00:00
|
|
|
import {
|
|
|
|
PARTICIPANT_JOINED_SRC,
|
|
|
|
PARTICIPANT_LEFT_SRC
|
|
|
|
} from './sounds';
|
2017-06-29 03:35:43 +00:00
|
|
|
|
|
|
|
declare var APP: Object;
|
2016-10-05 14:36:59 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Middleware that captures CONFERENCE_JOINED and CONFERENCE_LEFT actions and
|
|
|
|
* updates respectively ID of local participant.
|
|
|
|
*
|
|
|
|
* @param {Store} store - Redux store.
|
|
|
|
* @returns {Function}
|
|
|
|
*/
|
|
|
|
MiddlewareRegistry.register(store => next => action => {
|
2017-11-09 17:23:17 +00:00
|
|
|
const { conference } = store.getState()['features/base/conference'];
|
|
|
|
|
2018-02-26 19:37:12 +00:00
|
|
|
if (action.type === PARTICIPANT_JOINED
|
2018-03-07 00:28:19 +00:00
|
|
|
|| action.type === PARTICIPANT_LEFT) {
|
2018-02-26 19:37:12 +00:00
|
|
|
_maybePlaySounds(store, action);
|
|
|
|
}
|
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
switch (action.type) {
|
2018-02-26 19:37:12 +00:00
|
|
|
case APP_WILL_MOUNT:
|
|
|
|
_registerSounds(store);
|
|
|
|
break;
|
|
|
|
case APP_WILL_UNMOUNT:
|
|
|
|
_unregisterSounds(store);
|
|
|
|
break;
|
2016-10-05 14:36:59 +00:00
|
|
|
case CONFERENCE_JOINED:
|
2016-12-12 00:29:13 +00:00
|
|
|
store.dispatch(localParticipantIdChanged(action.conference.myUserId()));
|
2016-10-05 14:36:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CONFERENCE_LEFT:
|
|
|
|
store.dispatch(localParticipantIdChanged(LOCAL_PARTICIPANT_DEFAULT_ID));
|
|
|
|
break;
|
2017-06-29 03:35:43 +00:00
|
|
|
|
2018-03-07 00:28:19 +00:00
|
|
|
case DOMINANT_SPEAKER_CHANGED: {
|
|
|
|
// Ensure the raised hand state is cleared for the dominant speaker.
|
|
|
|
const participant = getLocalParticipant(store.getState());
|
|
|
|
|
|
|
|
if (participant) {
|
|
|
|
const local = participant.id === action.participant.id;
|
|
|
|
|
|
|
|
store.dispatch(participantUpdated({
|
|
|
|
id: action.participant.id,
|
|
|
|
local,
|
|
|
|
raisedHand: false
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof APP === 'object') {
|
|
|
|
APP.UI.markDominantSpeaker(action.participant.id);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-08-14 15:02:58 +00:00
|
|
|
case KICK_PARTICIPANT:
|
2017-11-09 17:23:17 +00:00
|
|
|
conference.kickParticipant(action.id);
|
2017-08-14 15:02:58 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MUTE_REMOTE_PARTICIPANT:
|
2017-11-09 17:23:17 +00:00
|
|
|
conference.muteParticipant(action.id);
|
2017-08-14 15:02:58 +00:00
|
|
|
break;
|
|
|
|
|
2017-06-29 03:35:43 +00:00
|
|
|
// TODO Remove this middleware when the local display name update flow is
|
|
|
|
// fully brought into redux.
|
|
|
|
case PARTICIPANT_DISPLAY_NAME_CHANGED: {
|
|
|
|
if (typeof APP !== 'undefined') {
|
|
|
|
const participant = getLocalParticipant(store.getState());
|
|
|
|
|
|
|
|
if (participant && participant.id === action.id) {
|
|
|
|
APP.UI.emitEvent(UIEvents.NICKNAME_CHANGED, action.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2017-12-19 23:11:54 +00:00
|
|
|
|
|
|
|
case PARTICIPANT_JOINED:
|
|
|
|
case PARTICIPANT_UPDATED: {
|
2018-03-07 00:28:19 +00:00
|
|
|
const { participant } = action;
|
|
|
|
const { id, local, raisedHand } = participant;
|
|
|
|
|
|
|
|
// Send an external update of the local participant's raised hand state
|
|
|
|
// if a new raised hand state is defined in the action.
|
|
|
|
if (typeof raisedHand !== 'undefined') {
|
|
|
|
if (local) {
|
|
|
|
conference.setLocalParticipantProperty(
|
|
|
|
'raisedHand',
|
|
|
|
raisedHand);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof APP === 'object') {
|
|
|
|
if (local) {
|
|
|
|
APP.UI.onLocalRaiseHandChanged(raisedHand);
|
|
|
|
APP.UI.setLocalRaisedHandStatus(raisedHand);
|
|
|
|
} else {
|
|
|
|
const remoteParticipant
|
|
|
|
= getParticipantById(store.getState(), id);
|
|
|
|
|
|
|
|
remoteParticipant
|
|
|
|
&& APP.UI.setRaisedHandStatus(
|
|
|
|
remoteParticipant.id,
|
|
|
|
remoteParticipant.name,
|
|
|
|
raisedHand);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-12-19 23:11:54 +00:00
|
|
|
|
2018-03-07 00:28:19 +00:00
|
|
|
// Notify external listeners of potential avatarURL changes.
|
|
|
|
if (typeof APP === 'object') {
|
2017-12-19 23:11:54 +00:00
|
|
|
const preUpdateAvatarURL
|
|
|
|
= getAvatarURLByParticipantId(store.getState(), id);
|
|
|
|
|
|
|
|
// Allow the redux update to go through and compare the old avatar
|
|
|
|
// to the new avatar and emit out change events if necessary.
|
|
|
|
const result = next(action);
|
|
|
|
|
|
|
|
const postUpdateAvatarURL
|
|
|
|
= getAvatarURLByParticipantId(store.getState(), id);
|
|
|
|
|
|
|
|
if (preUpdateAvatarURL !== postUpdateAvatarURL) {
|
|
|
|
const currentKnownId = local
|
|
|
|
? APP.conference.getMyUserId() : id;
|
|
|
|
|
|
|
|
APP.UI.refreshAvatarDisplay(
|
|
|
|
currentKnownId, postUpdateAvatarURL);
|
|
|
|
APP.API.notifyAvatarChanged(
|
|
|
|
currentKnownId, postUpdateAvatarURL);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2016-10-05 14:36:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return next(action);
|
|
|
|
});
|
2018-02-26 19:37:12 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Plays sounds when participants join/leave conference.
|
|
|
|
*
|
|
|
|
* @param {Store} store - The Redux store.
|
|
|
|
* @param {Action} action - The Redux action. Should be either
|
|
|
|
* {@link PARTICIPANT_JOINED} or {@link PARTICIPANT_LEFT}.
|
|
|
|
* @private
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
function _maybePlaySounds({ getState, dispatch }, action) {
|
|
|
|
const state = getState();
|
|
|
|
const { startAudioMuted } = state['features/base/config'];
|
|
|
|
|
|
|
|
// We're not playing sounds for local participant
|
|
|
|
// nor when the user is joining past the "startAudioMuted" limit.
|
|
|
|
// The intention there was to not play user joined notification in big
|
|
|
|
// conferences where 100th person is joining.
|
|
|
|
if (!action.participant.local
|
|
|
|
&& (!startAudioMuted
|
|
|
|
|| getParticipantCount(state) < startAudioMuted)) {
|
|
|
|
if (action.type === PARTICIPANT_JOINED) {
|
|
|
|
dispatch(playSound(PARTICIPANT_JOINED_SOUND_ID));
|
|
|
|
} else if (action.type === PARTICIPANT_LEFT) {
|
|
|
|
dispatch(playSound(PARTICIPANT_LEFT_SOUND_ID));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Registers sounds related with the participants feature.
|
|
|
|
*
|
|
|
|
* @param {Store} store - The Redux store.
|
|
|
|
* @private
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
function _registerSounds({ dispatch }) {
|
|
|
|
dispatch(
|
|
|
|
registerSound(PARTICIPANT_JOINED_SOUND_ID, PARTICIPANT_JOINED_SRC));
|
|
|
|
dispatch(
|
|
|
|
registerSound(PARTICIPANT_LEFT_SOUND_ID, PARTICIPANT_LEFT_SRC));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unregisters sounds related with the participants feature.
|
|
|
|
*
|
|
|
|
* @param {Store} store - The Redux store.
|
|
|
|
* @private
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
function _unregisterSounds({ dispatch }) {
|
|
|
|
dispatch(
|
|
|
|
unregisterSound(PARTICIPANT_JOINED_SOUND_ID, PARTICIPANT_JOINED_SRC));
|
|
|
|
dispatch(
|
|
|
|
unregisterSound(PARTICIPANT_LEFT_SOUND_ID, PARTICIPANT_LEFT_SRC));
|
|
|
|
}
|