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.

AddPeopleDialog.js 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // @flow
  2. import React, { useState, useEffect } from 'react';
  3. import { createInviteDialogEvent, sendAnalytics } from '../../../../analytics';
  4. import { getRoomName } from '../../../../base/conference';
  5. import { getInviteURL } from '../../../../base/connection';
  6. import { Dialog } from '../../../../base/dialog';
  7. import { translate } from '../../../../base/i18n';
  8. import { JitsiRecordingConstants } from '../../../../base/lib-jitsi-meet';
  9. import { getLocalParticipant } from '../../../../base/participants';
  10. import { connect } from '../../../../base/redux';
  11. import { isVpaasMeeting } from '../../../../billing-counter/functions';
  12. import EmbedMeetingTrigger from '../../../../embed-meeting/components/EmbedMeetingTrigger';
  13. import { getActiveSession } from '../../../../recording';
  14. import { updateDialInNumbers } from '../../../actions';
  15. import { _getDefaultPhoneNumber, getInviteText, isAddPeopleEnabled, isDialOutEnabled } from '../../../functions';
  16. import CopyMeetingLinkSection from './CopyMeetingLinkSection';
  17. import DialInSection from './DialInSection';
  18. import InviteByEmailSection from './InviteByEmailSection';
  19. import InviteContactsSection from './InviteContactsSection';
  20. import LiveStreamSection from './LiveStreamSection';
  21. declare var interfaceConfig: Object;
  22. type Props = {
  23. /**
  24. * The name of the current conference. Used as part of inviting users.
  25. */
  26. _conferenceName: string,
  27. /**
  28. * The object representing the dialIn feature.
  29. */
  30. _dialIn: Object,
  31. /**
  32. * Whether or not embed meeting should be visible.
  33. */
  34. _embedMeetingVisible: boolean,
  35. /**
  36. * Whether or not invite contacts should be visible.
  37. */
  38. _inviteContactsVisible: boolean,
  39. /**
  40. * The current url of the conference to be copied onto the clipboard.
  41. */
  42. _inviteUrl: string,
  43. /**
  44. * The current known URL for a live stream in progress.
  45. */
  46. _liveStreamViewURL: string,
  47. /**
  48. * The redux representation of the local participant.
  49. */
  50. _localParticipantName: ?string,
  51. /**
  52. * The current location url of the conference.
  53. */
  54. _locationUrl: Object,
  55. /**
  56. * Invoked to obtain translated strings.
  57. */
  58. t: Function,
  59. /**
  60. * Method to update the dial in numbers.
  61. */
  62. updateNumbers: Function
  63. };
  64. /**
  65. * Invite More component.
  66. *
  67. * @returns {React$Element<any>}
  68. */
  69. function AddPeopleDialog({
  70. _conferenceName,
  71. _dialIn,
  72. _embedMeetingVisible,
  73. _inviteContactsVisible,
  74. _inviteUrl,
  75. _liveStreamViewURL,
  76. _localParticipantName,
  77. _locationUrl,
  78. t,
  79. updateNumbers }: Props) {
  80. const [ phoneNumber, setPhoneNumber ] = useState(undefined);
  81. /**
  82. * Updates the dial-in numbers.
  83. */
  84. useEffect(() => {
  85. if (!_dialIn.numbers) {
  86. updateNumbers();
  87. }
  88. }, []);
  89. /**
  90. * Sends analytics events when the dialog opens/closes.
  91. *
  92. * @returns {void}
  93. */
  94. useEffect(() => {
  95. sendAnalytics(createInviteDialogEvent(
  96. 'invite.dialog.opened', 'dialog'));
  97. return () => {
  98. sendAnalytics(createInviteDialogEvent(
  99. 'invite.dialog.closed', 'dialog'));
  100. };
  101. }, []);
  102. /**
  103. * Updates the phone number in the state once the dial-in numbers are fetched.
  104. *
  105. * @returns {void}
  106. */
  107. useEffect(() => {
  108. if (!phoneNumber && _dialIn && _dialIn.numbers) {
  109. setPhoneNumber(_getDefaultPhoneNumber(_dialIn.numbers));
  110. }
  111. }, [ _dialIn ]);
  112. const invite = getInviteText({
  113. _conferenceName,
  114. _localParticipantName,
  115. _inviteUrl,
  116. _locationUrl,
  117. _dialIn,
  118. _liveStreamViewURL,
  119. phoneNumber,
  120. t
  121. });
  122. const inviteSubject = t('addPeople.inviteMoreMailSubject', {
  123. appName: interfaceConfig.APP_NAME
  124. });
  125. return (
  126. <Dialog
  127. cancelKey = { 'dialog.close' }
  128. hideCancelButton = { true }
  129. submitDisabled = { true }
  130. titleKey = 'addPeople.inviteMorePrompt'
  131. width = { 'small' }>
  132. <div className = 'invite-more-dialog'>
  133. { _inviteContactsVisible && <InviteContactsSection /> }
  134. <CopyMeetingLinkSection url = { _inviteUrl } />
  135. <InviteByEmailSection
  136. inviteSubject = { inviteSubject }
  137. inviteText = { invite } />
  138. { _embedMeetingVisible && <EmbedMeetingTrigger /> }
  139. <div className = 'invite-more-dialog separator' />
  140. {
  141. _liveStreamViewURL
  142. && <LiveStreamSection liveStreamViewURL = { _liveStreamViewURL } />
  143. }
  144. {
  145. _dialIn.numbers
  146. && <DialInSection
  147. conferenceName = { _conferenceName }
  148. dialIn = { _dialIn }
  149. locationUrl = { _locationUrl }
  150. phoneNumber = { phoneNumber } />
  151. }
  152. </div>
  153. </Dialog>
  154. );
  155. }
  156. /**
  157. * Maps (parts of) the Redux state to the associated props for the
  158. * {@code AddPeopleDialog} component.
  159. *
  160. * @param {Object} state - The Redux state.
  161. * @private
  162. * @returns {Props}
  163. */
  164. function mapStateToProps(state) {
  165. const localParticipant = getLocalParticipant(state);
  166. const currentLiveStreamingSession
  167. = getActiveSession(state, JitsiRecordingConstants.mode.STREAM);
  168. const { iAmRecorder } = state['features/base/config'];
  169. const addPeopleEnabled = isAddPeopleEnabled(state);
  170. const dialOutEnabled = isDialOutEnabled(state);
  171. const hideInviteContacts = iAmRecorder || (!addPeopleEnabled && !dialOutEnabled);
  172. return {
  173. _conferenceName: getRoomName(state),
  174. _dialIn: state['features/invite'],
  175. _embedMeetingVisible: !isVpaasMeeting(state),
  176. _inviteContactsVisible: interfaceConfig.ENABLE_DIAL_OUT && !hideInviteContacts,
  177. _inviteUrl: getInviteURL(state),
  178. _liveStreamViewURL:
  179. currentLiveStreamingSession
  180. && currentLiveStreamingSession.liveStreamViewURL,
  181. _localParticipantName: localParticipant?.name,
  182. _locationUrl: state['features/base/connection'].locationURL
  183. };
  184. }
  185. /**
  186. * Maps dispatching of some action to React component props.
  187. *
  188. * @param {Function} dispatch - Redux action dispatcher.
  189. * @returns {Props}
  190. */
  191. const mapDispatchToProps = {
  192. updateNumbers: () => updateDialInNumbers()
  193. };
  194. export default translate(
  195. connect(mapStateToProps, mapDispatchToProps)(AddPeopleDialog)
  196. );