diff --git a/react/features/recording/components/LiveStream/AbstractLiveStreamButton.js b/react/features/recording/components/LiveStream/AbstractLiveStreamButton.js index 1877e561c02a..a3b49fe0c654 100644 --- a/react/features/recording/components/LiveStream/AbstractLiveStreamButton.js +++ b/react/features/recording/components/LiveStream/AbstractLiveStreamButton.js @@ -1,6 +1,7 @@ // @flow import { openDialog } from '../../../base/dialog'; +import { IconLiveStreaming } from '../../../base/icons'; import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; import { getLocalParticipant } from '../../../base/participants'; import { @@ -30,6 +31,11 @@ export type Props = AbstractButtonProps & { */ _disabled: Boolean, + /** + * The tooltip to display when hovering over the button. + */ + _tooltip: ?String, + /** * The redux {@code dispatch} function. */ @@ -44,12 +50,22 @@ export type Props = AbstractButtonProps & { /** * An abstract class of a button for starting and stopping live streaming. */ -export default class AbstractLiveStreamButton - extends AbstractButton { +export default class AbstractLiveStreamButton extends AbstractButton { accessibilityLabel = 'dialog.accessibilityLabel.liveStreaming'; + icon = IconLiveStreaming; label = 'dialog.startLiveStreaming'; toggledLabel = 'dialog.stopLiveStreaming'; + /** + * Returns the tooltip that should be displayed when the button is disabled. + * + * @private + * @returns {string} + */ + _getTooltip() { + return this.props._tooltip || ''; + } + /** * Handles clicking / pressing the button. * @@ -65,6 +81,16 @@ export default class AbstractLiveStreamButton )); } + /** + * Returns a boolean value indicating if this button is disabled or not. + * + * @protected + * @returns {boolean} + */ + _isDisabled() { + return this.props._disabled; + } + /** * Indicates whether this button is in toggled state or not. * @@ -96,6 +122,7 @@ export function _mapStateToProps(state: Object, ownProps: Props) { // A button can be disabled/enabled only if enableFeaturesBasedOnToken // is on or if the recording is running. let _disabled; + let _tooltip = ''; if (typeof visible === 'undefined') { // If the containing component provides the visible prop, that is one @@ -112,18 +139,32 @@ export function _mapStateToProps(state: Object, ownProps: Props) { if (enableFeaturesBasedOnToken) { visible = visible && String(features.livestreaming) === 'true'; _disabled = String(features.livestreaming) === 'disabled'; + + if (!visible && !_disabled) { + _disabled = true; + visible = true; + + // button and tooltip + if (state['features/base/jwt'].isGuest) { + _tooltip = 'dialog.liveStreamingDisabledForGuestTooltip'; + } else { + _tooltip = 'dialog.liveStreamingDisabledTooltip'; + } + } } } // disable the button if the recording is running. if (getActiveSession(state, JitsiRecordingConstants.mode.FILE)) { _disabled = true; + _tooltip = 'dialog.liveStreamingDisabledBecauseOfActiveRecordingTooltip'; } return { _disabled, _isLiveStreamRunning: Boolean( getActiveSession(state, JitsiRecordingConstants.mode.STREAM)), + _tooltip, visible }; } diff --git a/react/features/recording/components/LiveStream/native/LiveStreamButton.js b/react/features/recording/components/LiveStream/native/LiveStreamButton.js index 8f70ae86046e..4c4a140f6ecc 100644 --- a/react/features/recording/components/LiveStream/native/LiveStreamButton.js +++ b/react/features/recording/components/LiveStream/native/LiveStreamButton.js @@ -2,19 +2,8 @@ import { LIVE_STREAMING_ENABLED, getFeatureFlag } from '../../../../base/flags'; import { translate } from '../../../../base/i18n'; -import { IconLiveStreaming } from '../../../../base/icons'; import { connect } from '../../../../base/redux'; -import AbstractLiveStreamButton, { - _mapStateToProps as _abstractMapStateToProps, - type Props -} from '../AbstractLiveStreamButton'; - -/** - * An implementation of a button for starting and stopping live streaming. - */ -class LiveStreamButton extends AbstractLiveStreamButton { - icon = IconLiveStreaming; -} +import AbstractLiveStreamButton, { _mapStateToProps as _abstractMapStateToProps } from '../AbstractLiveStreamButton'; /** * Maps (parts of) the redux state to the associated props for this component. @@ -35,4 +24,4 @@ export function mapStateToProps(state: Object, ownProps: Object) { }; } -export default translate(connect(mapStateToProps)(LiveStreamButton)); +export default translate(connect(mapStateToProps)(AbstractLiveStreamButton)); diff --git a/react/features/recording/components/LiveStream/web/LiveStreamButton.js b/react/features/recording/components/LiveStream/web/LiveStreamButton.js index 2b336c993633..f005f105992a 100644 --- a/react/features/recording/components/LiveStream/web/LiveStreamButton.js +++ b/react/features/recording/components/LiveStream/web/LiveStreamButton.js @@ -1,61 +1,14 @@ // @flow import { translate } from '../../../../base/i18n'; -import { IconLiveStreaming } from '../../../../base/icons'; import { connect } from '../../../../base/redux'; import AbstractLiveStreamButton, { _mapStateToProps as _abstractMapStateToProps, - type Props as AbstractProps + type Props } from '../AbstractLiveStreamButton'; declare var interfaceConfig: Object; -type Props = AbstractProps & { - - /** - * True if the button should be disabled, false otherwise. - * - * NOTE: On web, if the feature is not disabled on purpose, then we still - * show the button but disabled and with a tooltip rendered on it, - * explaining why it's not available. - */ - _disabled: boolean, - - /** - * Tooltip for the button when it's disabled in a certain way. - */ - _liveStreamDisabledTooltipKey: ?string -} - -/** - * An implementation of a button for starting and stopping live streaming. - */ -class LiveStreamButton extends AbstractLiveStreamButton { - icon = IconLiveStreaming; - - /** - * Returns the tooltip that should be displayed when the button is disabled. - * - * @private - * @returns {string} - */ - _getTooltip() { - return this.props._liveStreamDisabledTooltipKey || ''; - } - - /** - * Helper function to be implemented by subclasses, which must return a - * boolean value indicating if this button is disabled or not. - * - * @override - * @protected - * @returns {boolean} - */ - _isDisabled() { - return this.props._disabled; - } -} - /** * Maps (parts of) the redux state to the associated props for the * {@code LiveStreamButton} component. @@ -74,37 +27,14 @@ function _mapStateToProps(state: Object, ownProps: Props) { const abstractProps = _abstractMapStateToProps(state, ownProps); let { visible } = ownProps; - let { _disabled } = abstractProps; - let _liveStreamDisabledTooltipKey; - - if (!abstractProps.visible && _disabled !== undefined && !_disabled) { - _disabled = true; - - // button and tooltip - if (state['features/base/jwt'].isGuest) { - _liveStreamDisabledTooltipKey - = 'dialog.liveStreamingDisabledForGuestTooltip'; - } else { - _liveStreamDisabledTooltipKey - = 'dialog.liveStreamingDisabledTooltip'; - } - } else if (_disabled) { - _liveStreamDisabledTooltipKey = 'dialog.liveStreamingDisabledBecauseOfActiveRecordingTooltip'; - } else { - _disabled = false; - } - if (typeof visible === 'undefined') { - visible = interfaceConfig.TOOLBAR_BUTTONS.includes('livestreaming') - && (abstractProps.visible || Boolean(_liveStreamDisabledTooltipKey)); + visible = interfaceConfig.TOOLBAR_BUTTONS.includes('livestreaming') && abstractProps.visible; } return { ...abstractProps, - _disabled, - _liveStreamDisabledTooltipKey, visible }; } -export default translate(connect(_mapStateToProps)(LiveStreamButton)); +export default translate(connect(_mapStateToProps)(AbstractLiveStreamButton)); diff --git a/react/features/recording/components/Recording/AbstractRecordButton.js b/react/features/recording/components/Recording/AbstractRecordButton.js index da03c990c9e4..8f669ad620b0 100644 --- a/react/features/recording/components/Recording/AbstractRecordButton.js +++ b/react/features/recording/components/Recording/AbstractRecordButton.js @@ -5,6 +5,7 @@ import { sendAnalytics } from '../../../analytics'; import { openDialog } from '../../../base/dialog'; +import { IconToggleRecording } from '../../../base/icons'; import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; import { getLocalParticipant, @@ -34,6 +35,11 @@ export type Props = AbstractButtonProps & { */ _isRecordingRunning: boolean, + /** + * The tooltip to display when hovering over the button. + */ + _tooltip: ?String, + /** * The redux {@code dispatch} function. */ @@ -48,12 +54,22 @@ export type Props = AbstractButtonProps & { /** * An abstract implementation of a button for starting and stopping recording. */ -export default class AbstractRecordButton - extends AbstractButton { +export default class AbstractRecordButton extends AbstractButton { accessibilityLabel = 'toolbar.accessibilityLabel.recording'; + icon = IconToggleRecording; label = 'dialog.startRecording'; toggledLabel = 'dialog.stopRecording'; + /** + * Returns the tooltip that should be displayed when the button is disabled. + * + * @private + * @returns {string} + */ + _getTooltip() { + return this.props._tooltip || ''; + } + /** * Handles clicking / pressing the button. * @@ -85,7 +101,7 @@ export default class AbstractRecordButton * @returns {boolean} */ _isDisabled() { - return false; + return this.props._disabled; } /** @@ -119,6 +135,7 @@ export function _mapStateToProps(state: Object, ownProps: Props): Object { // a button can be disabled/enabled if enableFeaturesBasedOnToken // is on or if the livestreaming is running. let _disabled; + let _tooltip = ''; if (typeof visible === 'undefined') { // If the containing component provides the visible prop, that is one @@ -136,17 +153,30 @@ export function _mapStateToProps(state: Object, ownProps: Props): Object { if (enableFeaturesBasedOnToken) { visible = visible && String(features.recording) === 'true'; _disabled = String(features.recording) === 'disabled'; + if (!visible && !_disabled) { + _disabled = true; + visible = true; + + // button and tooltip + if (state['features/base/jwt'].isGuest) { + _tooltip = 'dialog.recordingDisabledForGuestTooltip'; + } else { + _tooltip = 'dialog.recordingDisabledTooltip'; + } + } } } // disable the button if the livestreaming is running. if (getActiveSession(state, JitsiRecordingConstants.mode.STREAM)) { _disabled = true; + _tooltip = 'dialog.recordingDisabledBecauseOfActiveLiveStreamingTooltip'; } return { _disabled, _isRecordingRunning: Boolean(getActiveSession(state, JitsiRecordingConstants.mode.FILE)), + _tooltip, visible }; } diff --git a/react/features/recording/components/Recording/native/RecordButton.js b/react/features/recording/components/Recording/native/RecordButton.js index 986c06f1e784..bac62a2768a1 100644 --- a/react/features/recording/components/Recording/native/RecordButton.js +++ b/react/features/recording/components/Recording/native/RecordButton.js @@ -4,19 +4,8 @@ import { Platform } from 'react-native'; import { IOS_RECORDING_ENABLED, RECORDING_ENABLED, getFeatureFlag } from '../../../../base/flags'; import { translate } from '../../../../base/i18n'; -import { IconToggleRecording } from '../../../../base/icons'; import { connect } from '../../../../base/redux'; -import AbstractRecordButton, { - _mapStateToProps as _abstractMapStateToProps, - type Props -} from '../AbstractRecordButton'; - -/** - * An implementation of a button for starting and stopping recording. - */ -class RecordButton extends AbstractRecordButton { - icon = IconToggleRecording; -} +import AbstractRecordButton, { _mapStateToProps as _abstractMapStateToProps } from '../AbstractRecordButton'; /** * Maps (parts of) the redux state to the associated props for this component. @@ -38,4 +27,4 @@ export function mapStateToProps(state: Object, ownProps: Object) { }; } -export default translate(connect(mapStateToProps)(RecordButton)); +export default translate(connect(mapStateToProps)(AbstractRecordButton)); diff --git a/react/features/recording/components/Recording/web/RecordButton.js b/react/features/recording/components/Recording/web/RecordButton.js index 45b3878fcdc4..d142cfbc52d2 100644 --- a/react/features/recording/components/Recording/web/RecordButton.js +++ b/react/features/recording/components/Recording/web/RecordButton.js @@ -1,61 +1,14 @@ // @flow import { translate } from '../../../../base/i18n'; -import { IconToggleRecording } from '../../../../base/icons'; import { connect } from '../../../../base/redux'; import AbstractRecordButton, { _mapStateToProps as _abstractMapStateToProps, - type Props as AbstractProps + type Props } from '../AbstractRecordButton'; declare var interfaceConfig: Object; -type Props = AbstractProps & { - - /** - * True if the button should be disabled, false otherwise. - * - * NOTE: On web, if the feature is not disabled on purpose, then we still - * show the button but disabled and with a tooltip rendered on it, - * explaining why it's not available. - */ - _disabled: boolean, - - /** - * Tooltip for the button when it's disabled in a certain way. - */ - _fileRecordingsDisabledTooltipKey: ?string -} - -/** - * An implementation of a button for starting and stopping recording. - */ -class RecordButton extends AbstractRecordButton { - icon = IconToggleRecording; - - /** - * Returns the tooltip that should be displayed when the button is disabled. - * - * @private - * @returns {string} - */ - _getTooltip() { - return this.props._fileRecordingsDisabledTooltipKey || ''; - } - - /** - * Helper function to be implemented by subclasses, which must return a - * boolean value indicating if this button is disabled or not. - * - * @override - * @protected - * @returns {boolean} - */ - _isDisabled() { - return this.props._disabled; - } -} - /** * Maps (parts of) the redux state to the associated props for the * {@code RecordButton} component. @@ -74,35 +27,14 @@ export function _mapStateToProps(state: Object, ownProps: Props): Object { const abstractProps = _abstractMapStateToProps(state, ownProps); let { visible } = ownProps; - let { _disabled } = abstractProps; - let _fileRecordingsDisabledTooltipKey; - - if (!abstractProps.visible && _disabled !== undefined && !_disabled) { - _disabled = true; - - // button and tooltip - if (state['features/base/jwt'].isGuest) { - _fileRecordingsDisabledTooltipKey = 'dialog.recordingDisabledForGuestTooltip'; - } else { - _fileRecordingsDisabledTooltipKey = 'dialog.recordingDisabledTooltip'; - } - } else if (_disabled) { - _fileRecordingsDisabledTooltipKey = 'dialog.recordingDisabledBecauseOfActiveLiveStreamingTooltip'; - } else { - _disabled = false; - } - if (typeof visible === 'undefined') { - visible = interfaceConfig.TOOLBAR_BUTTONS.includes('recording') - && (abstractProps.visible || Boolean(_fileRecordingsDisabledTooltipKey)); + visible = interfaceConfig.TOOLBAR_BUTTONS.includes('recording') && abstractProps.visible; } return { ...abstractProps, - visible, - _disabled, - _fileRecordingsDisabledTooltipKey + visible }; } -export default translate(connect(_mapStateToProps)(RecordButton)); +export default translate(connect(_mapStateToProps)(AbstractRecordButton));