[RN] Add RecordingLabel indicator for mobile
This commit is contained in:
parent
118250750a
commit
5499599720
|
@ -10,6 +10,7 @@ import { appNavigate } from '../../app';
|
||||||
import { connect, disconnect } from '../../base/connection';
|
import { connect, disconnect } from '../../base/connection';
|
||||||
import { DialogContainer } from '../../base/dialog';
|
import { DialogContainer } from '../../base/dialog';
|
||||||
import { CalleeInfoContainer } from '../../base/jwt';
|
import { CalleeInfoContainer } from '../../base/jwt';
|
||||||
|
import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
|
||||||
import { getParticipantCount } from '../../base/participants';
|
import { getParticipantCount } from '../../base/participants';
|
||||||
import { Container, LoadingIndicator, TintedView } from '../../base/react';
|
import { Container, LoadingIndicator, TintedView } from '../../base/react';
|
||||||
import { TestConnectionInfo } from '../../base/testing';
|
import { TestConnectionInfo } from '../../base/testing';
|
||||||
|
@ -17,6 +18,7 @@ import { createDesiredLocalTracks } from '../../base/tracks';
|
||||||
import { ConferenceNotification } from '../../calendar-sync';
|
import { ConferenceNotification } from '../../calendar-sync';
|
||||||
import { Filmstrip } from '../../filmstrip';
|
import { Filmstrip } from '../../filmstrip';
|
||||||
import { LargeVideo } from '../../large-video';
|
import { LargeVideo } from '../../large-video';
|
||||||
|
import { RecordingLabel } from '../../recording';
|
||||||
import { setToolboxVisible, Toolbox } from '../../toolbox';
|
import { setToolboxVisible, Toolbox } from '../../toolbox';
|
||||||
import { VideoQualityLabel } from '../../video-quality';
|
import { VideoQualityLabel } from '../../video-quality';
|
||||||
|
|
||||||
|
@ -246,7 +248,14 @@ class Conference extends Component<Props> {
|
||||||
* participants.
|
* participants.
|
||||||
*/}
|
*/}
|
||||||
<Filmstrip />
|
<Filmstrip />
|
||||||
<VideoQualityLabel style = { styles.videoQualityLabel } />
|
|
||||||
|
<View style = { styles.indicatorContainer }>
|
||||||
|
<RecordingLabel
|
||||||
|
mode = { JitsiRecordingConstants.mode.FILE } />
|
||||||
|
<RecordingLabel
|
||||||
|
mode = { JitsiRecordingConstants.mode.STREAM } />
|
||||||
|
<VideoQualityLabel />
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<TestConnectionInfo />
|
<TestConnectionInfo />
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,18 @@ export default createStyleSheet({
|
||||||
flex: 1
|
flex: 1
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View that contains the indicators.
|
||||||
|
*/
|
||||||
|
indicatorContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
margin: BoxModel.margin,
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
top: 0
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The style of the {@link View} which expands over the whole
|
* The style of the {@link View} which expands over the whole
|
||||||
* {@link Conference} area and splits it between the {@link Filmstrip} and
|
* {@link Conference} area and splits it between the {@link Filmstrip} and
|
||||||
|
@ -35,11 +47,5 @@ export default createStyleSheet({
|
||||||
// On iPhone X there is the notch. In the two cases BoxModel.margin is
|
// On iPhone X there is the notch. In the two cases BoxModel.margin is
|
||||||
// not enough.
|
// not enough.
|
||||||
top: BoxModel.margin * 3
|
top: BoxModel.margin * 3
|
||||||
},
|
|
||||||
|
|
||||||
videoQualityLabel: {
|
|
||||||
right: 0,
|
|
||||||
top: 0,
|
|
||||||
position: 'absolute'
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { Component } from 'react';
|
||||||
|
|
||||||
|
import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
export type Props = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if there is an active recording with the provided mode therefore the
|
||||||
|
* component must be rendered.
|
||||||
|
*/
|
||||||
|
_visible: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The recording mode this indicator should display.
|
||||||
|
*/
|
||||||
|
mode: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked to obtain translated strings.
|
||||||
|
*/
|
||||||
|
t: Function
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract class for the {@code RecordingLabel} component.
|
||||||
|
*/
|
||||||
|
export default class AbstractRecordingLabel<P: Props, S: *>
|
||||||
|
extends Component<P, S> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {{
|
||||||
|
* _visible: boolean
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
export function _abstractMapStateToProps(state: Object, ownProps: Props) {
|
||||||
|
const { mode } = ownProps;
|
||||||
|
const _recordingSessions = state['features/recording'].sessionDatas;
|
||||||
|
const _visible
|
||||||
|
= Array.isArray(_recordingSessions)
|
||||||
|
&& _recordingSessions.some(
|
||||||
|
session => session.status === JitsiRecordingConstants.status.ON
|
||||||
|
&& session.mode === mode
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
_visible
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { translate } from '../../base/i18n';
|
||||||
|
import { CircularLabel } from '../../base/label';
|
||||||
|
import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
|
||||||
|
import { combineStyles } from '../../base/styles';
|
||||||
|
|
||||||
|
import AbstractRecordingLabel, {
|
||||||
|
type Props as AbstractProps,
|
||||||
|
_abstractMapStateToProps
|
||||||
|
} from './AbstractRecordingLabel';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
|
type Props = AbstractProps & {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Style of the component passed as props.
|
||||||
|
*/
|
||||||
|
style: ?Object
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a React {@link Component} which displays the current state of
|
||||||
|
* conference recording.
|
||||||
|
*
|
||||||
|
* @extends {Component}
|
||||||
|
*/
|
||||||
|
class RecordingLabel extends AbstractRecordingLabel<Props, *> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements React {@code Component}'s render.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
const { _visible, mode, style, t } = this.props;
|
||||||
|
|
||||||
|
if (!_visible) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let labelKey;
|
||||||
|
let indicatorStyle;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case JitsiRecordingConstants.mode.STREAM:
|
||||||
|
labelKey = 'recording.live';
|
||||||
|
indicatorStyle = styles.indicatorLive;
|
||||||
|
break;
|
||||||
|
case JitsiRecordingConstants.mode.FILE:
|
||||||
|
labelKey = 'recording.rec';
|
||||||
|
indicatorStyle = styles.indicatorRecording;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Invalid mode is passed to the component.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CircularLabel
|
||||||
|
label = { t(labelKey) }
|
||||||
|
style = {
|
||||||
|
combineStyles(indicatorStyle, style)
|
||||||
|
} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps (parts of) the Redux state to the associated
|
||||||
|
* {@code RecordingLabel}'s props.
|
||||||
|
*
|
||||||
|
* NOTE: This component has no props other than the abstract ones but keeping
|
||||||
|
* the coding style the same for consistency reasons.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The Redux state.
|
||||||
|
* @param {Object} ownProps - The component's own props.
|
||||||
|
* @private
|
||||||
|
* @returns {{
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
function _mapStateToProps(state: Object, ownProps: Object) {
|
||||||
|
return {
|
||||||
|
..._abstractMapStateToProps(state, ownProps)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translate(connect(_mapStateToProps)(RecordingLabel));
|
|
@ -1,11 +1,17 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { CircularLabel } from '../../base/label';
|
import { CircularLabel } from '../../base/label';
|
||||||
import { translate } from '../../base/i18n';
|
import { translate } from '../../base/i18n';
|
||||||
import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
|
import { JitsiRecordingConstants } from '../../base/lib-jitsi-meet';
|
||||||
|
|
||||||
|
import AbstractRecordingLabel, {
|
||||||
|
type Props as AbstractProps,
|
||||||
|
_abstractMapStateToProps
|
||||||
|
} from './AbstractRecordingLabel';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The translation keys to use when displaying messages. The values are set
|
* The translation keys to use when displaying messages. The values are set
|
||||||
* lazily to work around circular dependency issues with lib-jitsi-meet causing
|
* lazily to work around circular dependency issues with lib-jitsi-meet causing
|
||||||
|
@ -61,7 +67,7 @@ function _getTranslationKeysByMode() {
|
||||||
/**
|
/**
|
||||||
* The type of the React {@code Component} props of {@link RecordingLabel}.
|
* The type of the React {@code Component} props of {@link RecordingLabel}.
|
||||||
*/
|
*/
|
||||||
type Props = {
|
type Props = AbstractProps & {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The redux representation of a recording session.
|
* The redux representation of a recording session.
|
||||||
|
@ -91,7 +97,7 @@ type State = {
|
||||||
*
|
*
|
||||||
* @extends {Component}
|
* @extends {Component}
|
||||||
*/
|
*/
|
||||||
class RecordingLabel extends Component<Props, State> {
|
class RecordingLabel extends AbstractRecordingLabel<Props, State> {
|
||||||
_autohideTimeout: number;
|
_autohideTimeout: number;
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -219,4 +225,23 @@ class RecordingLabel extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default translate(RecordingLabel);
|
/**
|
||||||
|
* Maps (parts of) the Redux state to the associated
|
||||||
|
* {@code RecordingLabel}'s props.
|
||||||
|
*
|
||||||
|
* NOTE: This component has no props other than the abstract ones but keeping
|
||||||
|
* the coding style the same for consistency reasons.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The Redux state.
|
||||||
|
* @param {Object} ownProps - The component's own props.
|
||||||
|
* @private
|
||||||
|
* @returns {{
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
function _mapStateToProps(state: Object, ownProps: Object) {
|
||||||
|
return {
|
||||||
|
..._abstractMapStateToProps(state, ownProps)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translate(connect(_mapStateToProps)(RecordingLabel));
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { ColorPalette, createStyleSheet } from '../../base/styles';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The styles of the React {@code Components} of the feature recording.
|
||||||
|
*/
|
||||||
|
export default createStyleSheet({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Style for the recording indicator.
|
||||||
|
*/
|
||||||
|
indicatorLive: {
|
||||||
|
backgroundColor: ColorPalette.blue
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Style for the recording indicator.
|
||||||
|
*/
|
||||||
|
indicatorRecording: {
|
||||||
|
backgroundColor: ColorPalette.red
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in New Issue