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

291 lines
9.1 KiB
JavaScript
Raw Normal View History

// @flow
2019-03-19 15:42:25 +00:00
import type { Dispatch } from 'redux';
import { getInviteURL } from '../base/connection';
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
import { getLocalParticipant, getParticipantCount } from '../base/participants';
import { inviteVideoRooms } from '../videosipgw';
import { getDialInConferenceID, getDialInNumbers } from './_utils';
import {
2018-06-26 22:56:22 +00:00
ADD_PENDING_INVITE_REQUEST,
BEGIN_ADD_PEOPLE,
HIDE_ADD_PEOPLE_DIALOG,
2018-06-26 22:56:22 +00:00
REMOVE_PENDING_INVITE_REQUESTS,
SET_CALLEE_INFO_VISIBLE,
UPDATE_DIAL_IN_NUMBERS_FAILED,
UPDATE_DIAL_IN_NUMBERS_SUCCESS
} from './actionTypes';
import { INVITE_TYPES } from './constants';
import {
2021-03-18 13:32:14 +00:00
invitePeopleAndChatRooms,
inviteSipEndpoints
} from './functions';
import logger from './logger';
/**
* Creates a (redux) action to signal that a click/tap has been performed on
* {@link InviteButton} and that the execution flow for adding/inviting people
* to the current conference/meeting is to begin.
*
* @returns {{
* type: BEGIN_ADD_PEOPLE
* }}
*/
export function beginAddPeople() {
return {
type: BEGIN_ADD_PEOPLE
};
}
/**
* Creates a (redux) action to signal that the {@code AddPeopleDialog}
* should close.
*
* @returns {{
* type: HIDE_ADD_PEOPLE_DIALOG
* }}
*/
export function hideAddPeopleDialog() {
return {
type: HIDE_ADD_PEOPLE_DIALOG
};
}
2018-06-26 22:56:22 +00:00
/**
* Invites (i.e. Sends invites to) an array of invitees (which may be a
* combination of users, rooms, phone numbers, and video rooms.
*
* @param {Array<Object>} invitees - The recipients to send invites to.
2018-06-26 22:56:22 +00:00
* @param {Array<Object>} showCalleeInfo - Indicates whether the
* {@code CalleeInfo} should be displayed or not.
* @returns {Promise<Array<Object>>} A {@code Promise} resolving with an array
* of invitees who were not invited (i.e. Invites were not sent to them).
*/
2018-06-26 22:56:22 +00:00
export function invite(
invitees: Array<Object>,
showCalleeInfo: boolean = false) {
return (
2019-03-19 15:42:25 +00:00
dispatch: Dispatch<any>,
getState: Function): Promise<Array<Object>> => {
2018-06-26 22:56:22 +00:00
const state = getState();
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 participantsCount = getParticipantCount(state);
2018-06-26 22:56:22 +00:00
const { calleeInfoVisible } = state['features/invite'];
if (showCalleeInfo
&& !calleeInfoVisible
&& invitees.length === 1
&& invitees[0].type === INVITE_TYPES.USER
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
&& participantsCount === 1) {
2018-06-26 22:56:22 +00:00
dispatch(setCalleeInfoVisible(true, invitees[0]));
}
const { conference, password } = state['features/base/conference'];
2018-06-26 22:56:22 +00:00
if (typeof conference === 'undefined') {
// Invite will fail before CONFERENCE_JOIN. The request will be
// cached in order to be executed on CONFERENCE_JOIN.
return new Promise(resolve => {
dispatch(addPendingInviteRequest({
invitees,
callback: failedInvitees => resolve(failedInvitees)
}));
});
}
let allInvitePromises = [];
let invitesLeftToSend = [ ...invitees ];
const {
callFlowsEnabled,
inviteServiceUrl,
inviteServiceCallFlowsUrl
} = state['features/base/config'];
const inviteUrl = getInviteURL(state);
2021-03-18 13:32:14 +00:00
const { sipInviteUrl } = state['features/base/config'];
2021-04-07 12:46:01 +00:00
const { locationURL } = state['features/base/connection'];
const { jwt } = state['features/base/jwt'];
2021-03-18 13:32:14 +00:00
const { name: displayName } = getLocalParticipant(state);
// First create all promises for dialing out.
2018-06-26 22:56:22 +00:00
const phoneNumbers
= invitesLeftToSend.filter(({ type }) => type === INVITE_TYPES.PHONE);
2018-06-26 22:56:22 +00:00
// For each number, dial out. On success, remove the number from
// {@link invitesLeftToSend}.
const phoneInvitePromises = phoneNumbers.map(item => {
const numberToInvite = item.number;
return conference.dial(numberToInvite)
.then(() => {
invitesLeftToSend
= invitesLeftToSend.filter(
invitee => invitee !== item);
})
.catch(error =>
logger.error('Error inviting phone number:', error));
});
allInvitePromises = allInvitePromises.concat(phoneInvitePromises);
const usersAndRooms
= invitesLeftToSend.filter(
({ type }) => [ INVITE_TYPES.USER, INVITE_TYPES.ROOM ].includes(type));
if (usersAndRooms.length) {
// Send a request to invite all the rooms and users. On success,
// filter all rooms and users from {@link invitesLeftToSend}.
const peopleInvitePromise
= invitePeopleAndChatRooms(
callFlowsEnabled
? inviteServiceCallFlowsUrl : inviteServiceUrl,
inviteUrl,
jwt,
usersAndRooms)
.then(() => {
invitesLeftToSend
= invitesLeftToSend.filter(
({ type }) => ![ INVITE_TYPES.USER, INVITE_TYPES.ROOM ].includes(type));
})
2018-06-26 22:56:22 +00:00
.catch(error => {
dispatch(setCalleeInfoVisible(false));
logger.error('Error inviting people:', error);
});
allInvitePromises.push(peopleInvitePromise);
}
// Sipgw calls are fire and forget. Invite them to the conference, then
// immediately remove them from invitesLeftToSend.
const vrooms
= invitesLeftToSend.filter(({ type }) => type === INVITE_TYPES.VIDEO_ROOM);
conference
&& vrooms.length > 0
&& dispatch(inviteVideoRooms(conference, vrooms));
invitesLeftToSend
= invitesLeftToSend.filter(({ type }) => type !== INVITE_TYPES.VIDEO_ROOM);
2021-03-18 13:32:14 +00:00
const sipEndpoints
= invitesLeftToSend.filter(({ type }) => type === INVITE_TYPES.SIP);
2021-03-18 13:32:14 +00:00
conference && inviteSipEndpoints(
sipEndpoints,
2021-04-07 12:46:01 +00:00
locationURL,
2021-03-18 13:32:14 +00:00
sipInviteUrl,
jwt,
conference.options.name,
password,
2021-03-18 13:32:14 +00:00
displayName
);
invitesLeftToSend
= invitesLeftToSend.filter(({ type }) => type !== INVITE_TYPES.SIP);
2021-03-18 13:32:14 +00:00
return (
Promise.all(allInvitePromises)
.then(() => invitesLeftToSend));
};
}
/**
* Sends AJAX requests for dial-in numbers and conference ID.
*
* @returns {Function}
*/
export function updateDialInNumbers() {
2019-03-19 15:42:25 +00:00
return (dispatch: Dispatch<any>, getState: Function) => {
const state = getState();
const { dialInConfCodeUrl, dialInNumbersUrl, hosts }
= state['features/base/config'];
const { numbersFetched } = state['features/invite'];
const mucURL = hosts && hosts.muc;
if (numbersFetched || !dialInConfCodeUrl || !dialInNumbersUrl || !mucURL) {
// URLs for fetching dial in numbers not defined
return;
}
const { locationURL = {} } = state['features/base/connection'];
const { room } = state['features/base/conference'];
Promise.all([
getDialInNumbers(dialInNumbersUrl, room, mucURL),
getDialInConferenceID(dialInConfCodeUrl, room, mucURL, locationURL)
])
.then(([ dialInNumbers, { conference, id, message, sipUri } ]) => {
if (!conference || !id) {
return Promise.reject(message);
}
dispatch({
type: UPDATE_DIAL_IN_NUMBERS_SUCCESS,
conferenceID: id,
dialInNumbers,
sipUri
});
})
.catch(error => {
dispatch({
type: UPDATE_DIAL_IN_NUMBERS_FAILED,
error
});
});
};
}
2018-06-26 22:56:22 +00:00
/**
* Sets the visibility of {@code CalleeInfo}.
*
* @param {boolean|undefined} [calleeInfoVisible] - If {@code CalleeInfo} is
* to be displayed/visible, then {@code true}; otherwise, {@code false} or
* {@code undefined}.
* @param {Object|undefined} [initialCalleeInfo] - Callee information.
* @returns {{
* type: SET_CALLEE_INFO_VISIBLE,
* calleeInfoVisible: (boolean|undefined),
* initialCalleeInfo
* }}
*/
export function setCalleeInfoVisible(
calleeInfoVisible: boolean,
initialCalleeInfo: ?Object) {
return {
type: SET_CALLEE_INFO_VISIBLE,
calleeInfoVisible,
initialCalleeInfo
};
}
/**
* Adds pending invite request.
*
* @param {Object} request - The request.
* @returns {{
* type: ADD_PENDING_INVITE_REQUEST,
* request: Object
* }}
*/
export function addPendingInviteRequest(
request: { invitees: Array<Object>, callback: Function }) {
return {
type: ADD_PENDING_INVITE_REQUEST,
request
};
}
/**
* Removes all pending invite requests.
*
* @returns {{
* type: REMOVE_PENDING_INVITE_REQUEST
* }}
*/
export function removePendingInviteRequests() {
return {
type: REMOVE_PENDING_INVITE_REQUESTS
};
}