Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

OverflowMenuButton.js 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /* @flow */
  2. import InlineDialog from '@atlaskit/inline-dialog';
  3. import React, { Component } from 'react';
  4. import { createToolbarEvent, sendAnalytics } from '../../../analytics';
  5. import { translate } from '../../../base/i18n';
  6. import { connect } from '../../../base/redux';
  7. import { ReactionEmoji, ReactionsMenu } from '../../../reactions/components';
  8. import { type ReactionEmojiProps } from '../../../reactions/constants';
  9. import { getReactionsQueue } from '../../../reactions/functions.any';
  10. import Drawer from './Drawer';
  11. import JitsiPortal from './JitsiPortal';
  12. import OverflowToggleButton from './OverflowToggleButton';
  13. /**
  14. * The type of the React {@code Component} props of {@link OverflowMenuButton}.
  15. */
  16. type Props = {
  17. /**
  18. * ID of the menu that is controlled by this button.
  19. */
  20. ariaControls: String,
  21. /**
  22. * A child React Element to display within {@code InlineDialog}.
  23. */
  24. children: React$Node,
  25. /**
  26. * Whether or not the OverflowMenu popover should display.
  27. */
  28. isOpen: boolean,
  29. /**
  30. * Callback to change the visibility of the overflow menu.
  31. */
  32. onVisibilityChange: Function,
  33. /**
  34. * Whether to display the OverflowMenu as a drawer.
  35. */
  36. overflowDrawer: boolean,
  37. /**
  38. * Invoked to obtain translated strings.
  39. */
  40. t: Function,
  41. /**
  42. * The array of reactions to be displayed.
  43. */
  44. reactionsQueue: Array<ReactionEmojiProps>,
  45. /**
  46. * Whether or not to display the reactions in the mobile menu.
  47. */
  48. showMobileReactions: boolean
  49. };
  50. /**
  51. * A React {@code Component} for opening or closing the {@code OverflowMenu}.
  52. *
  53. * @augments Component
  54. */
  55. class OverflowMenuButton extends Component<Props> {
  56. /**
  57. * Initializes a new {@code OverflowMenuButton} instance.
  58. *
  59. * @param {Object} props - The read-only properties with which the new
  60. * instance is to be initialized.
  61. */
  62. constructor(props: Props) {
  63. super(props);
  64. // Bind event handlers so they are only bound once per instance.
  65. this._onCloseDialog = this._onCloseDialog.bind(this);
  66. this._toggleDialogVisibility
  67. = this._toggleDialogVisibility.bind(this);
  68. this._onEscClick = this._onEscClick.bind(this);
  69. }
  70. _onEscClick: (KeyboardEvent) => void;
  71. /**
  72. * Click handler for the more actions entries.
  73. *
  74. * @param {KeyboardEvent} event - Esc key click to close the popup.
  75. * @returns {void}
  76. */
  77. _onEscClick(event) {
  78. if (event.key === 'Escape' && this.props.isOpen) {
  79. event.preventDefault();
  80. event.stopPropagation();
  81. this._onCloseDialog();
  82. }
  83. }
  84. /**
  85. * Implements React's {@link Component#render()}.
  86. *
  87. * @inheritdoc
  88. * @returns {ReactElement}
  89. */
  90. render() {
  91. const { children, isOpen, overflowDrawer, reactionsQueue, showMobileReactions } = this.props;
  92. return (
  93. <div className = 'toolbox-button-wth-dialog'>
  94. {
  95. overflowDrawer ? (
  96. <>
  97. <OverflowToggleButton
  98. handleClick = { this._toggleDialogVisibility }
  99. isOpen = { isOpen }
  100. onKeyDown = { this._onEscClick } />
  101. <JitsiPortal>
  102. <Drawer
  103. isOpen = { isOpen }
  104. onClose = { this._onCloseDialog }>
  105. {children}
  106. {showMobileReactions && <ReactionsMenu overflowMenu = { true } />}
  107. </Drawer>
  108. {showMobileReactions && <div className = 'reactions-animations-container'>
  109. {reactionsQueue.map(({ reaction, uid }, index) => (<ReactionEmoji
  110. index = { index }
  111. key = { uid }
  112. reaction = { reaction }
  113. uid = { uid } />))}
  114. </div>}
  115. </JitsiPortal>
  116. </>
  117. ) : (
  118. <InlineDialog
  119. content = { children }
  120. isOpen = { isOpen }
  121. onClose = { this._onCloseDialog }
  122. placement = 'top-end'>
  123. <OverflowToggleButton
  124. handleClick = { this._toggleDialogVisibility }
  125. isOpen = { isOpen }
  126. onKeyDown = { this._onEscClick } />
  127. </InlineDialog>
  128. )
  129. }
  130. </div>
  131. );
  132. }
  133. _onCloseDialog: () => void;
  134. /**
  135. * Callback invoked when {@code InlineDialog} signals that it should be
  136. * close.
  137. *
  138. * @private
  139. * @returns {void}
  140. */
  141. _onCloseDialog() {
  142. this.props.onVisibilityChange(false);
  143. }
  144. _toggleDialogVisibility: () => void;
  145. /**
  146. * Callback invoked to signal that an event has occurred that should change
  147. * the visibility of the {@code InlineDialog} component.
  148. *
  149. * @private
  150. * @returns {void}
  151. */
  152. _toggleDialogVisibility() {
  153. sendAnalytics(createToolbarEvent('overflow'));
  154. this.props.onVisibilityChange(!this.props.isOpen);
  155. }
  156. }
  157. /**
  158. * Maps (parts of) the Redux state to the associated props for the
  159. * {@code OverflowMenuButton} component.
  160. *
  161. * @param {Object} state - The Redux state.
  162. * @returns {Props}
  163. */
  164. function mapStateToProps(state) {
  165. const { overflowDrawer } = state['features/toolbox'];
  166. return {
  167. overflowDrawer,
  168. reactionsQueue: getReactionsQueue(state)
  169. };
  170. }
  171. export default translate(connect(mapStateToProps)(OverflowMenuButton));