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
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<P: Props>
extends AbstractButton<P, *> {
export default class AbstractLiveStreamButton<P: Props> extends AbstractButton<P, *> {
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<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.
*
@ -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
};
}

View File

@ -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<Props> {
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));

View File

@ -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<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
* {@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));

View File

@ -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<P: Props>
extends AbstractButton<P, *> {
export default class AbstractRecordButton<P: Props> extends AbstractButton<P, *> {
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<P: Props>
* @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
};
}

View File

@ -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<Props> {
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));

View File

@ -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<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
* {@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));