jiti-meet/react/features/invite/middleware.any.js

209 lines
5.3 KiB
JavaScript
Raw Normal View History

// @flow
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
import {
2018-06-26 22:56:22 +00:00
CONFERENCE_JOINED
} from '../base/conference';
import {
PARTICIPANT_JOINED,
PARTICIPANT_JOINED_SOUND_ID,
PARTICIPANT_LEFT,
2018-06-26 22:56:22 +00:00
PARTICIPANT_UPDATED,
getLocalParticipant,
getParticipantCount,
getParticipantPresenceStatus,
getRemoteParticipants,
2018-06-26 22:56:22 +00:00
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';
2018-06-26 22:56:22 +00:00
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;
2018-06-26 22:56:22 +00:00
const { dispatch, getState } = store;
const state = getState();
if (action.type === PARTICIPANT_UPDATED
|| action.type === PARTICIPANT_LEFT) {
oldParticipantPresence
2018-06-26 22:56:22 +00:00
= 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()) {
2018-06-26 22:56:22 +00:00
dispatch(registerSound(soundId, sound.file, sound.options));
}
break;
case APP_WILL_UNMOUNT:
for (const soundId of sounds.keys()) {
2018-06-26 22:56:22 +00:00
dispatch(unregisterSound(soundId));
}
break;
2018-06-26 22:56:22 +00:00
case CONFERENCE_JOINED:
_onConferenceJoined(store);
break;
case PARTICIPANT_JOINED:
case PARTICIPANT_LEFT:
case PARTICIPANT_UPDATED: {
2018-06-26 22:56:22 +00:00
_maybeHideCalleeInfo(action, store);
const newParticipantPresence
2018-06-26 22:56:22 +00:00
= 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) {
2018-06-26 22:56:22 +00:00
dispatch(stopSound(oldSoundId));
}
if (newSoundId) {
2018-06-26 22:56:22 +00:00
dispatch(playSound(newSoundId));
}
break;
}
case UPDATE_DIAL_IN_NUMBERS_FAILED:
2017-06-15 00:40:51 +00:00
logger.error(
'Error encountered while fetching dial-in numbers:',
action.error);
break;
}
return result;
});
2018-06-26 22:56:22 +00:00
/**
* 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;
}
feat: Participants optimisations (#9515) * fix(participants): Change from array to Map * fix(unload): optimise * feat: Introduces new states for e2ee feature. Stores everyoneSupportsE2EE and everyoneEnabledE2EE to minimize looping through participants list. squash: Uses participants map and go over the elements only once. * feat: Optimizes isEveryoneModerator to do less frequent checks in all participants. * fix: Drops deep equal from participants pane and uses the map. * fix(SharedVideo): isVideoPlaying * fix(participants): Optimise isEveryoneModerator * fix(e2e): Optimise everyoneEnabledE2EE * fix: JS errors. * ref(participants): remove getParticipants * fix(participants): Prepare for PR. * fix: Changes participants pane to be component. The functional component was always rendered: `prev props: {} !== {} :next props`. * feat: Optimization to skip participants list on pane closed. * fix: The participants list shows and the local participant. * fix: Fix wrong action name for av-moderation. * fix: Minimizes the number of render calls of av moderation notification. * fix: Fix iterating over remote participants. * fix: Fixes lint error. * fix: Reflects participant updates for av-moderation. * fix(ParticipantPane): to work with IDs. * fix(av-moderation): on PARTCIPANT_UPDATE * fix(ParticipantPane): close delay. * fix: address code review comments * fix(API): mute-everyone * fix: bugs * fix(Thumbnail): on mobile. * fix(ParticipantPane): Close context menu on click. * fix: Handles few error when local participant is undefined. * feat: Hides AV moderation if not supported. * fix: Show mute all video. * fix: Fixes updating participant for av moderation. Co-authored-by: damencho <damencho@jitsi.org>
2021-07-09 12:36:19 +00:00
const participants = getRemoteParticipants(state);
const participantCount = getParticipantCount(state);
let numberOfPoltergeists = 0;
participants.forEach(p => {
if (p.botType === 'poltergeist') {
numberOfPoltergeists++;
}
});
const numberOfRealParticipants = participantCount - numberOfPoltergeists;
2018-06-26 22:56:22 +00:00
if ((numberOfPoltergeists > 1 || numberOfRealParticipants > 1)
feat: Participants optimisations (#9515) * fix(participants): Change from array to Map * fix(unload): optimise * feat: Introduces new states for e2ee feature. Stores everyoneSupportsE2EE and everyoneEnabledE2EE to minimize looping through participants list. squash: Uses participants map and go over the elements only once. * feat: Optimizes isEveryoneModerator to do less frequent checks in all participants. * fix: Drops deep equal from participants pane and uses the map. * fix(SharedVideo): isVideoPlaying * fix(participants): Optimise isEveryoneModerator * fix(e2e): Optimise everyoneEnabledE2EE * fix: JS errors. * ref(participants): remove getParticipants * fix(participants): Prepare for PR. * fix: Changes participants pane to be component. The functional component was always rendered: `prev props: {} !== {} :next props`. * feat: Optimization to skip participants list on pane closed. * fix: The participants list shows and the local participant. * fix: Fix wrong action name for av-moderation. * fix: Minimizes the number of render calls of av moderation notification. * fix: Fix iterating over remote participants. * fix: Fixes lint error. * fix: Reflects participant updates for av-moderation. * fix(ParticipantPane): to work with IDs. * fix(av-moderation): on PARTCIPANT_UPDATE * fix(ParticipantPane): close delay. * fix: address code review comments * fix(API): mute-everyone * fix: bugs * fix(Thumbnail): on mobile. * fix(ParticipantPane): Close context menu on click. * fix: Handles few error when local participant is undefined. * feat: Hides AV moderation if not supported. * fix: Show mute all video. * fix: Fixes updating participant for av moderation. Co-authored-by: damencho <damencho@jitsi.org>
2021-07-09 12:36:19 +00:00
|| (action.type === PARTICIPANT_LEFT && participantCount === 1)) {
2018-06-26 22:56:22 +00:00
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());
}