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.

InviteByEmailSection.js 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // @flow
  2. import React, { useState } from 'react';
  3. import { translate } from '../../../../base/i18n';
  4. import {
  5. Icon,
  6. IconArrowDownSmall,
  7. IconCopy,
  8. IconEmail,
  9. IconGoogle,
  10. IconOutlook,
  11. IconYahoo
  12. } from '../../../../base/icons';
  13. import { Tooltip } from '../../../../base/tooltip';
  14. import { copyText } from '../../../../base/util';
  15. type Props = {
  16. /**
  17. * The encoded invitation subject.
  18. */
  19. inviteSubject: string,
  20. /**
  21. * The encoded invitation text to be sent.
  22. */
  23. inviteText: string,
  24. /**
  25. * Invoked to obtain translated strings.
  26. */
  27. t: Function,
  28. };
  29. /**
  30. * Component that renders email invite options.
  31. *
  32. * @returns {React$Element<any>}
  33. */
  34. function InviteByEmailSection({ inviteSubject, inviteText, t }: Props) {
  35. const [ isActive, setIsActive ] = useState(false);
  36. const encodedInviteSubject = encodeURIComponent(inviteSubject);
  37. const encodedInviteText = encodeURIComponent(inviteText);
  38. /**
  39. * Copies the conference invitation to the clipboard.
  40. *
  41. * @returns {void}
  42. */
  43. function _onCopyText() {
  44. copyText(inviteText);
  45. }
  46. /**
  47. * Copies the conference invitation to the clipboard.
  48. *
  49. * @param {Object} e - The key event to handle.
  50. *
  51. * @returns {void}
  52. */
  53. function _onCopyTextKeyPress(e) {
  54. if (e.key === ' ' || e.key === 'Enter') {
  55. e.preventDefault();
  56. copyText(inviteText);
  57. }
  58. }
  59. /**
  60. * Toggles the email invite drawer.
  61. *
  62. * @returns {void}
  63. */
  64. function _onToggleActiveState() {
  65. setIsActive(!isActive);
  66. }
  67. /**
  68. * Toggles the email invite drawer.
  69. *
  70. * @param {Object} e - The key event to handle.
  71. *
  72. * @returns {void}
  73. */
  74. function _onToggleActiveStateKeyPress(e) {
  75. if (e.key === ' ' || e.key === 'Enter') {
  76. e.preventDefault();
  77. setIsActive(!isActive);
  78. }
  79. }
  80. /**
  81. * Renders clickable elements that each open an email client
  82. * containing a conference invite.
  83. *
  84. * @returns {React$Element<any>}
  85. */
  86. function renderEmailIcons() {
  87. const PROVIDER_MAPPING = [
  88. {
  89. icon: IconEmail,
  90. tooltipKey: 'addPeople.defaultEmail',
  91. url: `mailto:?subject=${encodedInviteSubject}&body=${encodedInviteText}`
  92. },
  93. {
  94. icon: IconGoogle,
  95. tooltipKey: 'addPeople.googleEmail',
  96. url: `https://mail.google.com/mail/?view=cm&fs=1&su=${encodedInviteSubject}&body=${encodedInviteText}`
  97. },
  98. {
  99. icon: IconOutlook,
  100. tooltipKey: 'addPeople.outlookEmail',
  101. // eslint-disable-next-line max-len
  102. url: `https://outlook.office.com/mail/deeplink/compose?subject=${encodedInviteSubject}&body=${encodedInviteText}`
  103. },
  104. {
  105. icon: IconYahoo,
  106. tooltipKey: 'addPeople.yahooEmail',
  107. url: `https://compose.mail.yahoo.com/?To=&Subj=${encodedInviteSubject}&Body=${encodedInviteText}`
  108. }
  109. ];
  110. return (
  111. <>
  112. {
  113. PROVIDER_MAPPING.map(({ icon, tooltipKey, url }, idx) => (
  114. <Tooltip
  115. content = { t(tooltipKey) }
  116. key = { idx }
  117. position = 'top'>
  118. <a
  119. aria-label = { t(tooltipKey) }
  120. className = 'provider-icon'
  121. href = { url }
  122. rel = 'noopener noreferrer'
  123. target = '_blank'>
  124. <Icon src = { icon } />
  125. </a>
  126. </Tooltip>
  127. ))
  128. }
  129. </>
  130. );
  131. }
  132. return (
  133. <>
  134. <div>
  135. <div
  136. aria-expanded = { isActive }
  137. aria-label = { t('addPeople.shareInvite') }
  138. className = { `invite-more-dialog email-container${isActive ? ' active' : ''}` }
  139. onClick = { _onToggleActiveState }
  140. onKeyPress = { _onToggleActiveStateKeyPress }
  141. role = 'button'
  142. tabIndex = { 0 }>
  143. <span>{t('addPeople.shareInvite')}</span>
  144. <Icon src = { IconArrowDownSmall } />
  145. </div>
  146. <div className = { `invite-more-dialog icon-container${isActive ? ' active' : ''}` }>
  147. <Tooltip
  148. content = { t('addPeople.copyInvite') }
  149. position = 'top'>
  150. <div
  151. aria-label = { t('addPeople.copyInvite') }
  152. className = 'copy-invite-icon'
  153. onClick = { _onCopyText }
  154. onKeyPress = { _onCopyTextKeyPress }
  155. role = 'button'
  156. tabIndex = { 0 }>
  157. <Icon src = { IconCopy } />
  158. </div>
  159. </Tooltip>
  160. {renderEmailIcons()}
  161. </div>
  162. </div>
  163. </>
  164. );
  165. }
  166. export default translate(InviteByEmailSection);