jiti-meet/react/features/recording/components/AbstractRecordingLabel.js

206 lines
5.1 KiB
JavaScript

// @flow
import { Component } from 'react';
import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
import { getSessionStatusToShow } from '../functions';
/**
* NOTE: Web currently renders multiple indicators if multiple recording
* sessions are running. This is however may not be a good UX as it's not
* obvious why there are multiple similar 'REC' indicators rendered. Mobile
* only renders one indicator if there is at least one recording session
* running. These boolean are shared across the two components to make it
* easier to align web's behaviour to mobile's later if necessary.
*/
type Props = {
/**
* Whether this is the Jibri recorder participant.
*/
_iAmRecorder: boolean,
/**
* The status of the highermost priority session.
*/
_status: ?string,
/**
* An object containing the CSS classes.
*/
classes: ?{[ key: string]: string},
/**
* The recording mode this indicator should display.
*/
mode: string,
/**
* Invoked to obtain translated strings.
*/
t: Function
};
/**
* State of the component.
*/
type State = {
/**
* True if the label status is stale, so it needs to be removed.
*/
staleLabel: boolean
};
/**
* The timeout after a label is considered stale. See {@code _updateStaleStatus}
* for more details.
*/
const STALE_TIMEOUT = 10 * 1000;
/**
* Abstract class for the {@code RecordingLabel} component.
*/
export default class AbstractRecordingLabel
extends Component<Props, State> {
/**
* Implements {@code Component#getDerivedStateFromProps}.
*
* @inheritdoc
*/
static getDerivedStateFromProps(props: Props, prevState: State) {
return {
staleLabel: props._status !== JitsiRecordingConstants.status.OFF
&& prevState.staleLabel ? false : prevState.staleLabel
};
}
/**
* Initializes a new {@code AbstractRecordingLabel} component.
*
* @inheritdoc
*/
constructor(props: Props) {
super(props);
this.state = {
staleLabel: true
};
this._updateStaleStatus({}, props);
}
/**
* Implements React {@code Component}'s componentDidMount.
*
* @inheritdoc
*/
componentDidMount() {
this._mounted = true;
}
/**
* Implements React {@code Component}'s componentWillUnmount.
*
* @inheritdoc
*/
componentWillUnmount() {
this._mounted = false;
}
/**
* Implements {@code Component#componentDidUpdate}.
*
* @inheritdoc
*/
componentDidUpdate(prevProps: Props) {
this._updateStaleStatus(prevProps, this.props);
}
/**
* Implements React {@code Component}'s render.
*
* @inheritdoc
*/
render() {
return this.props._status && !this.state.staleLabel && !this.props._iAmRecorder
? this._renderLabel() : null;
}
_getLabelKey: () => ?string;
/**
* Returns the label key that this indicator should render.
*
* @protected
* @returns {?string}
*/
_getLabelKey() {
switch (this.props.mode) {
case JitsiRecordingConstants.mode.STREAM:
return 'recording.live';
case JitsiRecordingConstants.mode.FILE:
return 'recording.rec';
default:
// Invalid mode is passed to the component.
return undefined;
}
}
/**
* Renders the platform specific label component.
*
* @protected
* @returns {React$Element}
*/
_renderLabel: () => React$Element<*>;
/**
* Updates the stale status of the label on a prop change. A label is stale
* if it's in a {@code _status} that doesn't need to be rendered anymore.
*
* @param {Props} oldProps - The previous props of the component.
* @param {Props} newProps - The new props of the component.
* @returns {void}
*/
_updateStaleStatus(oldProps, newProps) {
if (newProps._status === JitsiRecordingConstants.status.OFF) {
if (oldProps._status !== JitsiRecordingConstants.status.OFF) {
setTimeout(() => {
if (!this._mounted) {
return;
}
// Only if it's still OFF.
if (this.props._status
=== JitsiRecordingConstants.status.OFF) {
this.setState({
staleLabel: true
});
}
}, STALE_TIMEOUT);
}
}
}
}
/**
* Maps (parts of) the Redux state to the associated
* {@code AbstractRecordingLabel}'s props.
*
* @param {Object} state - The Redux state.
* @param {Props} ownProps - The component's own props.
* @private
* @returns {{
* _status: ?string
* }}
*/
export function _mapStateToProps(state: Object, ownProps: Props) {
const { mode } = ownProps;
return {
_iAmRecorder: state['features/base/config'].iAmRecorder,
_status: getSessionStatusToShow(state, mode)
};
}