Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

actions.any.js 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // @flow
  2. import type { Dispatch } from 'redux';
  3. import { getInviteURL } from '../base/connection';
  4. import { getLocalParticipant, getParticipants } from '../base/participants';
  5. import { inviteVideoRooms } from '../videosipgw';
  6. import {
  7. ADD_PENDING_INVITE_REQUEST,
  8. BEGIN_ADD_PEOPLE,
  9. HIDE_ADD_PEOPLE_DIALOG,
  10. REMOVE_PENDING_INVITE_REQUESTS,
  11. SET_CALLEE_INFO_VISIBLE,
  12. UPDATE_DIAL_IN_NUMBERS_FAILED,
  13. UPDATE_DIAL_IN_NUMBERS_SUCCESS
  14. } from './actionTypes';
  15. import {
  16. getDialInConferenceID,
  17. getDialInNumbers,
  18. invitePeopleAndChatRooms,
  19. inviteSipEndpoints
  20. } from './functions';
  21. import logger from './logger';
  22. /**
  23. * Creates a (redux) action to signal that a click/tap has been performed on
  24. * {@link InviteButton} and that the execution flow for adding/inviting people
  25. * to the current conference/meeting is to begin.
  26. *
  27. * @returns {{
  28. * type: BEGIN_ADD_PEOPLE
  29. * }}
  30. */
  31. export function beginAddPeople() {
  32. return {
  33. type: BEGIN_ADD_PEOPLE
  34. };
  35. }
  36. /**
  37. * Creates a (redux) action to signal that the {@code AddPeopleDialog}
  38. * should close.
  39. *
  40. * @returns {{
  41. * type: HIDE_ADD_PEOPLE_DIALOG
  42. * }}
  43. */
  44. export function hideAddPeopleDialog() {
  45. return {
  46. type: HIDE_ADD_PEOPLE_DIALOG
  47. };
  48. }
  49. /**
  50. * Invites (i.e. Sends invites to) an array of invitees (which may be a
  51. * combination of users, rooms, phone numbers, and video rooms.
  52. *
  53. * @param {Array<Object>} invitees - The recipients to send invites to.
  54. * @param {Array<Object>} showCalleeInfo - Indicates whether the
  55. * {@code CalleeInfo} should be displayed or not.
  56. * @returns {Promise<Array<Object>>} A {@code Promise} resolving with an array
  57. * of invitees who were not invited (i.e. Invites were not sent to them).
  58. */
  59. export function invite(
  60. invitees: Array<Object>,
  61. showCalleeInfo: boolean = false) {
  62. return (
  63. dispatch: Dispatch<any>,
  64. getState: Function): Promise<Array<Object>> => {
  65. const state = getState();
  66. const participants = getParticipants(state);
  67. const { calleeInfoVisible } = state['features/invite'];
  68. if (showCalleeInfo
  69. && !calleeInfoVisible
  70. && invitees.length === 1
  71. && invitees[0].type === 'user'
  72. && participants.length === 1) {
  73. dispatch(setCalleeInfoVisible(true, invitees[0]));
  74. }
  75. const { conference, password } = state['features/base/conference'];
  76. if (typeof conference === 'undefined') {
  77. // Invite will fail before CONFERENCE_JOIN. The request will be
  78. // cached in order to be executed on CONFERENCE_JOIN.
  79. return new Promise(resolve => {
  80. dispatch(addPendingInviteRequest({
  81. invitees,
  82. callback: failedInvitees => resolve(failedInvitees)
  83. }));
  84. });
  85. }
  86. let allInvitePromises = [];
  87. let invitesLeftToSend = [ ...invitees ];
  88. const {
  89. callFlowsEnabled,
  90. inviteServiceUrl,
  91. inviteServiceCallFlowsUrl
  92. } = state['features/base/config'];
  93. const inviteUrl = getInviteURL(state);
  94. const { sipInviteUrl } = state['features/base/config'];
  95. const { locationURL } = state['features/base/connection'];
  96. const { jwt } = state['features/base/jwt'];
  97. const { name: displayName } = getLocalParticipant(state);
  98. // First create all promises for dialing out.
  99. const phoneNumbers
  100. = invitesLeftToSend.filter(({ type }) => type === 'phone');
  101. // For each number, dial out. On success, remove the number from
  102. // {@link invitesLeftToSend}.
  103. const phoneInvitePromises = phoneNumbers.map(item => {
  104. const numberToInvite = item.number;
  105. return conference.dial(numberToInvite)
  106. .then(() => {
  107. invitesLeftToSend
  108. = invitesLeftToSend.filter(
  109. invitee => invitee !== item);
  110. })
  111. .catch(error =>
  112. logger.error('Error inviting phone number:', error));
  113. });
  114. allInvitePromises = allInvitePromises.concat(phoneInvitePromises);
  115. const usersAndRooms
  116. = invitesLeftToSend.filter(
  117. ({ type }) => type === 'user' || type === 'room');
  118. if (usersAndRooms.length) {
  119. // Send a request to invite all the rooms and users. On success,
  120. // filter all rooms and users from {@link invitesLeftToSend}.
  121. const peopleInvitePromise
  122. = invitePeopleAndChatRooms(
  123. callFlowsEnabled
  124. ? inviteServiceCallFlowsUrl : inviteServiceUrl,
  125. inviteUrl,
  126. jwt,
  127. usersAndRooms)
  128. .then(() => {
  129. invitesLeftToSend
  130. = invitesLeftToSend.filter(
  131. ({ type }) => type !== 'user' && type !== 'room');
  132. })
  133. .catch(error => {
  134. dispatch(setCalleeInfoVisible(false));
  135. logger.error('Error inviting people:', error);
  136. });
  137. allInvitePromises.push(peopleInvitePromise);
  138. }
  139. // Sipgw calls are fire and forget. Invite them to the conference, then
  140. // immediately remove them from invitesLeftToSend.
  141. const vrooms
  142. = invitesLeftToSend.filter(({ type }) => type === 'videosipgw');
  143. conference
  144. && vrooms.length > 0
  145. && dispatch(inviteVideoRooms(conference, vrooms));
  146. invitesLeftToSend
  147. = invitesLeftToSend.filter(({ type }) => type !== 'videosipgw');
  148. const sipEndpoints
  149. = invitesLeftToSend.filter(({ type }) => type === 'sip');
  150. conference && inviteSipEndpoints(
  151. sipEndpoints,
  152. locationURL,
  153. sipInviteUrl,
  154. jwt,
  155. conference.options.name,
  156. password,
  157. displayName
  158. );
  159. invitesLeftToSend
  160. = invitesLeftToSend.filter(({ type }) => type !== 'sip');
  161. return (
  162. Promise.all(allInvitePromises)
  163. .then(() => invitesLeftToSend));
  164. };
  165. }
  166. /**
  167. * Sends AJAX requests for dial-in numbers and conference ID.
  168. *
  169. * @returns {Function}
  170. */
  171. export function updateDialInNumbers() {
  172. return (dispatch: Dispatch<any>, getState: Function) => {
  173. const state = getState();
  174. const { dialInConfCodeUrl, dialInNumbersUrl, hosts }
  175. = state['features/base/config'];
  176. const { numbersFetched } = state['features/invite'];
  177. const mucURL = hosts && hosts.muc;
  178. if (numbersFetched || !dialInConfCodeUrl || !dialInNumbersUrl || !mucURL) {
  179. // URLs for fetching dial in numbers not defined
  180. return;
  181. }
  182. const { room } = state['features/base/conference'];
  183. Promise.all([
  184. getDialInNumbers(dialInNumbersUrl, room, mucURL),
  185. getDialInConferenceID(dialInConfCodeUrl, room, mucURL)
  186. ])
  187. .then(([ dialInNumbers, { conference, id, message } ]) => {
  188. if (!conference || !id) {
  189. return Promise.reject(message);
  190. }
  191. dispatch({
  192. type: UPDATE_DIAL_IN_NUMBERS_SUCCESS,
  193. conferenceID: id,
  194. dialInNumbers
  195. });
  196. })
  197. .catch(error => {
  198. dispatch({
  199. type: UPDATE_DIAL_IN_NUMBERS_FAILED,
  200. error
  201. });
  202. });
  203. };
  204. }
  205. /**
  206. * Sets the visibility of {@code CalleeInfo}.
  207. *
  208. * @param {boolean|undefined} [calleeInfoVisible] - If {@code CalleeInfo} is
  209. * to be displayed/visible, then {@code true}; otherwise, {@code false} or
  210. * {@code undefined}.
  211. * @param {Object|undefined} [initialCalleeInfo] - Callee information.
  212. * @returns {{
  213. * type: SET_CALLEE_INFO_VISIBLE,
  214. * calleeInfoVisible: (boolean|undefined),
  215. * initialCalleeInfo
  216. * }}
  217. */
  218. export function setCalleeInfoVisible(
  219. calleeInfoVisible: boolean,
  220. initialCalleeInfo: ?Object) {
  221. return {
  222. type: SET_CALLEE_INFO_VISIBLE,
  223. calleeInfoVisible,
  224. initialCalleeInfo
  225. };
  226. }
  227. /**
  228. * Adds pending invite request.
  229. *
  230. * @param {Object} request - The request.
  231. * @returns {{
  232. * type: ADD_PENDING_INVITE_REQUEST,
  233. * request: Object
  234. * }}
  235. */
  236. export function addPendingInviteRequest(
  237. request: { invitees: Array<Object>, callback: Function }) {
  238. return {
  239. type: ADD_PENDING_INVITE_REQUEST,
  240. request
  241. };
  242. }
  243. /**
  244. * Removes all pending invite requests.
  245. *
  246. * @returns {{
  247. * type: REMOVE_PENDING_INVITE_REQUEST
  248. * }}
  249. */
  250. export function removePendingInviteRequests() {
  251. return {
  252. type: REMOVE_PENDING_INVITE_REQUESTS
  253. };
  254. }