您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

CopyMeetingUrl.js 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // @flow
  2. import React, { Component } from 'react';
  3. import { getCurrentConferenceUrl } from '../../../connection';
  4. import { translate } from '../../../i18n';
  5. import { Icon, IconCopy, IconCheck } from '../../../icons';
  6. import { connect } from '../../../redux';
  7. import { copyText, getDecodedURI } from '../../../util';
  8. type Props = {
  9. /**
  10. * The meeting url.
  11. */
  12. url: string,
  13. /**
  14. * Used for translation.
  15. */
  16. t: Function,
  17. /**
  18. * Used to determine if invitation link should be automatically copied
  19. * after creating a meeting.
  20. */
  21. _enableAutomaticUrlCopy: boolean,
  22. };
  23. type State = {
  24. /**
  25. * If true it shows the 'copy link' message.
  26. */
  27. showCopyLink: boolean,
  28. /**
  29. * If true it shows the 'link copied' message.
  30. */
  31. showLinkCopied: boolean,
  32. };
  33. const COPY_TIMEOUT = 2000;
  34. /**
  35. * Component used to copy meeting url on prejoin page.
  36. */
  37. class CopyMeetingUrl extends Component<Props, State> {
  38. /**
  39. * Initializes a new {@code Prejoin} instance.
  40. *
  41. * @inheritdoc
  42. */
  43. constructor(props) {
  44. super(props);
  45. this.state = {
  46. showCopyLink: false,
  47. showLinkCopied: false
  48. };
  49. this._copyUrl = this._copyUrl.bind(this);
  50. this._hideCopyLink = this._hideCopyLink.bind(this);
  51. this._hideLinkCopied = this._hideLinkCopied.bind(this);
  52. this._showCopyLink = this._showCopyLink.bind(this);
  53. this._showLinkCopied = this._showLinkCopied.bind(this);
  54. this._copyUrlAutomatically = this._copyUrlAutomatically.bind(this);
  55. }
  56. _copyUrl: () => void;
  57. /**
  58. * Callback invoked to copy the url to clipboard.
  59. *
  60. * @returns {void}
  61. */
  62. _copyUrl() {
  63. const success = copyText(this.props.url);
  64. if (success) {
  65. this._showLinkCopied();
  66. window.setTimeout(this._hideLinkCopied, COPY_TIMEOUT);
  67. }
  68. }
  69. _hideLinkCopied: () => void;
  70. /**
  71. * Hides the 'Link copied' message.
  72. *
  73. * @private
  74. * @returns {void}
  75. */
  76. _hideLinkCopied() {
  77. this.setState({
  78. showLinkCopied: false
  79. });
  80. }
  81. _hideCopyLink: () => void;
  82. /**
  83. * Hides the 'Copy link' text.
  84. *
  85. * @private
  86. * @returns {void}
  87. */
  88. _hideCopyLink() {
  89. this.setState({
  90. showCopyLink: false,
  91. showLinkCopied: false
  92. });
  93. }
  94. _showCopyLink: () => void;
  95. /**
  96. * Shows the dark 'Copy link' text on hover.
  97. *
  98. * @private
  99. * @returns {void}
  100. */
  101. _showCopyLink() {
  102. this.setState({
  103. showCopyLink: true,
  104. showLinkCopied: false
  105. });
  106. }
  107. _showLinkCopied: () => void;
  108. /**
  109. * Shows the green 'Link copied' message.
  110. *
  111. * @private
  112. * @returns {void}
  113. */
  114. _showLinkCopied() {
  115. this.setState({
  116. showLinkCopied: true,
  117. showCopyLink: false
  118. });
  119. }
  120. _copyUrlAutomatically: () => void;
  121. /**
  122. * Attempts to automatically copy invitation URL.
  123. * Document has to be focused in order for this to work.
  124. *
  125. * @private
  126. * @returns {void}
  127. */
  128. _copyUrlAutomatically() {
  129. navigator.clipboard.writeText(this.props.url)
  130. .then(() => {
  131. this._showLinkCopied();
  132. window.setTimeout(this._hideLinkCopied, COPY_TIMEOUT);
  133. });
  134. }
  135. /**
  136. * Implements React's {@link Component#componentDidMount()}. Invoked
  137. * immediately before mounting occurs.
  138. *
  139. * @inheritdoc
  140. */
  141. componentDidMount() {
  142. const { _enableAutomaticUrlCopy } = this.props;
  143. if (_enableAutomaticUrlCopy) {
  144. setTimeout(this._copyUrlAutomatically, 2000);
  145. }
  146. }
  147. /**
  148. * Implements React's {@link Component#render()}.
  149. *
  150. * @inheritdoc
  151. * @returns {ReactElement}
  152. */
  153. render() {
  154. const { showCopyLink, showLinkCopied } = this.state;
  155. const { url, t } = this.props;
  156. const { _copyUrl, _showCopyLink, _hideCopyLink } = this;
  157. const src = showLinkCopied ? IconCheck : IconCopy;
  158. return (
  159. <div
  160. className = 'copy-meeting'
  161. onMouseEnter = { _showCopyLink }
  162. onMouseLeave = { _hideCopyLink }>
  163. <div
  164. className = { `url ${showLinkCopied ? 'done' : ''}` }
  165. onClick = { _copyUrl } >
  166. <div className = 'copy-meeting-text'>
  167. { !showCopyLink && !showLinkCopied && getDecodedURI(url) }
  168. { showCopyLink && t('prejoin.copyAndShare') }
  169. { showLinkCopied && t('prejoin.linkCopied') }
  170. </div>
  171. <Icon
  172. onClick = { _copyUrl }
  173. size = { 24 }
  174. src = { src } />
  175. </div>
  176. </div>
  177. );
  178. }
  179. }
  180. /**
  181. * Maps (parts of) the redux state to the React {@code Component} props.
  182. *
  183. * @param {Object} state - The redux state.
  184. * @returns {Object}
  185. */
  186. function mapStateToProps(state) {
  187. const { enableAutomaticUrlCopy } = state['features/base/config'];
  188. return {
  189. url: getCurrentConferenceUrl(state),
  190. _enableAutomaticUrlCopy: enableAutomaticUrlCopy || false
  191. };
  192. }
  193. export default connect(mapStateToProps)(translate(CopyMeetingUrl));