2017-10-03 19:24:00 +00:00
|
|
|
// @flow
|
|
|
|
|
2019-03-19 15:42:25 +00:00
|
|
|
import type { Dispatch } from 'redux';
|
|
|
|
|
2018-04-25 11:06:46 +00:00
|
|
|
import { getInviteURL } from '../base/connection';
|
|
|
|
import { inviteVideoRooms } from '../videosipgw';
|
2018-06-26 22:56:22 +00:00
|
|
|
import { getParticipants } from '../base/participants';
|
2018-04-25 11:06:46 +00:00
|
|
|
|
2017-04-20 23:28:03 +00:00
|
|
|
import {
|
2018-06-26 22:56:22 +00:00
|
|
|
ADD_PENDING_INVITE_REQUEST,
|
2018-05-01 04:43:47 +00:00
|
|
|
BEGIN_ADD_PEOPLE,
|
2018-06-26 22:56:22 +00:00
|
|
|
REMOVE_PENDING_INVITE_REQUESTS,
|
|
|
|
SET_CALLEE_INFO_VISIBLE,
|
2019-02-26 10:41:57 +00:00
|
|
|
SET_INVITE_DIALOG_VISIBLE,
|
2017-04-20 23:28:03 +00:00
|
|
|
UPDATE_DIAL_IN_NUMBERS_FAILED,
|
|
|
|
UPDATE_DIAL_IN_NUMBERS_SUCCESS
|
|
|
|
} from './actionTypes';
|
2018-04-25 11:06:46 +00:00
|
|
|
import {
|
|
|
|
getDialInConferenceID,
|
|
|
|
getDialInNumbers,
|
|
|
|
invitePeopleAndChatRooms
|
|
|
|
} from './functions';
|
|
|
|
|
|
|
|
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
2017-05-16 19:19:30 +00:00
|
|
|
|
2018-05-01 04:43:47 +00:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-06-26 22:56:22 +00:00
|
|
|
|
2017-04-20 23:28:03 +00:00
|
|
|
/**
|
2018-11-08 12:25:02 +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.
|
2018-04-25 11:06:46 +00:00
|
|
|
*
|
2018-05-03 01:20:31 +00:00
|
|
|
* @param {Array<Object>} invitees - The recepients 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.
|
2018-05-03 01:20:31 +00:00
|
|
|
* @returns {Promise<Array<Object>>} A {@code Promise} resolving with an array
|
2018-11-08 12:25:02 +00:00
|
|
|
* of invitees who were not invited (i.e. Invites were not sent to them).
|
2018-04-25 11:06:46 +00:00
|
|
|
*/
|
2018-06-26 22:56:22 +00:00
|
|
|
export function invite(
|
|
|
|
invitees: Array<Object>,
|
|
|
|
showCalleeInfo: boolean = false) {
|
2018-04-25 11:06:46 +00:00
|
|
|
return (
|
2019-03-19 15:42:25 +00:00
|
|
|
dispatch: Dispatch<any>,
|
2018-04-25 11:06:46 +00:00
|
|
|
getState: Function): Promise<Array<Object>> => {
|
2018-06-26 22:56:22 +00:00
|
|
|
const state = getState();
|
|
|
|
const participants = getParticipants(state);
|
|
|
|
const { calleeInfoVisible } = state['features/invite'];
|
|
|
|
|
|
|
|
if (showCalleeInfo
|
|
|
|
&& !calleeInfoVisible
|
|
|
|
&& invitees.length === 1
|
|
|
|
&& invitees[0].type === 'user'
|
|
|
|
&& participants.length === 1) {
|
|
|
|
dispatch(setCalleeInfoVisible(true, invitees[0]));
|
|
|
|
}
|
|
|
|
|
|
|
|
const { conference } = state['features/base/conference'];
|
|
|
|
|
|
|
|
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)
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-04-25 11:06:46 +00:00
|
|
|
let allInvitePromises = [];
|
2018-05-03 01:20:31 +00:00
|
|
|
let invitesLeftToSend = [ ...invitees ];
|
|
|
|
|
2018-05-23 21:52:44 +00:00
|
|
|
const {
|
|
|
|
callFlowsEnabled,
|
|
|
|
inviteServiceUrl,
|
|
|
|
inviteServiceCallFlowsUrl
|
|
|
|
} = state['features/base/config'];
|
2018-04-25 11:06:46 +00:00
|
|
|
const inviteUrl = getInviteURL(state);
|
2018-05-03 01:20:31 +00:00
|
|
|
const { jwt } = state['features/base/jwt'];
|
2018-04-25 11:06:46 +00:00
|
|
|
|
|
|
|
// First create all promises for dialing out.
|
2018-06-26 22:56:22 +00:00
|
|
|
const phoneNumbers
|
|
|
|
= invitesLeftToSend.filter(({ type }) => type === 'phone');
|
2018-04-25 11:06:46 +00:00
|
|
|
|
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);
|
2018-04-25 11:06:46 +00:00
|
|
|
|
2018-05-03 01:20:31 +00:00
|
|
|
const usersAndRooms
|
|
|
|
= invitesLeftToSend.filter(
|
|
|
|
({ type }) => type === 'user' || type === 'room');
|
2018-04-25 11:06:46 +00:00
|
|
|
|
|
|
|
if (usersAndRooms.length) {
|
|
|
|
// Send a request to invite all the rooms and users. On success,
|
|
|
|
// filter all rooms and users from {@link invitesLeftToSend}.
|
2018-05-03 01:20:31 +00:00
|
|
|
const peopleInvitePromise
|
|
|
|
= invitePeopleAndChatRooms(
|
2018-05-23 21:52:44 +00:00
|
|
|
callFlowsEnabled
|
|
|
|
? inviteServiceCallFlowsUrl : inviteServiceUrl,
|
2018-05-03 01:20:31 +00:00
|
|
|
inviteUrl,
|
|
|
|
jwt,
|
|
|
|
usersAndRooms)
|
2018-04-25 11:06:46 +00:00
|
|
|
.then(() => {
|
2018-05-03 01:20:31 +00:00
|
|
|
invitesLeftToSend
|
|
|
|
= invitesLeftToSend.filter(
|
|
|
|
({ type }) => type !== 'user' && type !== 'room');
|
2018-04-25 11:06:46 +00:00
|
|
|
})
|
2018-06-26 22:56:22 +00:00
|
|
|
.catch(error => {
|
|
|
|
dispatch(setCalleeInfoVisible(false));
|
|
|
|
logger.error('Error inviting people:', error);
|
|
|
|
});
|
2018-04-25 11:06:46 +00:00
|
|
|
|
|
|
|
allInvitePromises.push(peopleInvitePromise);
|
|
|
|
}
|
|
|
|
|
2018-05-03 01:20:31 +00:00
|
|
|
// Sipgw calls are fire and forget. Invite them to the conference, then
|
|
|
|
// immediately remove them from invitesLeftToSend.
|
|
|
|
const vrooms
|
|
|
|
= invitesLeftToSend.filter(({ type }) => type === 'videosipgw');
|
2018-04-25 11:06:46 +00:00
|
|
|
|
|
|
|
conference
|
|
|
|
&& vrooms.length > 0
|
|
|
|
&& dispatch(inviteVideoRooms(conference, vrooms));
|
|
|
|
|
2018-05-03 01:20:31 +00:00
|
|
|
invitesLeftToSend
|
|
|
|
= invitesLeftToSend.filter(({ type }) => type !== 'videosipgw');
|
2018-04-25 11:06:46 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
Promise.all(allInvitePromises)
|
2018-05-03 01:20:31 +00:00
|
|
|
.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) => {
|
2018-05-03 01:20:31 +00:00
|
|
|
const state = getState();
|
|
|
|
const { dialInConfCodeUrl, dialInNumbersUrl, hosts }
|
|
|
|
= state['features/base/config'];
|
|
|
|
const mucURL = hosts && hosts.muc;
|
|
|
|
|
|
|
|
if (!dialInConfCodeUrl || !dialInNumbersUrl || !mucURL) {
|
|
|
|
// URLs for fetching dial in numbers not defined
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const { room } = state['features/base/conference'];
|
|
|
|
|
|
|
|
Promise.all([
|
2019-02-02 03:10:34 +00:00
|
|
|
getDialInNumbers(dialInNumbersUrl, room, mucURL),
|
2018-05-03 01:20:31 +00:00
|
|
|
getDialInConferenceID(dialInConfCodeUrl, room, mucURL)
|
|
|
|
])
|
|
|
|
.then(([ dialInNumbers, { conference, id, message } ]) => {
|
|
|
|
if (!conference || !id) {
|
|
|
|
return Promise.reject(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
dispatch({
|
|
|
|
type: UPDATE_DIAL_IN_NUMBERS_SUCCESS,
|
|
|
|
conferenceID: id,
|
|
|
|
dialInNumbers
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
dispatch({
|
|
|
|
type: UPDATE_DIAL_IN_NUMBERS_FAILED,
|
|
|
|
error
|
|
|
|
});
|
|
|
|
});
|
2018-04-25 11:06:46 +00:00
|
|
|
};
|
|
|
|
}
|
2018-06-26 22:56:22 +00:00
|
|
|
|
2019-02-26 10:41:57 +00:00
|
|
|
/**
|
|
|
|
* Sets the visibility of the invite dialog.
|
|
|
|
*
|
|
|
|
* @param {boolean} visible - The visibility to set.
|
|
|
|
* @returns {{
|
|
|
|
* type: SET_INVITE_DIALOG_VISIBLE,
|
|
|
|
* visible: boolean
|
|
|
|
* }}
|
|
|
|
*/
|
|
|
|
export function setAddPeopleDialogVisible(visible: boolean) {
|
|
|
|
return {
|
|
|
|
type: SET_INVITE_DIALOG_VISIBLE,
|
|
|
|
visible
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
};
|
|
|
|
}
|