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.tsx 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import React from 'react';
  2. import { useTranslation } from 'react-i18next';
  3. import { makeStyles } from 'tss-react/mui';
  4. import { isIosMobileBrowser } from '../../../../base/environment/utils';
  5. import Icon from '../../../../base/icons/components/Icon';
  6. import {
  7. IconCopy,
  8. IconEnvelope,
  9. IconGoogle,
  10. IconOffice365,
  11. IconYahoo
  12. } from '../../../../base/icons/svg';
  13. import Tooltip from '../../../../base/tooltip/components/Tooltip';
  14. import { copyText } from '../../../../base/util/copyText.web';
  15. interface IProps {
  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. * The encoded no new-lines iOS invitation text to be sent on default mail.
  26. */
  27. inviteTextiOS: string;
  28. }
  29. const useStyles = makeStyles()(theme => {
  30. return {
  31. container: {
  32. marginTop: theme.spacing(4)
  33. },
  34. label: {
  35. marginBottom: theme.spacing(2)
  36. },
  37. iconRow: {
  38. display: 'flex',
  39. alignItems: 'center',
  40. justifyContent: 'space-between'
  41. },
  42. iconContainer: {
  43. display: 'block',
  44. padding: theme.spacing(2),
  45. cursor: 'pointer'
  46. }
  47. };
  48. });
  49. /**
  50. * Component that renders email invite options.
  51. *
  52. * @returns {ReactNode}
  53. */
  54. function InviteByEmailSection({ inviteSubject, inviteText, inviteTextiOS }: IProps) {
  55. const { classes } = useStyles();
  56. const { t } = useTranslation();
  57. const encodedInviteSubject = encodeURIComponent(inviteSubject);
  58. const encodedInviteText = encodeURIComponent(inviteText);
  59. const encodedInviteTextiOS = encodeURIComponent(inviteTextiOS);
  60. const encodedDefaultEmailText = isIosMobileBrowser() ? encodedInviteTextiOS : encodedInviteText;
  61. /**
  62. * Copies the conference invitation to the clipboard.
  63. *
  64. * @returns {void}
  65. */
  66. function _onCopyText() {
  67. copyText(inviteText);
  68. }
  69. /**
  70. * Copies the conference invitation to the clipboard.
  71. *
  72. * @param {Object} e - The key event to handle.
  73. *
  74. * @returns {void}
  75. */
  76. function _onCopyTextKeyPress(e: React.KeyboardEvent) {
  77. if (e.key === ' ' || e.key === 'Enter') {
  78. e.preventDefault();
  79. copyText(inviteText);
  80. }
  81. }
  82. /**
  83. * Renders clickable elements that each open an email client
  84. * containing a conference invite.
  85. *
  86. * @returns {ReactNode}
  87. */
  88. function renderEmailIcons() {
  89. const PROVIDER_MAPPING = [
  90. {
  91. icon: IconEnvelope,
  92. tooltipKey: 'addPeople.defaultEmail',
  93. url: `mailto:?subject=${encodedInviteSubject}&body=${encodedDefaultEmailText}`
  94. },
  95. {
  96. icon: IconGoogle,
  97. tooltipKey: 'addPeople.googleEmail',
  98. url: `https://mail.google.com/mail/?view=cm&fs=1&su=${encodedInviteSubject}&body=${encodedInviteText}`
  99. },
  100. {
  101. icon: IconOffice365,
  102. tooltipKey: 'addPeople.outlookEmail',
  103. // eslint-disable-next-line max-len
  104. url: `https://outlook.office.com/mail/deeplink/compose?subject=${encodedInviteSubject}&body=${encodedInviteText}`
  105. },
  106. {
  107. icon: IconYahoo,
  108. tooltipKey: 'addPeople.yahooEmail',
  109. url: `https://compose.mail.yahoo.com/?To=&Subj=${encodedInviteSubject}&Body=${encodedInviteText}`
  110. }
  111. ];
  112. return (
  113. <>
  114. {
  115. PROVIDER_MAPPING.map(({ icon, tooltipKey, url }, idx) => (
  116. <Tooltip
  117. content = { t(tooltipKey) }
  118. key = { idx }
  119. position = 'top'>
  120. <a
  121. aria-label = { t(tooltipKey) }
  122. className = { classes.iconContainer }
  123. href = { url }
  124. rel = 'noopener noreferrer'
  125. target = '_blank'>
  126. <Icon src = { icon } />
  127. </a>
  128. </Tooltip>
  129. ))
  130. }
  131. </>
  132. );
  133. }
  134. return (
  135. <>
  136. <div className = { classes.container }>
  137. <p className = { classes.label }>{t('addPeople.shareInvite')}</p>
  138. <div className = { classes.iconRow }>
  139. <Tooltip
  140. content = { t('addPeople.copyInvite') }
  141. position = 'top'>
  142. <div
  143. aria-label = { t('addPeople.copyInvite') }
  144. className = { classes.iconContainer }
  145. // eslint-disable-next-line react/jsx-no-bind
  146. onClick = { _onCopyText }
  147. // eslint-disable-next-line react/jsx-no-bind
  148. onKeyPress = { _onCopyTextKeyPress }
  149. role = 'button'
  150. tabIndex = { 0 }>
  151. <Icon src = { IconCopy } />
  152. </div>
  153. </Tooltip>
  154. {renderEmailIcons()}
  155. </div>
  156. </div>
  157. </>
  158. );
  159. }
  160. export default InviteByEmailSection;