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.

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