Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

OverflowMenuButton.tsx 6.7KB

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