您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

actions.any.js 7.8KB

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