選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

actions.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. import { JitsiConferenceEvents } from '../lib-jitsi-meet';
  2. import {
  3. changeParticipantAvatarID,
  4. changeParticipantAvatarURL,
  5. changeParticipantEmail,
  6. dominantSpeakerChanged,
  7. getLocalParticipant,
  8. participantJoined,
  9. participantLeft,
  10. participantRoleChanged
  11. } from '../participants';
  12. import { trackAdded, trackRemoved } from '../tracks';
  13. import {
  14. CONFERENCE_FAILED,
  15. CONFERENCE_JOINED,
  16. CONFERENCE_LEFT,
  17. CONFERENCE_WILL_JOIN,
  18. CONFERENCE_WILL_LEAVE,
  19. LOCK_STATE_CHANGED,
  20. SET_LASTN,
  21. SET_PASSWORD,
  22. SET_ROOM
  23. } from './actionTypes';
  24. import {
  25. AVATAR_ID_COMMAND,
  26. AVATAR_URL_COMMAND,
  27. EMAIL_COMMAND
  28. } from './constants';
  29. import { _addLocalTracksToConference } from './functions';
  30. import type { Dispatch } from 'redux';
  31. /**
  32. * Adds conference (event) listeners.
  33. *
  34. * @param {JitsiConference} conference - The JitsiConference instance.
  35. * @param {Dispatch} dispatch - The Redux dispatch function.
  36. * @private
  37. * @returns {void}
  38. */
  39. function _addConferenceListeners(conference, dispatch) {
  40. conference.on(
  41. JitsiConferenceEvents.CONFERENCE_FAILED,
  42. (...args) => dispatch(conferenceFailed(conference, ...args)));
  43. conference.on(
  44. JitsiConferenceEvents.CONFERENCE_JOINED,
  45. (...args) => dispatch(conferenceJoined(conference, ...args)));
  46. conference.on(
  47. JitsiConferenceEvents.CONFERENCE_LEFT,
  48. (...args) => dispatch(conferenceLeft(conference, ...args)));
  49. conference.on(
  50. JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED,
  51. (...args) => dispatch(dominantSpeakerChanged(...args)));
  52. conference.on(
  53. JitsiConferenceEvents.LOCK_STATE_CHANGED,
  54. (...args) => dispatch(_lockStateChanged(conference, ...args)));
  55. conference.on(
  56. JitsiConferenceEvents.TRACK_ADDED,
  57. t => t && !t.isLocal() && dispatch(trackAdded(t)));
  58. conference.on(
  59. JitsiConferenceEvents.TRACK_REMOVED,
  60. t => t && !t.isLocal() && dispatch(trackRemoved(t)));
  61. conference.on(
  62. JitsiConferenceEvents.USER_JOINED,
  63. (id, user) => dispatch(participantJoined({
  64. id,
  65. name: user.getDisplayName(),
  66. role: user.getRole()
  67. })));
  68. conference.on(
  69. JitsiConferenceEvents.USER_LEFT,
  70. (...args) => dispatch(participantLeft(...args)));
  71. conference.on(
  72. JitsiConferenceEvents.USER_ROLE_CHANGED,
  73. (...args) => dispatch(participantRoleChanged(...args)));
  74. conference.addCommandListener(
  75. AVATAR_ID_COMMAND,
  76. (data, id) => dispatch(changeParticipantAvatarID(id, data.value)));
  77. conference.addCommandListener(
  78. AVATAR_URL_COMMAND,
  79. (data, id) => dispatch(changeParticipantAvatarURL(id, data.value)));
  80. conference.addCommandListener(
  81. EMAIL_COMMAND,
  82. (data, id) => dispatch(changeParticipantEmail(id, data.value)));
  83. }
  84. /**
  85. * Sets the data for the local participant to the conference.
  86. *
  87. * @param {JitsiConference} conference - The JitsiConference instance.
  88. * @param {Object} state - The Redux state.
  89. * @returns {void}
  90. */
  91. function _setLocalParticipantData(conference, state) {
  92. const localParticipant
  93. = getLocalParticipant(state['features/base/participants']);
  94. conference.removeCommand(AVATAR_ID_COMMAND);
  95. conference.sendCommand(AVATAR_ID_COMMAND, {
  96. value: localParticipant.avatarID
  97. });
  98. }
  99. /**
  100. * Signals that a specific conference has failed.
  101. *
  102. * @param {JitsiConference} conference - The JitsiConference that has failed.
  103. * @param {string} error - The error describing/detailing the cause of the
  104. * failure.
  105. * @returns {{
  106. * type: CONFERENCE_FAILED,
  107. * conference: JitsiConference,
  108. * error: string
  109. * }}
  110. * @public
  111. */
  112. export function conferenceFailed(conference, error) {
  113. return {
  114. type: CONFERENCE_FAILED,
  115. conference,
  116. error
  117. };
  118. }
  119. /**
  120. * Attach any pre-existing local media to the conference once the conference has
  121. * been joined.
  122. *
  123. * @param {JitsiConference} conference - The JitsiConference instance which was
  124. * joined by the local participant.
  125. * @returns {Function}
  126. */
  127. export function conferenceJoined(conference) {
  128. return (dispatch, getState) => {
  129. const localTracks
  130. = getState()['features/base/tracks']
  131. .filter(t => t.local)
  132. .map(t => t.jitsiTrack);
  133. if (localTracks.length) {
  134. _addLocalTracksToConference(conference, localTracks);
  135. }
  136. dispatch({
  137. type: CONFERENCE_JOINED,
  138. conference
  139. });
  140. };
  141. }
  142. /**
  143. * Signals that a specific conference has been left.
  144. *
  145. * @param {JitsiConference} conference - The JitsiConference instance which was
  146. * left by the local participant.
  147. * @returns {{
  148. * type: CONFERENCE_LEFT,
  149. * conference: JitsiConference
  150. * }}
  151. */
  152. export function conferenceLeft(conference) {
  153. return {
  154. type: CONFERENCE_LEFT,
  155. conference
  156. };
  157. }
  158. /**
  159. * Signals the intention of the application to have the local participant join a
  160. * conference with a specific room (name). Similar in fashion
  161. * to CONFERENCE_JOINED.
  162. *
  163. * @param {string} room - The room (name) which identifies the conference the
  164. * local participant will (try to) join.
  165. * @returns {{
  166. * type: CONFERENCE_WILL_JOIN,
  167. * room: string
  168. * }}
  169. */
  170. function _conferenceWillJoin(room) {
  171. return {
  172. type: CONFERENCE_WILL_JOIN,
  173. room
  174. };
  175. }
  176. /**
  177. * Signals the intention of the application to have the local participant leave
  178. * a specific conference. Similar in fashion to CONFERENCE_LEFT. Contrary to it
  179. * though, it's not guaranteed because CONFERENCE_LEFT may be triggered by
  180. * lib-jitsi-meet and not the application.
  181. *
  182. * @param {JitsiConference} conference - The JitsiConference instance which will
  183. * be left by the local participant.
  184. * @returns {{
  185. * type: CONFERENCE_LEFT,
  186. * conference: JitsiConference
  187. * }}
  188. */
  189. export function conferenceWillLeave(conference) {
  190. return {
  191. type: CONFERENCE_WILL_LEAVE,
  192. conference
  193. };
  194. }
  195. /**
  196. * Initializes a new conference.
  197. *
  198. * @returns {Function}
  199. */
  200. export function createConference() {
  201. return (dispatch, getState) => {
  202. const state = getState();
  203. const connection = state['features/base/connection'].connection;
  204. if (!connection) {
  205. throw new Error('Cannot create conference without connection');
  206. }
  207. const { password, room } = state['features/base/conference'];
  208. if (typeof room === 'undefined' || room === '') {
  209. throw new Error('Cannot join conference without room name');
  210. }
  211. dispatch(_conferenceWillJoin(room));
  212. // TODO Take options from config.
  213. const conference
  214. = connection.initJitsiConference(
  215. // XXX Lib-jitsi-meet does not accept uppercase letters.
  216. room.toLowerCase(),
  217. {
  218. openSctp: true
  219. // FIXME I tested H.264 from iPhone 6S during a morning
  220. // standup but, unfortunately, the other participants who
  221. // happened to be running the Web app saw only black.
  222. //
  223. // preferH264: true
  224. });
  225. _addConferenceListeners(conference, dispatch);
  226. _setLocalParticipantData(conference, state);
  227. conference.join(password);
  228. };
  229. }
  230. /**
  231. * Signals that the lock state of a specific JitsiConference changed.
  232. *
  233. * @param {JitsiConference} conference - The JitsiConference which had its lock
  234. * state changed.
  235. * @param {boolean} locked - If the specified conference became locked, true;
  236. * otherwise, false.
  237. * @returns {{
  238. * type: LOCK_STATE_CHANGED,
  239. * conference: JitsiConference,
  240. * locked: boolean
  241. * }}
  242. */
  243. function _lockStateChanged(conference, locked) {
  244. return {
  245. type: LOCK_STATE_CHANGED,
  246. conference,
  247. locked
  248. };
  249. }
  250. /**
  251. * Sets the video channel's last N (value) of the current conference. A value of
  252. * undefined shall be used to reset it to the default value.
  253. *
  254. * @param {(number|undefined)} lastN - The last N value to be set.
  255. * @returns {Function}
  256. */
  257. export function setLastN(lastN: ?number) {
  258. return (dispatch: Dispatch<*>, getState: Function) => {
  259. if (typeof lastN === 'undefined') {
  260. const { config } = getState()['features/base/lib-jitsi-meet'];
  261. /* eslint-disable no-param-reassign */
  262. lastN = config.channelLastN;
  263. if (typeof lastN === 'undefined') {
  264. lastN = -1;
  265. }
  266. /* eslint-enable no-param-reassign */
  267. }
  268. dispatch({
  269. type: SET_LASTN,
  270. lastN
  271. });
  272. };
  273. }
  274. /**
  275. * Sets the password to join or lock a specific JitsiConference.
  276. *
  277. * @param {JitsiConference} conference - The JitsiConference which requires a
  278. * password to join or is to be locked with the specified password.
  279. * @param {Function} method - The JitsiConference method of password protection
  280. * such as join or lock.
  281. * @param {string} password - The password with which the specified conference
  282. * is to be joined or locked.
  283. * @returns {Function}
  284. */
  285. export function setPassword(conference, method, password) {
  286. return (dispatch, getState) => {
  287. switch (method) {
  288. case conference.join: {
  289. let state = getState()['features/base/conference'];
  290. // Make sure that the action will set a password for a conference
  291. // that the application wants joined.
  292. if (state.passwordRequired === conference) {
  293. dispatch({
  294. type: SET_PASSWORD,
  295. conference,
  296. method,
  297. password
  298. });
  299. // Join the conference with the newly-set password.
  300. // Make sure that the action did set the password.
  301. state = getState()['features/base/conference'];
  302. if (state.password === password
  303. && !state.passwordRequired
  304. // Make sure that the application still wants the
  305. // conference joined.
  306. && !state.conference) {
  307. method.call(conference, password);
  308. }
  309. }
  310. break;
  311. }
  312. case conference.lock: {
  313. const state = getState()['features/base/conference'];
  314. if (state.conference === conference) {
  315. return (
  316. method.call(conference, password)
  317. .then(() => dispatch({
  318. type: SET_PASSWORD,
  319. conference,
  320. method,
  321. password
  322. })));
  323. }
  324. return Promise.reject();
  325. }
  326. }
  327. };
  328. }
  329. /**
  330. * Sets (the name of) the room of the conference to be joined.
  331. *
  332. * @param {(string|undefined)} room - The name of the room of the conference to
  333. * be joined.
  334. * @returns {{
  335. * type: SET_ROOM,
  336. * room: string
  337. * }}
  338. */
  339. export function setRoom(room) {
  340. return {
  341. type: SET_ROOM,
  342. room
  343. };
  344. }