123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- // @flow
-
- import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
- import {
- CONFERENCE_JOINED
- } from '../base/conference';
- import {
- getLocalParticipant,
- getParticipantCount,
- getParticipantPresenceStatus,
- getRemoteParticipants,
- PARTICIPANT_JOINED,
- PARTICIPANT_JOINED_SOUND_ID,
- PARTICIPANT_LEFT,
- PARTICIPANT_UPDATED,
- pinParticipant
- } from '../base/participants';
- import { MiddlewareRegistry } from '../base/redux';
- import {
- playSound,
- registerSound,
- stopSound,
- unregisterSound
- } from '../base/sounds';
- import {
- CALLING,
- CONNECTED_USER,
- EXPIRED,
- INVITED,
- REJECTED,
- RINGING
- } from '../presence-status';
-
- import {
- SET_CALLEE_INFO_VISIBLE,
- UPDATE_DIAL_IN_NUMBERS_FAILED
- } from './actionTypes';
- import {
- invite,
- removePendingInviteRequests,
- setCalleeInfoVisible
- } from './actions';
- import {
- OUTGOING_CALL_EXPIRED_SOUND_ID,
- OUTGOING_CALL_REJECTED_SOUND_ID,
- OUTGOING_CALL_RINGING_SOUND_ID,
- OUTGOING_CALL_START_SOUND_ID
- } from './constants';
- import logger from './logger';
- import { sounds } from './sounds';
-
- declare var interfaceConfig: Object;
-
- /**
- * Maps the presence status with the ID of the sound that will be played when
- * the status is received.
- */
- const statusToRingtone = {
- [CALLING]: OUTGOING_CALL_START_SOUND_ID,
- [CONNECTED_USER]: PARTICIPANT_JOINED_SOUND_ID,
- [EXPIRED]: OUTGOING_CALL_EXPIRED_SOUND_ID,
- [INVITED]: OUTGOING_CALL_START_SOUND_ID,
- [REJECTED]: OUTGOING_CALL_REJECTED_SOUND_ID,
- [RINGING]: OUTGOING_CALL_RINGING_SOUND_ID
- };
-
- /**
- * The middleware of the feature invite common to mobile/react-native and
- * Web/React.
- *
- * @param {Store} store - The redux store.
- * @returns {Function}
- */
- MiddlewareRegistry.register(store => next => action => {
- let oldParticipantPresence;
- const { dispatch, getState } = store;
- const state = getState();
-
- if (action.type === PARTICIPANT_UPDATED
- || action.type === PARTICIPANT_LEFT) {
- oldParticipantPresence
- = getParticipantPresenceStatus(state, action.participant.id);
- }
-
- if (action.type === SET_CALLEE_INFO_VISIBLE) {
- if (action.calleeInfoVisible) {
- dispatch(pinParticipant(getLocalParticipant(state).id));
- } else {
- // unpin participant
- dispatch(pinParticipant());
- }
- }
-
- const result = next(action);
-
- switch (action.type) {
- case APP_WILL_MOUNT:
- for (const [ soundId, sound ] of sounds.entries()) {
- dispatch(registerSound(soundId, sound.file, sound.options));
- }
- break;
-
- case APP_WILL_UNMOUNT:
- for (const soundId of sounds.keys()) {
- dispatch(unregisterSound(soundId));
- }
- break;
-
- case CONFERENCE_JOINED:
- _onConferenceJoined(store);
- break;
-
- case PARTICIPANT_JOINED:
- case PARTICIPANT_LEFT:
- case PARTICIPANT_UPDATED: {
- _maybeHideCalleeInfo(action, store);
-
- const newParticipantPresence
- = getParticipantPresenceStatus(state, action.participant.id);
-
- if (oldParticipantPresence === newParticipantPresence) {
- break;
- }
-
- const oldSoundId
- = oldParticipantPresence
- && statusToRingtone[oldParticipantPresence];
- const newSoundId
- = newParticipantPresence
- && statusToRingtone[newParticipantPresence];
-
-
- if (oldSoundId === newSoundId) {
- break;
- }
-
- if (oldSoundId) {
- dispatch(stopSound(oldSoundId));
- }
-
- if (newSoundId) {
- dispatch(playSound(newSoundId));
- }
-
- break;
- }
- case UPDATE_DIAL_IN_NUMBERS_FAILED:
- logger.error(
- 'Error encountered while fetching dial-in numbers:',
- action.error);
- break;
- }
-
- return result;
- });
-
- /**
- * Hides the callee info layot if there are more than 1 real
- * (not poltergeist, shared video, etc.) participants in the call.
- *
- * @param {Object} action - The redux action.
- * @param {ReduxStore} store - The redux store.
- * @returns {void}
- */
- function _maybeHideCalleeInfo(action, store) {
- const state = store.getState();
-
- if (!state['features/invite'].calleeInfoVisible) {
- return;
- }
- const participants = getRemoteParticipants(state);
- const participantCount = getParticipantCount(state);
- let numberOfPoltergeists = 0;
-
- participants.forEach(p => {
- if (p.botType === 'poltergeist') {
- numberOfPoltergeists++;
- }
- });
- const numberOfRealParticipants = participantCount - numberOfPoltergeists;
-
- if ((numberOfPoltergeists > 1 || numberOfRealParticipants > 1)
- || (action.type === PARTICIPANT_LEFT && participantCount === 1)) {
- store.dispatch(setCalleeInfoVisible(false));
- }
- }
-
- /**
- * Executes the pending invitation requests if any.
- *
- * @param {ReduxStore} store - The redux store.
- * @returns {void}
- */
- function _onConferenceJoined(store) {
- const { dispatch, getState } = store;
-
- const pendingInviteRequests
- = getState()['features/invite'].pendingInviteRequests || [];
-
- pendingInviteRequests.forEach(({ invitees, callback }) => {
- dispatch(invite(invitees))
- .then(failedInvitees => {
- callback(failedInvitees);
- });
- });
-
- dispatch(removePendingInviteRequests());
- }
|