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

middleware.native.js 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // @flow
  2. import i18next from 'i18next';
  3. import { NativeEventEmitter, NativeModules } from 'react-native';
  4. import { MiddlewareRegistry } from '../base/redux';
  5. import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app';
  6. import { getInviteURL } from '../base/connection';
  7. import { inviteVideoRooms } from '../videosipgw';
  8. import {
  9. BEGIN_ADD_PEOPLE,
  10. _SET_EMITTER_SUBSCRIPTIONS
  11. } from './actionTypes';
  12. import {
  13. getInviteResultsForQuery,
  14. isAddPeopleEnabled,
  15. isDialOutEnabled,
  16. sendInvitesForItems
  17. } from './functions';
  18. import './middleware.any';
  19. /**
  20. * The react-native module of the feature invite.
  21. */
  22. const { Invite } = NativeModules;
  23. /**
  24. * The middleware of the feature invite specific to mobile/react-native.
  25. *
  26. * @param {Store} store - The redux store.
  27. * @returns {Function}
  28. */
  29. Invite && MiddlewareRegistry.register(store => next => action => {
  30. switch (action.type) {
  31. case _SET_EMITTER_SUBSCRIPTIONS:
  32. return _setEmitterSubscriptions(store, next, action);
  33. case APP_WILL_MOUNT:
  34. return _appWillMount(store, next, action);
  35. case APP_WILL_UNMOUNT: {
  36. const result = next(action);
  37. store.dispatch({
  38. type: _SET_EMITTER_SUBSCRIPTIONS,
  39. emitterSubscriptions: undefined
  40. });
  41. return result;
  42. }
  43. case BEGIN_ADD_PEOPLE:
  44. return _beginAddPeople(store, next, action);
  45. }
  46. return next(action);
  47. });
  48. /**
  49. * Notifies the feature jwt that the action {@link APP_WILL_MOUNT} is being
  50. * dispatched within a specific redux {@code store}.
  51. *
  52. * @param {Store} store - The redux store in which the specified {@code action}
  53. * is being dispatched.
  54. * @param {Dispatch} next - The redux dispatch function to dispatch the
  55. * specified {@code action} to the specified {@code store}.
  56. * @param {Action} action - The redux action {@code APP_WILL_MOUNT} which is
  57. * being dispatched in the specified {@code store}.
  58. * @private
  59. * @returns {*} The value returned by {@code next(action)}.
  60. */
  61. function _appWillMount({ dispatch, getState }, next, action) {
  62. const result = next(action);
  63. const emitter = new NativeEventEmitter(Invite);
  64. const context = {
  65. dispatch,
  66. getState
  67. };
  68. dispatch({
  69. type: _SET_EMITTER_SUBSCRIPTIONS,
  70. emitterSubscriptions: [
  71. emitter.addListener(
  72. 'org.jitsi.meet:features/invite#invite',
  73. _onInvite,
  74. context),
  75. emitter.addListener(
  76. 'org.jitsi.meet:features/invite#performQuery',
  77. _onPerformQuery,
  78. context)
  79. ]
  80. });
  81. return result;
  82. }
  83. /**
  84. * Notifies the feature invite that the action {@link BEGIN_ADD_PEOPLE} is being
  85. * dispatched within a specific redux {@code store}.
  86. *
  87. * @param {Store} store - The redux store in which the specified {@code action}
  88. * is being dispatched.
  89. * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
  90. * specified {@code action} to the specified {@code store}.
  91. * @param {Action} action - The redux action {@code BEGIN_ADD_PEOPLE} which is
  92. * being dispatched in the specified {@code store}.
  93. * @private
  94. * @returns {*} The value returned by {@code next(action)}.
  95. */
  96. function _beginAddPeople({ getState }, next, action) {
  97. const result = next(action);
  98. // The JavaScript App needs to provide uniquely identifying information to
  99. // the native Invite module so that the latter may match the former to the
  100. // native JitsiMeetView which hosts it.
  101. const { app } = getState()['features/app'];
  102. if (app) {
  103. const { externalAPIScope } = app.props;
  104. if (externalAPIScope) {
  105. Invite.beginAddPeople(externalAPIScope);
  106. }
  107. }
  108. return result;
  109. }
  110. /**
  111. * Handles the {@code invite} event of the feature invite i.e. invites specific
  112. * invitees to the current, ongoing conference.
  113. *
  114. * @param {Object} event - The details of the event.
  115. * @returns {void}
  116. */
  117. function _onInvite(
  118. { addPeopleControllerScope, externalAPIScope, invitees }) {
  119. const { getState } = this; // eslint-disable-line no-invalid-this
  120. const state = getState();
  121. // If there are multiple JitsiMeetView instances alive, they will all get
  122. // the event, since there is a single bridge, so make sure we don't act if
  123. // the event is not for us.
  124. if (state['features/app'].app.props.externalAPIScope !== externalAPIScope) {
  125. return;
  126. }
  127. const { conference } = state['features/base/conference'];
  128. const { inviteServiceUrl } = state['features/base/config'];
  129. const options = {
  130. conference,
  131. inviteServiceUrl,
  132. inviteUrl: getInviteURL(state),
  133. inviteVideoRooms,
  134. jwt: state['features/base/jwt'].jwt
  135. };
  136. sendInvitesForItems(invitees, options)
  137. .then(failedInvitees =>
  138. Invite.inviteSettled(
  139. externalAPIScope,
  140. addPeopleControllerScope,
  141. failedInvitees));
  142. }
  143. /**
  144. * Handles the {@code performQuery} event of the feature invite i.e. queries for
  145. * invitees who may subsequently be invited to the current, ongoing conference.
  146. *
  147. * @param {Object} event - The details of the event.
  148. * @returns {void}
  149. */
  150. function _onPerformQuery(
  151. { addPeopleControllerScope, externalAPIScope, query }) {
  152. const { getState } = this; // eslint-disable-line no-invalid-this
  153. const state = getState();
  154. // If there are multiple JitsiMeetView instances alive, they will all get
  155. // the event, since there is a single bridge, so make sure we don't act if
  156. // the event is not for us.
  157. if (state['features/app'].app.props.externalAPIScope !== externalAPIScope) {
  158. return;
  159. }
  160. const {
  161. dialOutAuthUrl,
  162. peopleSearchQueryTypes,
  163. peopleSearchUrl
  164. } = state['features/base/config'];
  165. const options = {
  166. dialOutAuthUrl,
  167. addPeopleEnabled: isAddPeopleEnabled(state),
  168. dialOutEnabled: isDialOutEnabled(state),
  169. jwt: state['features/base/jwt'].jwt,
  170. peopleSearchQueryTypes,
  171. peopleSearchUrl
  172. };
  173. getInviteResultsForQuery(query, options)
  174. .catch(() => [])
  175. .then(results => {
  176. const translatedResults = results.map(result => {
  177. if (result.type === 'phone') {
  178. result.title = i18next.t('addPeople.telephone', {
  179. number: result.number
  180. });
  181. if (result.showCountryCodeReminder) {
  182. result.subtitle = i18next.t(
  183. 'addPeople.countryReminder'
  184. );
  185. }
  186. }
  187. return result;
  188. }).filter(result => result.type !== 'phone' || result.allowed);
  189. Invite.receivedResults(
  190. externalAPIScope,
  191. addPeopleControllerScope,
  192. query,
  193. translatedResults);
  194. });
  195. }
  196. /**
  197. * Notifies the feature invite that the action
  198. * {@link _SET_EMITTER_SUBSCRIPTIONS} is being dispatched within a specific
  199. * redux {@code store}.
  200. *
  201. * @param {Store} store - The redux store in which the specified {@code action}
  202. * is being dispatched.
  203. * @param {Dispatch} next - The redux dispatch function to dispatch the
  204. * specified {@code action} to the specified {@code store}.
  205. * @param {Action} action - The redux action {@code _SET_EMITTER_SUBSCRIPTIONS}
  206. * which is being dispatched in the specified {@code store}.
  207. * @private
  208. * @returns {*}
  209. */
  210. function _setEmitterSubscriptions({ getState }, next, action) {
  211. const { emitterSubscriptions } = getState()['features/invite'];
  212. if (emitterSubscriptions) {
  213. for (const subscription of emitterSubscriptions) {
  214. subscription.remove();
  215. }
  216. }
  217. return next(action);
  218. }