fix(record):web/mobile match disable functionality

This commit is contained in:
Hristo Terezov 2020-04-29 17:35:27 -05:00
parent ce1de9e1e7
commit a2c4d17e4d
6 changed files with 87 additions and 176 deletions

View File

@ -1,6 +1,7 @@
// @flow // @flow
import { openDialog } from '../../../base/dialog'; import { openDialog } from '../../../base/dialog';
import { IconLiveStreaming } from '../../../base/icons';
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
import { getLocalParticipant } from '../../../base/participants'; import { getLocalParticipant } from '../../../base/participants';
import { import {
@ -30,6 +31,11 @@ export type Props = AbstractButtonProps & {
*/ */
_disabled: Boolean, _disabled: Boolean,
/**
* The tooltip to display when hovering over the button.
*/
_tooltip: ?String,
/** /**
* The redux {@code dispatch} function. * 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. * An abstract class of a button for starting and stopping live streaming.
*/ */
export default class AbstractLiveStreamButton<P: Props> export default class AbstractLiveStreamButton<P: Props> extends AbstractButton<P, *> {
extends AbstractButton<P, *> {
accessibilityLabel = 'dialog.accessibilityLabel.liveStreaming'; accessibilityLabel = 'dialog.accessibilityLabel.liveStreaming';
icon = IconLiveStreaming;
label = 'dialog.startLiveStreaming'; label = 'dialog.startLiveStreaming';
toggledLabel = 'dialog.stopLiveStreaming'; 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. * Handles clicking / pressing the button.
* *
@ -65,6 +81,16 @@ export default class AbstractLiveStreamButton<P: Props>
)); ));
} }
/**
* 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. * 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 // A button can be disabled/enabled only if enableFeaturesBasedOnToken
// is on or if the recording is running. // is on or if the recording is running.
let _disabled; let _disabled;
let _tooltip = '';
if (typeof visible === 'undefined') { if (typeof visible === 'undefined') {
// If the containing component provides the visible prop, that is one // If the containing component provides the visible prop, that is one
@ -112,18 +139,32 @@ export function _mapStateToProps(state: Object, ownProps: Props) {
if (enableFeaturesBasedOnToken) { if (enableFeaturesBasedOnToken) {
visible = visible && String(features.livestreaming) === 'true'; visible = visible && String(features.livestreaming) === 'true';
_disabled = String(features.livestreaming) === 'disabled'; _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. // disable the button if the recording is running.
if (getActiveSession(state, JitsiRecordingConstants.mode.FILE)) { if (getActiveSession(state, JitsiRecordingConstants.mode.FILE)) {
_disabled = true; _disabled = true;
_tooltip = 'dialog.liveStreamingDisabledBecauseOfActiveRecordingTooltip';
} }
return { return {
_disabled, _disabled,
_isLiveStreamRunning: Boolean( _isLiveStreamRunning: Boolean(
getActiveSession(state, JitsiRecordingConstants.mode.STREAM)), getActiveSession(state, JitsiRecordingConstants.mode.STREAM)),
_tooltip,
visible visible
}; };
} }

View File

@ -2,19 +2,8 @@
import { LIVE_STREAMING_ENABLED, getFeatureFlag } from '../../../../base/flags'; import { LIVE_STREAMING_ENABLED, getFeatureFlag } from '../../../../base/flags';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { IconLiveStreaming } from '../../../../base/icons';
import { connect } from '../../../../base/redux'; import { connect } from '../../../../base/redux';
import AbstractLiveStreamButton, { import AbstractLiveStreamButton, { _mapStateToProps as _abstractMapStateToProps } from '../AbstractLiveStreamButton';
_mapStateToProps as _abstractMapStateToProps,
type Props
} from '../AbstractLiveStreamButton';
/**
* An implementation of a button for starting and stopping live streaming.
*/
class LiveStreamButton extends AbstractLiveStreamButton<Props> {
icon = IconLiveStreaming;
}
/** /**
* Maps (parts of) the redux state to the associated props for this component. * 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));

View File

@ -1,61 +1,14 @@
// @flow // @flow
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { IconLiveStreaming } from '../../../../base/icons';
import { connect } from '../../../../base/redux'; import { connect } from '../../../../base/redux';
import AbstractLiveStreamButton, { import AbstractLiveStreamButton, {
_mapStateToProps as _abstractMapStateToProps, _mapStateToProps as _abstractMapStateToProps,
type Props as AbstractProps type Props
} from '../AbstractLiveStreamButton'; } from '../AbstractLiveStreamButton';
declare var interfaceConfig: Object; 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<Props> {
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 * Maps (parts of) the redux state to the associated props for the
* {@code LiveStreamButton} component. * {@code LiveStreamButton} component.
@ -74,37 +27,14 @@ function _mapStateToProps(state: Object, ownProps: Props) {
const abstractProps = _abstractMapStateToProps(state, ownProps); const abstractProps = _abstractMapStateToProps(state, ownProps);
let { visible } = 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') { if (typeof visible === 'undefined') {
visible = interfaceConfig.TOOLBAR_BUTTONS.includes('livestreaming') visible = interfaceConfig.TOOLBAR_BUTTONS.includes('livestreaming') && abstractProps.visible;
&& (abstractProps.visible || Boolean(_liveStreamDisabledTooltipKey));
} }
return { return {
...abstractProps, ...abstractProps,
_disabled,
_liveStreamDisabledTooltipKey,
visible visible
}; };
} }
export default translate(connect(_mapStateToProps)(LiveStreamButton)); export default translate(connect(_mapStateToProps)(AbstractLiveStreamButton));

View File

@ -5,6 +5,7 @@ import {
sendAnalytics sendAnalytics
} from '../../../analytics'; } from '../../../analytics';
import { openDialog } from '../../../base/dialog'; import { openDialog } from '../../../base/dialog';
import { IconToggleRecording } from '../../../base/icons';
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
import { import {
getLocalParticipant, getLocalParticipant,
@ -34,6 +35,11 @@ export type Props = AbstractButtonProps & {
*/ */
_isRecordingRunning: boolean, _isRecordingRunning: boolean,
/**
* The tooltip to display when hovering over the button.
*/
_tooltip: ?String,
/** /**
* The redux {@code dispatch} function. * The redux {@code dispatch} function.
*/ */
@ -48,12 +54,22 @@ export type Props = AbstractButtonProps & {
/** /**
* An abstract implementation of a button for starting and stopping recording. * An abstract implementation of a button for starting and stopping recording.
*/ */
export default class AbstractRecordButton<P: Props> export default class AbstractRecordButton<P: Props> extends AbstractButton<P, *> {
extends AbstractButton<P, *> {
accessibilityLabel = 'toolbar.accessibilityLabel.recording'; accessibilityLabel = 'toolbar.accessibilityLabel.recording';
icon = IconToggleRecording;
label = 'dialog.startRecording'; label = 'dialog.startRecording';
toggledLabel = 'dialog.stopRecording'; 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. * Handles clicking / pressing the button.
* *
@ -85,7 +101,7 @@ export default class AbstractRecordButton<P: Props>
* @returns {boolean} * @returns {boolean}
*/ */
_isDisabled() { _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 // a button can be disabled/enabled if enableFeaturesBasedOnToken
// is on or if the livestreaming is running. // is on or if the livestreaming is running.
let _disabled; let _disabled;
let _tooltip = '';
if (typeof visible === 'undefined') { if (typeof visible === 'undefined') {
// If the containing component provides the visible prop, that is one // 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) { if (enableFeaturesBasedOnToken) {
visible = visible && String(features.recording) === 'true'; visible = visible && String(features.recording) === 'true';
_disabled = String(features.recording) === 'disabled'; _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. // disable the button if the livestreaming is running.
if (getActiveSession(state, JitsiRecordingConstants.mode.STREAM)) { if (getActiveSession(state, JitsiRecordingConstants.mode.STREAM)) {
_disabled = true; _disabled = true;
_tooltip = 'dialog.recordingDisabledBecauseOfActiveLiveStreamingTooltip';
} }
return { return {
_disabled, _disabled,
_isRecordingRunning: Boolean(getActiveSession(state, JitsiRecordingConstants.mode.FILE)), _isRecordingRunning: Boolean(getActiveSession(state, JitsiRecordingConstants.mode.FILE)),
_tooltip,
visible visible
}; };
} }

View File

@ -4,19 +4,8 @@ import { Platform } from 'react-native';
import { IOS_RECORDING_ENABLED, RECORDING_ENABLED, getFeatureFlag } from '../../../../base/flags'; import { IOS_RECORDING_ENABLED, RECORDING_ENABLED, getFeatureFlag } from '../../../../base/flags';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { IconToggleRecording } from '../../../../base/icons';
import { connect } from '../../../../base/redux'; import { connect } from '../../../../base/redux';
import AbstractRecordButton, { import AbstractRecordButton, { _mapStateToProps as _abstractMapStateToProps } from '../AbstractRecordButton';
_mapStateToProps as _abstractMapStateToProps,
type Props
} from '../AbstractRecordButton';
/**
* An implementation of a button for starting and stopping recording.
*/
class RecordButton extends AbstractRecordButton<Props> {
icon = IconToggleRecording;
}
/** /**
* Maps (parts of) the redux state to the associated props for this component. * 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));

View File

@ -1,61 +1,14 @@
// @flow // @flow
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { IconToggleRecording } from '../../../../base/icons';
import { connect } from '../../../../base/redux'; import { connect } from '../../../../base/redux';
import AbstractRecordButton, { import AbstractRecordButton, {
_mapStateToProps as _abstractMapStateToProps, _mapStateToProps as _abstractMapStateToProps,
type Props as AbstractProps type Props
} from '../AbstractRecordButton'; } from '../AbstractRecordButton';
declare var interfaceConfig: Object; 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<Props> {
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 * Maps (parts of) the redux state to the associated props for the
* {@code RecordButton} component. * {@code RecordButton} component.
@ -74,35 +27,14 @@ export function _mapStateToProps(state: Object, ownProps: Props): Object {
const abstractProps = _abstractMapStateToProps(state, ownProps); const abstractProps = _abstractMapStateToProps(state, ownProps);
let { visible } = 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') { if (typeof visible === 'undefined') {
visible = interfaceConfig.TOOLBAR_BUTTONS.includes('recording') visible = interfaceConfig.TOOLBAR_BUTTONS.includes('recording') && abstractProps.visible;
&& (abstractProps.visible || Boolean(_fileRecordingsDisabledTooltipKey));
} }
return { return {
...abstractProps, ...abstractProps,
visible, visible
_disabled,
_fileRecordingsDisabledTooltipKey
}; };
} }
export default translate(connect(_mapStateToProps)(RecordButton)); export default translate(connect(_mapStateToProps)(AbstractRecordButton));