Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

actions.js 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /* global interfaceConfig */
  2. import throttle from 'lodash/throttle';
  3. import { set } from '../redux';
  4. import { showNotification } from '../../notifications';
  5. import {
  6. DOMINANT_SPEAKER_CHANGED,
  7. KICK_PARTICIPANT,
  8. MUTE_REMOTE_PARTICIPANT,
  9. PARTICIPANT_DISPLAY_NAME_CHANGED,
  10. PARTICIPANT_ID_CHANGED,
  11. PARTICIPANT_JOINED,
  12. PARTICIPANT_LEFT,
  13. PARTICIPANT_UPDATED,
  14. PIN_PARTICIPANT
  15. } from './actionTypes';
  16. import { MAX_DISPLAY_NAME_LENGTH } from './constants';
  17. import { getLocalParticipant } from './functions';
  18. /**
  19. * Create an action for when dominant speaker changes.
  20. *
  21. * @param {string} id - Participant's ID.
  22. * @param {JitsiConference} conference - The {@code JitsiConference} associated
  23. * with the participant identified by the specified {@code id}. Only the local
  24. * participant is allowed to not specify an associated {@code JitsiConference}
  25. * instance.
  26. * @returns {{
  27. * type: DOMINANT_SPEAKER_CHANGED,
  28. * participant: {
  29. * conference: JitsiConference,
  30. * id: string
  31. * }
  32. * }}
  33. */
  34. export function dominantSpeakerChanged(id, conference) {
  35. return {
  36. type: DOMINANT_SPEAKER_CHANGED,
  37. participant: {
  38. conference,
  39. id
  40. }
  41. };
  42. }
  43. /**
  44. * Create an action for removing a participant from the conference.
  45. *
  46. * @param {string} id - Participant's ID.
  47. * @returns {{
  48. * type: KICK_PARTICIPANT,
  49. * id: string
  50. * }}
  51. */
  52. export function kickParticipant(id) {
  53. return {
  54. type: KICK_PARTICIPANT,
  55. id
  56. };
  57. }
  58. /**
  59. * Creates an action to signal the connection status of the local participant
  60. * has changed.
  61. *
  62. * @param {string} connectionStatus - The current connection status of the local
  63. * participant, as enumerated by the library's participantConnectionStatus
  64. * constants.
  65. * @returns {Function}
  66. */
  67. export function localParticipantConnectionStatusChanged(connectionStatus) {
  68. return (dispatch, getState) => {
  69. const participant = getLocalParticipant(getState);
  70. if (participant) {
  71. return dispatch(participantConnectionStatusChanged(
  72. participant.id,
  73. connectionStatus));
  74. }
  75. };
  76. }
  77. /**
  78. * Action to signal that the ID of local participant has changed. It happens
  79. * when the local participant joins a new conference or leaves an existing
  80. * conference.
  81. *
  82. * @param {string} id - New ID for local participant.
  83. * @returns {Function}
  84. */
  85. export function localParticipantIdChanged(id) {
  86. return (dispatch, getState) => {
  87. const participant = getLocalParticipant(getState);
  88. if (participant) {
  89. return dispatch({
  90. type: PARTICIPANT_ID_CHANGED,
  91. newValue: id,
  92. oldValue: participant.id
  93. });
  94. }
  95. };
  96. }
  97. /**
  98. * Action to signal that a local participant has joined.
  99. *
  100. * @param {Participant} participant={} - Information about participant.
  101. * @returns {{
  102. * type: PARTICIPANT_JOINED,
  103. * participant: Participant
  104. * }}
  105. */
  106. export function localParticipantJoined(participant = {}) {
  107. return participantJoined(set(participant, 'local', true));
  108. }
  109. /**
  110. * Action to remove a local participant.
  111. *
  112. * @returns {Function}
  113. */
  114. export function localParticipantLeft() {
  115. return (dispatch, getState) => {
  116. const participant = getLocalParticipant(getState);
  117. if (participant) {
  118. return (
  119. dispatch(
  120. participantLeft(
  121. participant.id,
  122. // XXX Only the local participant is allowed to leave
  123. // without stating the JitsiConference instance because
  124. // the local participant is uniquely identified by the
  125. // very fact that there is only one local participant
  126. // (and the fact that the local participant "joins" at
  127. // the beginning of the app and "leaves" at the end of
  128. // the app).
  129. undefined)));
  130. }
  131. };
  132. }
  133. /**
  134. * Action to signal the role of the local participant has changed. It can happen
  135. * when the participant has joined a conference, even before a non-default local
  136. * id has been set, or after a moderator leaves.
  137. *
  138. * @param {string} role - The new role of the local participant.
  139. * @returns {Function}
  140. */
  141. export function localParticipantRoleChanged(role) {
  142. return (dispatch, getState) => {
  143. const participant = getLocalParticipant(getState);
  144. if (participant) {
  145. return dispatch(participantRoleChanged(participant.id, role));
  146. }
  147. };
  148. }
  149. /**
  150. * Create an action for muting another participant in the conference.
  151. *
  152. * @param {string} id - Participant's ID.
  153. * @returns {{
  154. * type: MUTE_REMOTE_PARTICIPANT,
  155. * id: string
  156. * }}
  157. */
  158. export function muteRemoteParticipant(id) {
  159. return {
  160. type: MUTE_REMOTE_PARTICIPANT,
  161. id
  162. };
  163. }
  164. /**
  165. * Action to update a participant's connection status.
  166. *
  167. * @param {string} id - Participant's ID.
  168. * @param {string} connectionStatus - The new connection status of the
  169. * participant.
  170. * @returns {{
  171. * type: PARTICIPANT_UPDATED,
  172. * participant: {
  173. * connectionStatus: string,
  174. * id: string
  175. * }
  176. * }}
  177. */
  178. export function participantConnectionStatusChanged(id, connectionStatus) {
  179. return {
  180. type: PARTICIPANT_UPDATED,
  181. participant: {
  182. connectionStatus,
  183. id
  184. }
  185. };
  186. }
  187. /**
  188. * Action to signal that a participant's display name has changed.
  189. *
  190. * @param {string} id - The id of the participant being changed.
  191. * @param {string} displayName - The new display name.
  192. * @returns {{
  193. * type: PARTICIPANT_DISPLAY_NAME_CHANGED,
  194. * id: string,
  195. * name: string
  196. * }}
  197. */
  198. export function participantDisplayNameChanged(id, displayName = '') {
  199. // FIXME Do not use this action over participantUpdated. This action exists
  200. // as a a bridge for local name updates. Once other components responsible
  201. // for updating the local user's display name are in react/redux, this
  202. // action should be replaceable with the participantUpdated action.
  203. return {
  204. type: PARTICIPANT_DISPLAY_NAME_CHANGED,
  205. id,
  206. name: displayName.substr(0, MAX_DISPLAY_NAME_LENGTH)
  207. };
  208. }
  209. /**
  210. * Action to signal that a participant has joined.
  211. *
  212. * @param {Participant} participant - Information about participant.
  213. * @returns {{
  214. * type: PARTICIPANT_JOINED,
  215. * participant: Participant
  216. * }}
  217. */
  218. export function participantJoined(participant) {
  219. // Only the local participant is not identified with an id-conference pair.
  220. if (participant.local) {
  221. return {
  222. type: PARTICIPANT_JOINED,
  223. participant
  224. };
  225. }
  226. // In other words, a remote participant is identified with an id-conference
  227. // pair.
  228. const { conference } = participant;
  229. if (!conference) {
  230. throw Error(
  231. 'A remote participant must be associated with a JitsiConference!');
  232. }
  233. return (dispatch, getState) => {
  234. // A remote participant is only expected to join in a joined or joining
  235. // conference. The following check is really necessary because a
  236. // JitsiConference may have moved into leaving but may still manage to
  237. // sneak a PARTICIPANT_JOINED in if its leave is delayed for any purpose
  238. // (which is not outragous given that leaving involves network
  239. // requests.)
  240. const stateFeaturesBaseConference
  241. = getState()['features/base/conference'];
  242. if (conference === stateFeaturesBaseConference.conference
  243. || conference === stateFeaturesBaseConference.joining) {
  244. return dispatch({
  245. type: PARTICIPANT_JOINED,
  246. participant
  247. });
  248. }
  249. };
  250. }
  251. /**
  252. * Action to signal that a participant has left.
  253. *
  254. * @param {string} id - Participant's ID.
  255. * @param {JitsiConference} conference - The {@code JitsiConference} associated
  256. * with the participant identified by the specified {@code id}. Only the local
  257. * participant is allowed to not specify an associated {@code JitsiConference}
  258. * instance.
  259. * @returns {{
  260. * type: PARTICIPANT_LEFT,
  261. * participant: {
  262. * conference: JitsiConference,
  263. * id: string
  264. * }
  265. * }}
  266. */
  267. export function participantLeft(id, conference) {
  268. return {
  269. type: PARTICIPANT_LEFT,
  270. participant: {
  271. conference,
  272. id
  273. }
  274. };
  275. }
  276. /**
  277. * Action to signal that a participant's presence status has changed.
  278. *
  279. * @param {string} id - Participant's ID.
  280. * @param {string} presence - Participant's new presence status.
  281. * @returns {{
  282. * type: PARTICIPANT_UPDATED,
  283. * participant: {
  284. * id: string,
  285. * presence: string
  286. * }
  287. * }}
  288. */
  289. export function participantPresenceChanged(id, presence) {
  290. return participantUpdated({
  291. id,
  292. presence
  293. });
  294. }
  295. /**
  296. * Action to signal that a participant's role has changed.
  297. *
  298. * @param {string} id - Participant's ID.
  299. * @param {PARTICIPANT_ROLE} role - Participant's new role.
  300. * @returns {{
  301. * type: PARTICIPANT_UPDATED,
  302. * participant: {
  303. * id: string,
  304. * role: PARTICIPANT_ROLE
  305. * }
  306. * }}
  307. */
  308. export function participantRoleChanged(id, role) {
  309. return participantUpdated({
  310. id,
  311. role
  312. });
  313. }
  314. /**
  315. * Action to signal that some of participant properties has been changed.
  316. *
  317. * @param {Participant} participant={} - Information about participant. To
  318. * identify the participant the object should contain either property id with
  319. * value the id of the participant or property local with value true (if the
  320. * local participant hasn't joined the conference yet).
  321. * @returns {{
  322. * type: PARTICIPANT_UPDATED,
  323. * participant: Participant
  324. * }}
  325. */
  326. export function participantUpdated(participant = {}) {
  327. return {
  328. type: PARTICIPANT_UPDATED,
  329. participant
  330. };
  331. }
  332. /**
  333. * Create an action which pins a conference participant.
  334. *
  335. * @param {string|null} id - The ID of the conference participant to pin or null
  336. * if none of the conference's participants are to be pinned.
  337. * @returns {{
  338. * type: PIN_PARTICIPANT,
  339. * participant: {
  340. * id: string
  341. * }
  342. * }}
  343. */
  344. export function pinParticipant(id) {
  345. return {
  346. type: PIN_PARTICIPANT,
  347. participant: {
  348. id
  349. }
  350. };
  351. }
  352. /**
  353. * An array of names of participants that have joined the conference. The array
  354. * is replaced with an empty array as notifications are displayed.
  355. *
  356. * @private
  357. * @type {string[]}
  358. */
  359. let joinedParticipantsNames = [];
  360. /**
  361. * A throttled internal function that takes the internal list of participant
  362. * names, {@code joinedParticipantsNames}, and triggers the display of a
  363. * notification informing of their joining.
  364. *
  365. * @private
  366. * @type {Function}
  367. */
  368. const _throttledNotifyParticipantConnected = throttle(dispatch => {
  369. const joinedParticipantsCount = joinedParticipantsNames.length;
  370. let notificationProps;
  371. if (joinedParticipantsCount >= 3) {
  372. notificationProps = {
  373. titleArguments: {
  374. name: joinedParticipantsNames[0],
  375. count: joinedParticipantsCount - 1
  376. },
  377. titleKey: 'notify.connectedThreePlusMembers'
  378. };
  379. } else if (joinedParticipantsCount === 2) {
  380. notificationProps = {
  381. titleArguments: {
  382. first: joinedParticipantsNames[0],
  383. second: joinedParticipantsNames[1]
  384. },
  385. titleKey: 'notify.connectedTwoMembers'
  386. };
  387. } else if (joinedParticipantsCount) {
  388. notificationProps = {
  389. titleArguments: {
  390. name: joinedParticipantsNames[0]
  391. },
  392. titleKey: 'notify.connectedOneMember'
  393. };
  394. }
  395. if (notificationProps) {
  396. dispatch(
  397. showNotification(notificationProps, 2500));
  398. }
  399. joinedParticipantsNames = [];
  400. }, 500, { leading: false });
  401. /**
  402. * Queues the display of a notification of a participant having connected to
  403. * the meeting. The notifications are batched so that quick consecutive
  404. * connection events are shown in one notification.
  405. *
  406. * @param {string} displayName - The name of the participant that connected.
  407. * @returns {Function}
  408. */
  409. export function showParticipantJoinedNotification(displayName) {
  410. joinedParticipantsNames.push(
  411. displayName || interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME);
  412. return dispatch => _throttledNotifyParticipantConnected(dispatch);
  413. }