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.

AbstractLiveStreamButton.ts 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import { IReduxState } from '../../../app/types';
  2. import { IconSites } from '../../../base/icons/svg';
  3. import { MEET_FEATURES } from '../../../base/jwt/constants';
  4. import { isJwtFeatureEnabled } from '../../../base/jwt/functions';
  5. import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
  6. import { isLocalParticipantModerator } from '../../../base/participants/functions';
  7. import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
  8. import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
  9. import { maybeShowPremiumFeatureDialog } from '../../../jaas/actions';
  10. import { getActiveSession } from '../../functions';
  11. import { getLiveStreaming } from './functions';
  12. /**
  13. * The type of the React {@code Component} props of
  14. * {@link AbstractLiveStreamButton}.
  15. */
  16. export interface IProps extends AbstractButtonProps {
  17. /**
  18. * True if the button needs to be disabled.
  19. */
  20. _disabled: boolean;
  21. /**
  22. * True if there is a running active live stream, false otherwise.
  23. */
  24. _isLiveStreamRunning: boolean;
  25. /**
  26. * The tooltip to display when hovering over the button.
  27. */
  28. _tooltip?: string;
  29. }
  30. /**
  31. * An abstract class of a button for starting and stopping live streaming.
  32. */
  33. export default class AbstractLiveStreamButton<P extends IProps> extends AbstractButton<P> {
  34. accessibilityLabel = 'dialog.startLiveStreaming';
  35. toggledAccessibilityLabel = 'dialog.stopLiveStreaming';
  36. icon = IconSites;
  37. label = 'dialog.startLiveStreaming';
  38. toggledLabel = 'dialog.stopLiveStreaming';
  39. /**
  40. * Returns the tooltip that should be displayed when the button is disabled.
  41. *
  42. * @private
  43. * @returns {string}
  44. */
  45. _getTooltip() {
  46. return this.props._tooltip ?? '';
  47. }
  48. /**
  49. * Helper function to be implemented by subclasses, which should be used
  50. * to handle the live stream button being clicked / pressed.
  51. *
  52. * @protected
  53. * @returns {void}
  54. */
  55. _onHandleClick() {
  56. // To be implemented by subclass.
  57. }
  58. /**
  59. * Handles clicking / pressing the button.
  60. *
  61. * @override
  62. * @protected
  63. * @returns {void}
  64. */
  65. async _handleClick() {
  66. const { dispatch } = this.props;
  67. const dialogShown = await dispatch(maybeShowPremiumFeatureDialog(MEET_FEATURES.RECORDING));
  68. if (!dialogShown) {
  69. this._onHandleClick();
  70. }
  71. }
  72. /**
  73. * Returns a boolean value indicating if this button is disabled or not.
  74. *
  75. * @protected
  76. * @returns {boolean}
  77. */
  78. _isDisabled() {
  79. return this.props._disabled;
  80. }
  81. /**
  82. * Indicates whether this button is in toggled state or not.
  83. *
  84. * @override
  85. * @protected
  86. * @returns {boolean}
  87. */
  88. _isToggled() {
  89. return this.props._isLiveStreamRunning;
  90. }
  91. }
  92. /**
  93. * Maps (parts of) the redux state to the associated props for the
  94. * {@code AbstractLiveStreamButton} component.
  95. *
  96. * @param {Object} state - The Redux state.
  97. * @param {IProps} ownProps - The own props of the Component.
  98. * @private
  99. * @returns {{
  100. * _disabled: boolean,
  101. * _isLiveStreamRunning: boolean,
  102. * visible: boolean
  103. * }}
  104. */
  105. export function _mapStateToProps(state: IReduxState, ownProps: IProps) {
  106. let { visible } = ownProps;
  107. // A button can be disabled/enabled only if enableFeaturesBasedOnToken
  108. // is on or if the recording is running.
  109. let _disabled = false;
  110. let _tooltip = '';
  111. if (typeof visible === 'undefined') {
  112. // If the containing component provides the visible prop, that is one
  113. // above all, but if not, the button should be autonomous and decide on
  114. // its own to be visible or not.
  115. const isModerator = isLocalParticipantModerator(state);
  116. const liveStreaming = getLiveStreaming(state);
  117. if (isModerator) {
  118. visible = liveStreaming.enabled ? isJwtFeatureEnabled(state, 'livestreaming', true) : false;
  119. } else {
  120. visible = false;
  121. }
  122. }
  123. // disable the button if the recording is running.
  124. if (visible && getActiveSession(state, JitsiRecordingConstants.mode.FILE)) {
  125. _disabled = true;
  126. _tooltip = 'dialog.liveStreamingDisabledBecauseOfActiveRecordingTooltip';
  127. }
  128. // disable the button if we are in a breakout room.
  129. if (isInBreakoutRoom(state)) {
  130. _disabled = true;
  131. visible = false;
  132. }
  133. return {
  134. _disabled,
  135. _isLiveStreamRunning: Boolean(getActiveSession(state, JitsiRecordingConstants.mode.STREAM)),
  136. _tooltip,
  137. visible
  138. };
  139. }