mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-05-17 21:17:46 +00:00
* fix(vertical-filmstrip): different label animations for filmstrip states Instead of one timing for sliding the video status label left and right, have different timings depending on the filmstrip state. To facilitate triggering the different animations, add more classes to the labels that need to move that specify the filmstrip state. - Faster transition if focusing on self-view with videos present so the label does not overlap videos transitioning from 0 opacity. - Transition delay when de-focusing on self-view with videos present so videos have time to go away before the label moves over them. - Maintain no movement if there are no videos, regardless of filmstrip toggle state. - Different delays for when the filmstrip is being toggled visible and hidden if there are remote videos visible. * SQUASH: remove remote videos count * SQUASH: add docs to scss
225 lines
6.7 KiB
JavaScript
225 lines
6.7 KiB
JavaScript
import React, { Component } from 'react';
|
|
import { connect } from 'react-redux';
|
|
|
|
import { toggleAudioOnly } from '../../base/conference';
|
|
import { translate } from '../../base/i18n';
|
|
|
|
/**
|
|
* React {@code Component} responsible for displaying a label that indicates
|
|
* the displayed video state of the current conference. {@code AudioOnlyLabel}
|
|
* will display when the conference is in audio only mode. {@code HDVideoLabel}
|
|
* will display if not in audio only mode and a high-definition large video is
|
|
* being displayed.
|
|
*/
|
|
export class VideoStatusLabel extends Component {
|
|
/**
|
|
* {@code VideoStatusLabel}'s property types.
|
|
*
|
|
* @static
|
|
*/
|
|
static propTypes = {
|
|
/**
|
|
* Whether or not the conference is in audio only mode.
|
|
*/
|
|
_audioOnly: React.PropTypes.bool,
|
|
|
|
/**
|
|
* Whether or not a connection to a conference has been established.
|
|
*/
|
|
_conferenceStarted: React.PropTypes.bool,
|
|
|
|
/**
|
|
* Whether or not the filmstrip is displayed with remote videos. Used to
|
|
* determine display classes to set.
|
|
*/
|
|
_filmstripVisible: React.PropTypes.bool,
|
|
|
|
/**
|
|
* Whether or not a high-definition large video is displayed.
|
|
*/
|
|
_largeVideoHD: React.PropTypes.bool,
|
|
|
|
/**
|
|
* Whether or note remote videos are visible in the filmstrip,
|
|
* regardless of count. Used to determine display classes to set.
|
|
*/
|
|
_remoteVideosVisible: React.PropTypes.bool,
|
|
|
|
/**
|
|
* Invoked to request toggling of audio only mode.
|
|
*/
|
|
dispatch: React.PropTypes.func,
|
|
|
|
/**
|
|
* Invoked to obtain translated strings.
|
|
*/
|
|
t: React.PropTypes.func
|
|
}
|
|
|
|
/**
|
|
* Initializes a new {@code VideoStatusLabel} instance.
|
|
*
|
|
* @param {Object} props - The read-only React Component props with which
|
|
* the new instance is to be initialized.
|
|
*/
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
// Whether or not the filmstrip is transitioning from not visible
|
|
// to visible. Used to set a transition class for animation.
|
|
togglingToVisible: false
|
|
};
|
|
|
|
// Bind event handler so it is only bound once for every instance.
|
|
this._toggleAudioOnly = this._toggleAudioOnly.bind(this);
|
|
}
|
|
|
|
/**
|
|
* Updates the state for whether or not the filmstrip is being toggled to
|
|
* display after having being hidden.
|
|
*
|
|
* @inheritdoc
|
|
* @param {Object} nextProps - The read-only props which this Component will
|
|
* receive.
|
|
* @returns {void}
|
|
*/
|
|
componentWillReceiveProps(nextProps) {
|
|
this.setState({
|
|
togglingToVisible: nextProps._filmstripVisible
|
|
&& !this.props._filmstripVisible
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Implements React's {@link Component#render()}.
|
|
*
|
|
* @inheritdoc
|
|
* @returns {ReactElement}
|
|
*/
|
|
render() {
|
|
const {
|
|
_audioOnly,
|
|
_conferenceStarted,
|
|
_filmstripVisible,
|
|
_remoteVideosVisible,
|
|
_largeVideoHD,
|
|
t
|
|
} = this.props;
|
|
|
|
// FIXME The _conferenceStarted check is used to be defensive against
|
|
// toggling audio only mode while there is no conference and hides the
|
|
// need for error handling around audio only mode toggling.
|
|
if (!_conferenceStarted) {
|
|
return null;
|
|
}
|
|
|
|
let displayedLabel;
|
|
|
|
if (_audioOnly) {
|
|
displayedLabel = <i className = 'icon-visibility-off' />;
|
|
} else {
|
|
displayedLabel = _largeVideoHD
|
|
? t('videoStatus.hd') : t('videoStatus.sd');
|
|
}
|
|
|
|
// Determine which classes should be set on the component. These classes
|
|
// will used to help with animations and setting position.
|
|
const baseClasses = 'video-state-indicator moveToCorner';
|
|
const filmstrip
|
|
= _filmstripVisible ? 'with-filmstrip' : 'without-filmstrip';
|
|
const remoteVideosVisible = _remoteVideosVisible
|
|
? 'with-remote-videos'
|
|
: 'without-remote-videos';
|
|
const opening = this.state.togglingToVisible ? 'opening' : '';
|
|
const classNames
|
|
= `${baseClasses} ${filmstrip} ${remoteVideosVisible} ${opening}`;
|
|
|
|
return (
|
|
<div
|
|
className = { classNames }
|
|
id = 'videoResolutionLabel' >
|
|
{ displayedLabel }
|
|
{ this._renderVideonMenu() }
|
|
</div>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Renders a dropdown menu for changing video modes.
|
|
*
|
|
* @private
|
|
* @returns {ReactElement}
|
|
*/
|
|
_renderVideonMenu() {
|
|
const { _audioOnly, t } = this.props;
|
|
const audioOnlyAttributes = _audioOnly ? { className: 'active' }
|
|
: { onClick: this._toggleAudioOnly };
|
|
const videoAttributes = _audioOnly ? { onClick: this._toggleAudioOnly }
|
|
: { className: 'active' };
|
|
|
|
return (
|
|
<div className = 'video-state-indicator-menu'>
|
|
<div className = 'video-state-indicator-menu-options'>
|
|
<div { ...audioOnlyAttributes }>
|
|
<i className = 'icon-visibility' />
|
|
{ t('audioOnly.audioOnly') }
|
|
</div>
|
|
<div { ...videoAttributes }>
|
|
<i className = 'icon-camera' />
|
|
{ this.props._largeVideoHD
|
|
? t('videoStatus.hdVideo')
|
|
: t('videoStatus.sdVideo') }
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Dispatches an action to toggle the state of audio only mode.
|
|
*
|
|
* @private
|
|
* @returns {void}
|
|
*/
|
|
_toggleAudioOnly() {
|
|
this.props.dispatch(toggleAudioOnly());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Maps (parts of) the Redux state to the associated {@code VideoStatusLabel}'s
|
|
* props.
|
|
*
|
|
* @param {Object} state - The Redux state.
|
|
* @private
|
|
* @returns {{
|
|
* _audioOnly: boolean,
|
|
* _conferenceStarted: boolean,
|
|
* _filmstripVisible: true,
|
|
* _largeVideoHD: (boolean|undefined),
|
|
* _remoteVideosVisible: boolean
|
|
* }}
|
|
*/
|
|
function _mapStateToProps(state) {
|
|
const {
|
|
audioOnly,
|
|
conference,
|
|
isLargeVideoHD
|
|
} = state['features/base/conference'];
|
|
const {
|
|
remoteVideosVisible,
|
|
visible
|
|
} = state['features/filmstrip'];
|
|
|
|
return {
|
|
_audioOnly: audioOnly,
|
|
_conferenceStarted: Boolean(conference),
|
|
_filmstripVisible: visible,
|
|
_largeVideoHD: isLargeVideoHD,
|
|
_remoteVideosVisible: remoteVideosVisible
|
|
};
|
|
}
|
|
|
|
export default translate(connect(_mapStateToProps)(VideoStatusLabel));
|