Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

actions.js 8.2KB

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