You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

actions.native.js 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /* @flow */
  2. import _ from 'lodash';
  3. import type { Dispatch } from 'redux';
  4. import { conferenceWillLeave } from '../conference';
  5. import JitsiMeetJS, { JitsiConnectionEvents } from '../lib-jitsi-meet';
  6. import { parseStandardURIString } from '../util';
  7. import {
  8. CONNECTION_DISCONNECTED,
  9. CONNECTION_ESTABLISHED,
  10. CONNECTION_FAILED,
  11. CONNECTION_WILL_CONNECT,
  12. SET_LOCATION_URL
  13. } from './actionTypes';
  14. /**
  15. * Opens new connection.
  16. *
  17. * @returns {Function}
  18. */
  19. export function connect() {
  20. return (dispatch: Dispatch<*>, getState: Function) => {
  21. const state = getState();
  22. const options = _constructOptions(state);
  23. const { issuer, jwt } = state['features/jwt'];
  24. const connection
  25. = new JitsiMeetJS.JitsiConnection(
  26. options.appId,
  27. jwt && issuer && issuer !== 'anonymous' ? jwt : undefined,
  28. options);
  29. dispatch(_connectionWillConnect(connection));
  30. connection.addEventListener(
  31. JitsiConnectionEvents.CONNECTION_DISCONNECTED,
  32. _onConnectionDisconnected);
  33. connection.addEventListener(
  34. JitsiConnectionEvents.CONNECTION_ESTABLISHED,
  35. _onConnectionEstablished);
  36. connection.addEventListener(
  37. JitsiConnectionEvents.CONNECTION_FAILED,
  38. _onConnectionFailed);
  39. connection.connect();
  40. /**
  41. * Dispatches CONNECTION_DISCONNECTED action when connection is
  42. * disconnected.
  43. *
  44. * @param {string} message - Disconnect reason.
  45. * @returns {void}
  46. * @private
  47. */
  48. function _onConnectionDisconnected(message: string) {
  49. connection.removeEventListener(
  50. JitsiConnectionEvents.CONNECTION_DISCONNECTED,
  51. _onConnectionDisconnected);
  52. dispatch(_connectionDisconnected(connection, message));
  53. }
  54. /**
  55. * Resolves external promise when connection is established.
  56. *
  57. * @returns {void}
  58. * @private
  59. */
  60. function _onConnectionEstablished() {
  61. unsubscribe();
  62. dispatch(connectionEstablished(connection));
  63. }
  64. /**
  65. * Rejects external promise when connection fails.
  66. *
  67. * @param {JitsiConnectionErrors} err - Connection error.
  68. * @returns {void}
  69. * @private
  70. */
  71. function _onConnectionFailed(err) {
  72. unsubscribe();
  73. console.error('CONNECTION FAILED:', err);
  74. dispatch(connectionFailed(connection, err));
  75. }
  76. /**
  77. * Unsubscribes connection instance from CONNECTION_ESTABLISHED
  78. * and CONNECTION_FAILED events.
  79. *
  80. * @returns {void}
  81. */
  82. function unsubscribe() {
  83. connection.removeEventListener(
  84. JitsiConnectionEvents.CONNECTION_ESTABLISHED,
  85. _onConnectionEstablished);
  86. connection.removeEventListener(
  87. JitsiConnectionEvents.CONNECTION_FAILED,
  88. _onConnectionFailed);
  89. }
  90. };
  91. }
  92. /**
  93. * Create an action for when the signaling connection has been lost.
  94. *
  95. * @param {JitsiConnection} connection - The JitsiConnection which disconnected.
  96. * @param {string} message - Error message.
  97. * @private
  98. * @returns {{
  99. * type: CONNECTION_DISCONNECTED,
  100. * connection: JitsiConnection,
  101. * message: string
  102. * }}
  103. */
  104. function _connectionDisconnected(connection: Object, message: string) {
  105. return {
  106. type: CONNECTION_DISCONNECTED,
  107. connection,
  108. message
  109. };
  110. }
  111. /**
  112. * Create an action for when a connection will connect.
  113. *
  114. * @param {JitsiConnection} connection - The JitsiConnection which will connect.
  115. * @private
  116. * @returns {{
  117. * type: CONNECTION_WILL_CONNECT,
  118. * connection: JitsiConnection
  119. * }}
  120. */
  121. function _connectionWillConnect(connection) {
  122. return {
  123. type: CONNECTION_WILL_CONNECT,
  124. connection
  125. };
  126. }
  127. /**
  128. * Create an action for when the signaling connection has been established.
  129. *
  130. * @param {JitsiConnection} connection - The JitsiConnection which was
  131. * established.
  132. * @public
  133. * @returns {{
  134. * type: CONNECTION_ESTABLISHED,
  135. * connection: JitsiConnection
  136. * }}
  137. */
  138. export function connectionEstablished(connection: Object) {
  139. return {
  140. type: CONNECTION_ESTABLISHED,
  141. connection
  142. };
  143. }
  144. /**
  145. * Create an action for when the signaling connection could not be created.
  146. *
  147. * @param {JitsiConnection} connection - The JitsiConnection which failed.
  148. * @param {string} error - Error.
  149. * @param {string} message - Error message.
  150. * @public
  151. * @returns {{
  152. * type: CONNECTION_FAILED,
  153. * connection: JitsiConnection,
  154. * error: string,
  155. * message: string
  156. * }}
  157. */
  158. export function connectionFailed(
  159. connection: Object,
  160. error: string,
  161. message: ?string) {
  162. return {
  163. type: CONNECTION_FAILED,
  164. connection,
  165. error,
  166. message
  167. };
  168. }
  169. /**
  170. * Constructs options to be passed to the constructor of {@code JitsiConnection}
  171. * based on the redux state.
  172. *
  173. * @param {Object} state - The redux state.
  174. * @returns {Object} The options to be passed to the constructor of
  175. * {@code JitsiConnection}.
  176. */
  177. function _constructOptions(state) {
  178. const defaultOptions = state['features/base/connection'].options;
  179. const options = _.merge(
  180. {},
  181. defaultOptions,
  182. // Lib-jitsi-meet wants the config passed in multiple places and here is
  183. // the latest one I have discovered.
  184. state['features/base/config'],
  185. );
  186. let { bosh } = options;
  187. if (bosh) {
  188. // Append room to the URL's search.
  189. const { room } = state['features/base/conference'];
  190. // XXX The Jitsi Meet deployments require the room argument to be in
  191. // lower case at the time of this writing but, unfortunately, they do
  192. // not ignore case themselves.
  193. room && (bosh += `?room=${room.toLowerCase()}`);
  194. // XXX By default, config.js does not add a protocol to the BOSH URL.
  195. // Which trips React Native. Make sure there is a protocol in order to
  196. // satisfy React Native.
  197. if (bosh !== defaultOptions.bosh
  198. && !parseStandardURIString(bosh).protocol) {
  199. const { protocol } = parseStandardURIString(defaultOptions.bosh);
  200. protocol && (bosh = protocol + bosh);
  201. }
  202. options.bosh = bosh;
  203. }
  204. return options;
  205. }
  206. /**
  207. * Closes connection.
  208. *
  209. * @returns {Function}
  210. */
  211. export function disconnect() {
  212. return (dispatch: Dispatch<*>, getState: Function) => {
  213. const state = getState();
  214. const { conference, joining } = state['features/base/conference'];
  215. // The conference we are joining or have already joined.
  216. const conference_ = conference || joining;
  217. // Promise which completes when the conference has been left and the
  218. // connection has been disconnected.
  219. let promise;
  220. // Leave the conference.
  221. if (conference_) {
  222. // In a fashion similar to JitsiConference's CONFERENCE_LEFT event
  223. // (and the respective Redux action) which is fired after the
  224. // conference has been left, notify the application about the
  225. // intention to leave the conference.
  226. dispatch(conferenceWillLeave(conference_));
  227. promise = conference_.leave();
  228. } else {
  229. promise = Promise.resolve();
  230. }
  231. // Disconnect the connection.
  232. const { connecting, connection } = state['features/base/connection'];
  233. // The connection we are connecting or have already connected.
  234. const connection_ = connection || connecting;
  235. if (connection_) {
  236. promise = promise.then(() => connection_.disconnect());
  237. }
  238. return promise;
  239. };
  240. }
  241. /**
  242. * Sets the location URL of the application, connecton, conference, etc.
  243. *
  244. * @param {URL} [locationURL] - The location URL of the application,
  245. * connection, conference, etc.
  246. * @returns {{
  247. * type: SET_LOCATION_URL,
  248. * locationURL: URL
  249. * }}
  250. */
  251. export function setLocationURL(locationURL: ?URL) {
  252. return {
  253. type: SET_LOCATION_URL,
  254. locationURL
  255. };
  256. }