2018-04-17 20:18:02 +00:00
|
|
|
// @flow
|
2022-04-04 10:38:49 +00:00
|
|
|
import React, { Component } from 'react';
|
2018-04-17 20:18:02 +00:00
|
|
|
|
2019-07-19 13:26:32 +00:00
|
|
|
// We need to reference these files directly to avoid loading things that are not available
|
|
|
|
// in this environment (e.g. JitsiMeetJS or interfaceConfig)
|
2022-04-04 10:38:49 +00:00
|
|
|
import { IconCameraEmpty, IconCameraEmptyDisabled } from '../base/icons';
|
2019-07-19 13:26:32 +00:00
|
|
|
import type { Props } from '../base/toolbox/components/AbstractButton';
|
2022-04-04 10:38:49 +00:00
|
|
|
|
|
|
|
import ToolbarButton from './ToolbarButton';
|
2018-04-17 20:18:02 +00:00
|
|
|
|
|
|
|
const { api } = window.alwaysOnTop;
|
|
|
|
|
2018-05-03 17:36:29 +00:00
|
|
|
/**
|
|
|
|
* The type of the React {@code Component} state of {@link VideoMuteButton}.
|
|
|
|
*/
|
2018-04-17 20:18:02 +00:00
|
|
|
type State = {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether video is available is not.
|
|
|
|
*/
|
|
|
|
videoAvailable: boolean,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether video is muted or not.
|
|
|
|
*/
|
|
|
|
videoMuted: boolean
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2018-05-03 17:36:29 +00:00
|
|
|
* Stateless "mute/unmute video" button for the Always-on-Top windows.
|
2018-04-17 20:18:02 +00:00
|
|
|
*/
|
2022-04-04 10:38:49 +00:00
|
|
|
export default class VideoMuteButton extends Component<Props, State> {
|
2018-04-17 20:18:02 +00:00
|
|
|
|
2022-04-04 10:38:49 +00:00
|
|
|
icon = IconCameraEmpty;
|
|
|
|
toggledIcon = IconCameraEmptyDisabled;
|
2018-06-07 20:32:18 +00:00
|
|
|
accessibilityLabel = 'Video mute';
|
|
|
|
|
2018-04-17 20:18:02 +00:00
|
|
|
/**
|
|
|
|
* Initializes a new {@code VideoMuteButton} instance.
|
|
|
|
*
|
|
|
|
* @param {Props} props - The React {@code Component} props to initialize
|
|
|
|
* the new {@code VideoMuteButton} instance with.
|
|
|
|
*/
|
|
|
|
constructor(props: Props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
videoAvailable: false,
|
|
|
|
videoMuted: true
|
|
|
|
};
|
|
|
|
|
|
|
|
// Bind event handlers so they are only bound once per instance.
|
|
|
|
this._videoAvailabilityListener
|
|
|
|
= this._videoAvailabilityListener.bind(this);
|
|
|
|
this._videoMutedListener = this._videoMutedListener.bind(this);
|
2022-04-04 10:38:49 +00:00
|
|
|
this._onClick = this._onClick.bind(this);
|
2018-04-17 20:18:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets mouse move listener and initial toolbar timeout.
|
|
|
|
*
|
|
|
|
* @inheritdoc
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
componentDidMount() {
|
|
|
|
api.on('videoAvailabilityChanged', this._videoAvailabilityListener);
|
|
|
|
api.on('videoMuteStatusChanged', this._videoMutedListener);
|
|
|
|
|
|
|
|
Promise.all([
|
|
|
|
api.isVideoAvailable(),
|
|
|
|
api.isVideoMuted()
|
|
|
|
])
|
2018-05-03 17:36:29 +00:00
|
|
|
.then(([ videoAvailable, videoMuted ]) =>
|
2018-04-17 20:18:02 +00:00
|
|
|
this.setState({
|
|
|
|
videoAvailable,
|
|
|
|
videoMuted
|
2018-05-03 17:36:29 +00:00
|
|
|
}))
|
2019-09-06 11:52:40 +00:00
|
|
|
.catch(console.error);
|
2018-04-17 20:18:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes all listeners.
|
|
|
|
*
|
|
|
|
* @inheritdoc
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
componentWillUnmount() {
|
2018-05-03 17:36:29 +00:00
|
|
|
api.removeListener(
|
|
|
|
'videoAvailabilityChanged',
|
2018-04-17 20:18:02 +00:00
|
|
|
this._videoAvailabilityListener);
|
2018-05-03 17:36:29 +00:00
|
|
|
api.removeListener(
|
|
|
|
'videoMuteStatusChanged',
|
2018-04-17 20:18:02 +00:00
|
|
|
this._videoMutedListener);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Indicates whether this button is disabled or not.
|
|
|
|
*
|
|
|
|
* @override
|
2018-05-11 02:10:26 +00:00
|
|
|
* @protected
|
2018-04-17 20:18:02 +00:00
|
|
|
* @returns {boolean}
|
|
|
|
*/
|
|
|
|
_isDisabled() {
|
|
|
|
return !this.state.videoAvailable;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-03-16 15:59:33 +00:00
|
|
|
* Indicates if video is currently muted or not.
|
2018-04-17 20:18:02 +00:00
|
|
|
*
|
|
|
|
* @override
|
2018-05-11 02:10:26 +00:00
|
|
|
* @protected
|
2018-04-17 20:18:02 +00:00
|
|
|
* @returns {boolean}
|
|
|
|
*/
|
|
|
|
_isVideoMuted() {
|
|
|
|
return this.state.videoMuted;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Changes the muted state.
|
|
|
|
*
|
2018-05-11 02:10:26 +00:00
|
|
|
* @override
|
2018-04-17 20:18:02 +00:00
|
|
|
* @param {boolean} videoMuted - Whether video should be muted or not.
|
2018-05-11 02:10:26 +00:00
|
|
|
* @protected
|
2018-04-17 20:18:02 +00:00
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
_setVideoMuted(videoMuted: boolean) { // eslint-disable-line no-unused-vars
|
|
|
|
this.state.videoAvailable && api.executeCommand('toggleVideo');
|
|
|
|
}
|
|
|
|
|
|
|
|
_videoAvailabilityListener: ({ available: boolean }) => void;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles video available api events.
|
|
|
|
*
|
|
|
|
* @param {{ available: boolean }} status - The new available status.
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
_videoAvailabilityListener({ available }) {
|
|
|
|
this.setState({ videoAvailable: available });
|
|
|
|
}
|
|
|
|
|
|
|
|
_videoMutedListener: ({ muted: boolean }) => void;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles video muted api events.
|
|
|
|
*
|
|
|
|
* @param {{ muted: boolean }} status - The new muted status.
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
_videoMutedListener({ muted }) {
|
|
|
|
this.setState({ videoMuted: muted });
|
|
|
|
}
|
2022-04-04 10:38:49 +00:00
|
|
|
|
|
|
|
_onClick: () => {};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles clicking / pressing the button, and toggles the video mute state
|
|
|
|
* accordingly.
|
|
|
|
*
|
|
|
|
* @protected
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
_onClick() {
|
|
|
|
this._setVideoMuted(!this._isVideoMuted());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements React's {@link Component#render()}.
|
|
|
|
*
|
|
|
|
* @inheritdoc
|
|
|
|
* @returns {ReactElement}
|
|
|
|
*/
|
|
|
|
render() {
|
|
|
|
const toggled = this._isVideoMuted();
|
|
|
|
|
|
|
|
return (<ToolbarButton
|
|
|
|
accessibilityLabel = { this.accessibilityLabel }
|
|
|
|
disabled = { this._isDisabled() }
|
|
|
|
icon = { toggled ? this.toggledIcon : this.icon }
|
|
|
|
onClick = { this._onClick }
|
|
|
|
toggled = { toggled } />);
|
|
|
|
}
|
2018-04-17 20:18:02 +00:00
|
|
|
}
|