Coding style

This commit is contained in:
Lyubo Marinov 2018-05-03 12:36:29 -05:00
parent 9ca7ca9515
commit a42496ba53
10 changed files with 138 additions and 138 deletions

View File

@ -7,12 +7,12 @@ import Toolbar from './Toolbar';
const { api } = window.alwaysOnTop;
/**
* The timeout in ms for hidding the toolbar.
* The timeout in ms for hiding the toolbar.
*/
const TOOLBAR_TIMEOUT = 4000;
/**
* The type of the React {@code Component} state of {@link FeedbackButton}.
* The type of the React {@code Component} state of {@link AlwaysOnTop}.
*/
type State = {
avatarURL: string,
@ -40,18 +40,18 @@ export default class AlwaysOnTop extends Component<*, State> {
super(props);
this.state = {
visible: true,
avatarURL: '',
displayName: '',
isVideoDisplayed: true,
avatarURL: ''
visible: true
};
// Bind event handlers so they are only bound once per instance.
this._avatarChangedListener = this._avatarChangedListener.bind(this);
this._largeVideoChangedListener
= this._largeVideoChangedListener.bind(this);
this._displayNameChangedListener
= this._displayNameChangedListener.bind(this);
this._largeVideoChangedListener
= this._largeVideoChangedListener.bind(this);
this._mouseMove = this._mouseMove.bind(this);
this._onMouseOut = this._onMouseOut.bind(this);
this._onMouseOver = this._onMouseOver.bind(this);
@ -65,11 +65,8 @@ export default class AlwaysOnTop extends Component<*, State> {
* @returns {void}
*/
_avatarChangedListener({ avatarURL, id }) {
if (api._getOnStageParticipant() !== id) {
return;
}
if (avatarURL !== this.state.avatarURL) {
if (api._getOnStageParticipant() === id
&& avatarURL !== this.state.avatarURL) {
this.setState({ avatarURL });
}
}
@ -82,11 +79,8 @@ export default class AlwaysOnTop extends Component<*, State> {
* @returns {void}
*/
_displayNameChangedListener({ formattedDisplayName, id }) {
if (api._getOnStageParticipant() !== id) {
return;
}
if (formattedDisplayName !== this.state.displayName) {
if (api._getOnStageParticipant() === id
&& formattedDisplayName !== this.state.displayName) {
this.setState({ displayName: formattedDisplayName });
}
}
@ -97,14 +91,15 @@ export default class AlwaysOnTop extends Component<*, State> {
* @returns {void}
*/
_hideToolbarAfterTimeout() {
setTimeout(() => {
if (this._hovered) {
this._hideToolbarAfterTimeout();
return;
}
this.setState({ visible: false });
}, TOOLBAR_TIMEOUT);
setTimeout(
() => {
if (this._hovered) {
this._hideToolbarAfterTimeout();
} else {
this.setState({ visible: false });
}
},
TOOLBAR_TIMEOUT);
}
_largeVideoChangedListener: () => void;
@ -116,8 +111,8 @@ export default class AlwaysOnTop extends Component<*, State> {
*/
_largeVideoChangedListener() {
const userID = api._getOnStageParticipant();
const displayName = api._getFormattedDisplayName(userID);
const avatarURL = api.getAvatarURL(userID);
const displayName = api._getFormattedDisplayName(userID);
const isVideoDisplayed = Boolean(api._getLargeVideo());
this.setState({
@ -135,9 +130,7 @@ export default class AlwaysOnTop extends Component<*, State> {
* @returns {void}
*/
_mouseMove() {
if (!this.state.visible) {
this.setState({ visible: true });
}
this.state.visible || this.setState({ visible: true });
}
_onMouseOut: () => void;
@ -201,9 +194,9 @@ export default class AlwaysOnTop extends Component<*, State> {
* @returns {void}
*/
componentDidMount() {
api.on('largeVideoChanged', this._largeVideoChangedListener);
api.on('displayNameChange', this._displayNameChangedListener);
api.on('avatarChanged', this._avatarChangedListener);
api.on('displayNameChange', this._displayNameChangedListener);
api.on('largeVideoChanged', this._largeVideoChangedListener);
this._largeVideoChangedListener();
@ -219,11 +212,14 @@ export default class AlwaysOnTop extends Component<*, State> {
* @returns {void}
*/
componentWillUnmount() {
api.removeListener('largeVideoChanged',
this._largeVideoChangedListener);
api.removeListener('displayNameChange',
this._displayNameChangedListener);
api.removeListener('avatarChanged', this._avatarChangedListener);
api.removeListener(
'displayNameChange',
this._displayNameChangedListener);
api.removeListener(
'largeVideoChanged',
this._largeVideoChangedListener);
window.removeEventListener('mousemove', this._mouseMove);
}
@ -252,9 +248,7 @@ export default class AlwaysOnTop extends Component<*, State> {
className = { this.state.visible ? 'fadeIn' : 'fadeOut' }
onMouseOut = { this._onMouseOut }
onMouseOver = { this._onMouseOver } />
{
this._renderVideoNotAvailableScreen()
}
{ this._renderVideoNotAvailableScreen() }
</div>
);
}

View File

@ -1,14 +1,16 @@
// @flow
// XXX: AlwaysOnTop imports the button directly in order to avoid bringing in
// other components that use lib-jitsi-meet, which always on top does not
// import.
// XXX Import the button directly in order to avoid bringing in other components
// that use lib-jitsi-meet, which always-on-top does not import.
import AbstractAudioMuteButton
from '../toolbox/components/buttons/AbstractAudioMuteButton';
import type { Props } from '../toolbox/components/buttons/AbstractButton';
const { api } = window.alwaysOnTop;
/**
* The type of the React {@code Component} state of {@link AudioMuteButton}.
*/
type State = {
/**
@ -23,7 +25,7 @@ type State = {
};
/**
* Stateless hangup button for the Always-on-Top windows.
* Stateless "mute/unmute audio" button for the Always-on-Top windows.
*/
export default class AudioMuteButton
extends AbstractAudioMuteButton<Props, State> {
@ -62,14 +64,11 @@ export default class AudioMuteButton
api.isAudioAvailable(),
api.isAudioMuted()
])
.then(values => {
const [ audioAvailable, audioMuted ] = values;
.then(([ audioAvailable, audioMuted ]) =>
this.setState({
audioAvailable,
audioMuted
});
})
}))
.catch(console.error);
}
@ -80,45 +79,14 @@ export default class AudioMuteButton
* @returns {void}
*/
componentWillUnmount() {
api.removeListener('audioAvailabilityChanged',
api.removeListener(
'audioAvailabilityChanged',
this._audioAvailabilityListener);
api.removeListener('audioMuteStatusChanged',
api.removeListener(
'audioMuteStatusChanged',
this._audioMutedListener);
}
/**
* Indicates whether this button is disabled or not.
*
* @override
* @private
* @returns {boolean}
*/
_isDisabled() {
return !this.state.audioAvailable;
}
/**
* Indicates if audio is currently muted ot nor.
*
* @override
* @private
* @returns {boolean}
*/
_isAudioMuted() {
return this.state.audioMuted;
}
/**
* Changes the muted state.
*
* @param {boolean} audioMuted - Whether audio should be muted or not.
* @private
* @returns {void}
*/
_setAudioMuted(audioMuted: boolean) { // eslint-disable-line no-unused-vars
this.state.audioAvailable && api.executeCommand('toggleAudio');
}
_audioAvailabilityListener: ({ available: boolean }) => void;
/**
@ -142,4 +110,37 @@ export default class AudioMuteButton
_audioMutedListener({ muted }) {
this.setState({ audioMuted: muted });
}
/**
* Indicates if audio is currently muted ot nor.
*
* @override
* @private
* @returns {boolean}
*/
_isAudioMuted() {
return this.state.audioMuted;
}
/**
* Indicates whether this button is disabled or not.
*
* @override
* @private
* @returns {boolean}
*/
_isDisabled() {
return !this.state.audioAvailable;
}
/**
* Changes the muted state.
*
* @param {boolean} audioMuted - Whether audio should be muted or not.
* @private
* @returns {void}
*/
_setAudioMuted(audioMuted: boolean) { // eslint-disable-line no-unused-vars
this.state.audioAvailable && api.executeCommand('toggleAudio');
}
}

View File

@ -1,8 +1,7 @@
// @flow
// XXX: AlwaysOnTop imports the button directly in order to avoid bringing in
// other components that use lib-jitsi-meet, which always on top does not
// import.
// XXX Import the button directly in order to avoid bringing in other components
// that use lib-jitsi-meet, which always-on-top does not import.
import AbstractHangupButton
from '../toolbox/components/buttons/AbstractHangupButton';
import type { Props } from '../toolbox/components/buttons/AbstractButton';

View File

@ -24,7 +24,7 @@ type Props = {
/**
* Callback invoked when the mouse has moved over the toolbar.
*/
onMouseOver: Function
onMouseOver: Function
};
/**

View File

@ -1,14 +1,16 @@
// @flow
// XXX: AlwaysOnTop imports the button directly in order to avoid bringing in
// other components that use lib-jitsi-meet, which always on top does not
// import.
// XXX Import the button directly in order to avoid bringing in other components
// that use lib-jitsi-meet, which always-on-top does not import.
import AbstractVideoMuteButton
from '../toolbox/components/buttons/AbstractVideoMuteButton';
import type { Props } from '../toolbox/components/buttons/AbstractButton';
const { api } = window.alwaysOnTop;
/**
* The type of the React {@code Component} state of {@link VideoMuteButton}.
*/
type State = {
/**
@ -23,7 +25,7 @@ type State = {
};
/**
* Stateless hangup button for the Always-on-Top windows.
* Stateless "mute/unmute video" button for the Always-on-Top windows.
*/
export default class VideoMuteButton
extends AbstractVideoMuteButton<Props, State> {
@ -62,14 +64,11 @@ export default class VideoMuteButton
api.isVideoAvailable(),
api.isVideoMuted()
])
.then(values => {
const [ videoAvailable, videoMuted ] = values;
.then(([ videoAvailable, videoMuted ]) =>
this.setState({
videoAvailable,
videoMuted
});
})
}))
.catch(console.error);
}
@ -80,9 +79,11 @@ export default class VideoMuteButton
* @returns {void}
*/
componentWillUnmount() {
api.removeListener('videoAvailabilityChanged',
api.removeListener(
'videoAvailabilityChanged',
this._videoAvailabilityListener);
api.removeListener('videoMuteStatusChanged',
api.removeListener(
'videoMuteStatusChanged',
this._videoMutedListener);
}

View File

@ -1,14 +1,14 @@
// @flow
import React from 'react';
import ReactDOM from 'react-dom';
import AlwaysOnTop from './AlwaysOnTop';
// Render the main/root Component.
ReactDOM.render(
<AlwaysOnTop />,
document.getElementById('react')
);
// $FlowExpectedError
ReactDOM.render(<AlwaysOnTop />, document.getElementById('react'));
window.addEventListener('beforeunload', () => {
ReactDOM.unmountComponentAtNode(document.getElementById('react'));
});
window.addEventListener(
'beforeunload',
() => ReactDOM.unmountComponentAtNode(document.getElementById('react')));

View File

@ -139,10 +139,13 @@ class Conference extends Component<Props> {
render() {
const {
VIDEO_QUALITY_LABEL_DISABLED,
filmStripOnly
// XXX The character casing of the name filmStripOnly utilized by
// interfaceConfig is obsolete but legacy support is required.
filmStripOnly: filmstripOnly
} = interfaceConfig;
const hideVideoQualityLabel
= filmStripOnly
= filmstripOnly
|| VIDEO_QUALITY_LABEL_DISABLED
|| this.props._iAmRecorder;
@ -153,11 +156,11 @@ class Conference extends Component<Props> {
<div id = 'videospace'>
<LargeVideo
hideVideoQualityLabel = { hideVideoQualityLabel } />
<Filmstrip filmstripOnly = { filmStripOnly } />
<Filmstrip filmstripOnly = { filmstripOnly } />
</div>
{ !filmStripOnly && <Toolbox /> }
{ !filmStripOnly && <SidePanel /> }
{ filmstripOnly || <Toolbox /> }
{ filmstripOnly || <SidePanel /> }
<DialogContainer />
<NotificationsContainer />

View File

@ -9,7 +9,6 @@ import { dockToolbox } from '../../toolbox';
import { setFilmstripHovered } from '../actions';
import { shouldRemoteVideosBeVisible } from '../functions';
import Toolbar from './Toolbar';
declare var interfaceConfig: Object;
@ -36,9 +35,9 @@ class Filmstrip extends Component<*> {
*/
static propTypes = {
/**
* Whether or not the conference is in filmstripOnly mode.
* Whether the UI/UX is filmstrip-only.
*/
_filmStripOnly: PropTypes.bool,
_filmstripOnly: PropTypes.bool,
/**
* Whether or not remote videos are currently being hovered over.
@ -58,7 +57,7 @@ class Filmstrip extends Component<*> {
_toolboxVisible: PropTypes.bool,
/**
* Updates the redux store with filmstrip hover changes.
* The redux {@code dispatch} function.
*/
dispatch: PropTypes.func
};
@ -85,8 +84,8 @@ class Filmstrip extends Component<*> {
this._isHovered = false;
// Bind event handlers so they are only bound once for every instance.
this._onMouseOver = this._onMouseOver.bind(this);
this._onMouseOut = this._onMouseOut.bind(this);
this._onMouseOver = this._onMouseOver.bind(this);
}
/**
@ -97,27 +96,27 @@ class Filmstrip extends Component<*> {
*/
render() {
const {
_filmStripOnly,
_filmstripOnly,
_remoteVideosVisible,
_toolboxVisible
} = this.props;
/**
* Note: Appending of {@code RemoteVideo} views is handled through
* VideoLayout. The views do not get blown away on render() because
* ReactDOMComponent is only aware of the given JSX and not new appended
* DOM. As such, when updateDOMProperties gets called, only attributes
* will get updated without replacing the DOM. If the known DOM gets
* modified, then the views will get blown away.
*/
// Note: Appending of {@code RemoteVideo} views is handled through
// VideoLayout. The views do not get blown away on render() because
// ReactDOMComponent is only aware of the given JSX and not new appended
// DOM. As such, when updateDOMProperties gets called, only attributes
// will get updated without replacing the DOM. If the known DOM gets
// modified, then the views will get blown away.
const reduceHeight
= _toolboxVisible && interfaceConfig.TOOLBAR_BUTTONS.length;
const filmstripClassNames = `filmstrip ${_remoteVideosVisible
? '' : 'hide-videos'} ${reduceHeight ? 'reduce-height' : ''}`;
const classNames
= `filmstrip ${
_remoteVideosVisible ? '' : 'hide-videos'} ${
reduceHeight ? 'reduce-height' : ''}`;
return (
<div className = { filmstripClassNames }>
{ _filmStripOnly && <Toolbar /> }
<div className = { classNames }>
{ _filmstripOnly && <Toolbar /> }
<div
className = 'filmstrip__videos'
id = 'remoteVideos'>
@ -131,9 +130,9 @@ class Filmstrip extends Component<*> {
<div
className = 'filmstrip__videos'
id = 'filmstripRemoteVideos'>
{/**
* This extra video container is needed for scrolling
* thumbnails in Firefox; otherwise, the flex
{/*
* XXX This extra video container is needed for
* scrolling thumbnails in Firefox; otherwise, the flex
* thumbnails resize instead of causing overflow.
*/}
<div
@ -192,7 +191,7 @@ class Filmstrip extends Component<*> {
* @param {Object} state - The Redux state.
* @private
* @returns {{
* _filmStripOnly: boolean,
* _filmstripOnly: boolean,
* _hovered: boolean,
* _remoteVideosVisible: boolean,
* _toolboxVisible: boolean
@ -202,7 +201,7 @@ function _mapStateToProps(state) {
const { hovered } = state['features/filmstrip'];
return {
_filmStripOnly: Boolean(interfaceConfig.filmStripOnly),
_filmstripOnly: Boolean(interfaceConfig.filmStripOnly),
_hovered: hovered,
_remoteVideosVisible: shouldRemoteVideosBeVisible(state),
_toolboxVisible: state['features/toolbox'].visible

View File

@ -12,16 +12,19 @@ import {
declare var interfaceConfig: Object;
/**
* The type of the React {@code Component} props of {@link Toolbar}.
*/
type Props = {
/**
* Set of buttons which should be visible in this toolbar.
* The set of buttons which should be visible in this {@code Toolbar}.
*/
_visibleButtons: Set<string>
};
/**
* Implements the conference toolbar on React/Web for filmstrip only mode.
* Implements the conference toolbar on React/Web for filmstrip-only mode.
*
* @extends Component
*/

View File

@ -17,7 +17,7 @@ type Props = AbstractButtonProps & {
/**
* Whether we are in filmstrip only mode or not.
*/
_filmStripOnly: boolean,
_filmstripOnly: boolean,
/**
* Array containing the enabled settings sections.
@ -46,10 +46,10 @@ class SettingsButton extends AbstractButton<Props, *> {
* @returns {void}
*/
_handleClick() {
const { _filmStripOnly, _sections, dispatch } = this.props;
const { _filmstripOnly, _sections, dispatch } = this.props;
sendAnalytics(createToolbarEvent('settings'));
if (_filmStripOnly
if (_filmstripOnly
|| (_sections.length === 1 && _sections.includes('devices'))) {
dispatch(openDeviceSelectionDialog());
} else {
@ -76,7 +76,7 @@ class SettingsButton extends AbstractButton<Props, *> {
* @param {Object} state - The Redux state.
* @private
* @returns {{
* _filmStripOnly: boolean
* _filmstripOnly: boolean
* }}
*/
function _mapStateToProps(state): Object { // eslint-disable-line no-unused-vars
@ -84,7 +84,7 @@ function _mapStateToProps(state): Object { // eslint-disable-line no-unused-vars
// interfaceConfig is part of redux we will.
return {
_filmStripOnly: Boolean(interfaceConfig.filmStripOnly),
_filmstripOnly: Boolean(interfaceConfig.filmStripOnly),
_sections: interfaceConfig.SETTINGS_SECTIONS || []
};
}