123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- import React, { Component } from 'react';
-
- import StatelessToolbar from '../toolbox/components/StatelessToolbar';
- import StatelessToolbarButton
- from '../toolbox/components/StatelessToolbarButton';
-
- const { api } = window.alwaysOnTop;
-
- /**
- * The timeout in ms for hidding the toolbar.
- */
- const TOOLBAR_TIMEOUT = 4000;
-
- /**
- * Map with toolbar button descriptors.
- */
- const toolbarButtons = {
- /**
- * The descriptor of the camera toolbar button.
- */
- camera: {
- classNames: [ 'button', 'icon-camera' ],
- enabled: true,
- id: 'toolbar_button_camera',
- onClick() {
- api.executeCommand('toggleVideo');
- }
- },
-
- /**
- * The descriptor of the toolbar button which hangs up the call/conference.
- */
- hangup: {
- classNames: [ 'button', 'icon-hangup', 'button_hangup' ],
- enabled: true,
- id: 'toolbar_button_hangup',
- onClick() {
- api.executeCommand('hangup');
- window.close();
- }
- },
-
- /**
- * The descriptor of the microphone toolbar button.
- */
- microphone: {
- classNames: [ 'button', 'icon-microphone' ],
- enabled: true,
- id: 'toolbar_button_mute',
- onClick() {
- api.executeCommand('toggleAudio');
- }
- }
- };
-
- /**
- * Represents the always on top page.
- *
- * @class AlwaysOnTop
- * @extends Component
- */
- export default class AlwaysOnTop extends Component<*> {
- /**
- * Initializes new AlwaysOnTop instance.
- *
- * @param {Object} props - The read-only properties with which the new
- * instance is to be initialized.
- */
- constructor(props) {
- super(props);
-
- this.state = {
- visible: true,
- audioMuted: false,
- videoMuted: false,
- audioAvailable: false,
- videoAvailable: false
- };
-
- this._hovered = false;
-
- this._audioAvailabilityListener
- = this._audioAvailabilityListener.bind(this);
- this._audioMutedListener = this._audioMutedListener.bind(this);
- this._mouseMove = this._mouseMove.bind(this);
- this._onMouseOver = this._onMouseOver.bind(this);
- this._onMouseOut = this._onMouseOut.bind(this);
- this._videoAvailabilityListener
- = this._videoAvailabilityListener.bind(this);
- this._videoMutedListener = this._videoMutedListener.bind(this);
- }
-
- /**
- * Handles audio available api events.
- *
- * @param {{ available: boolean }} status - The new available status.
- * @returns {void}
- */
- _audioAvailabilityListener({ available }) {
- this.setState({ audioAvailable: available });
- }
-
- /**
- * Handles audio muted api events.
- *
- * @param {{ muted: boolean }} status - The new muted status.
- * @returns {void}
- */
- _audioMutedListener({ muted }) {
- this.setState({ audioMuted: muted });
- }
-
- /**
- * Hides the toolbar after a timeout.
- *
- * @returns {void}
- */
- _hideToolbarAfterTimeout() {
- setTimeout(() => {
- if (this._hovered) {
- this._hideToolbarAfterTimeout();
-
- return;
- }
- this.setState({ visible: false });
- }, TOOLBAR_TIMEOUT);
- }
-
- /**
- * Handles mouse move events.
- *
- * @returns {void}
- */
- _mouseMove() {
- if (!this.state.visible) {
- this.setState({ visible: true });
- }
- }
-
- /**
- * Toolbar mouse over handler.
- *
- * @returns {void}
- */
- _onMouseOver() {
- this._hovered = true;
- }
-
- /**
- * Toolbar mouse out handler.
- *
- * @returns {void}
- */
- _onMouseOut() {
- this._hovered = false;
- }
-
- /**
- * Handles audio available api events.
- *
- * @param {{ available: boolean }} status - The new available status.
- * @returns {void}
- */
- _videoAvailabilityListener({ available }) {
- this.setState({ videoAvailable: available });
- }
-
- /**
- * Handles video muted api events.
- *
- * @param {{ muted: boolean }} status - The new muted status.
- * @returns {void}
- */
- _videoMutedListener({ muted }) {
- this.setState({ videoMuted: muted });
- }
-
- /**
- * Sets mouse move listener and initial toolbar timeout.
- *
- * @inheritdoc
- * @returns {void}
- */
- componentDidMount() {
- api.on('audioMuteStatusChanged', this._audioMutedListener);
- api.on('videoMuteStatusChanged', this._videoMutedListener);
- api.on('audioAvailabilityChanged', this._audioAvailabilityListener);
- api.on('videoAvailabilityChanged', this._videoAvailabilityListener);
-
- Promise.all([
- api.isAudioMuted(),
- api.isVideoMuted(),
- api.isAudioAvailable(),
- api.isVideoAvailable()
- ])
- .then(([
- audioMuted = false,
- videoMuted = false,
- audioAvailable = false,
- videoAvailable = false
- ]) =>
- this.setState({
- audioMuted,
- videoMuted,
- audioAvailable,
- videoAvailable
- })
- )
- .catch(console.error);
-
- window.addEventListener('mousemove', this._mouseMove);
-
- this._hideToolbarAfterTimeout();
- }
-
- /**
- * Removes all listeners.
- *
- * @inheritdoc
- * @returns {void}
- */
- componentWillUnmount() {
- api.removeListener('audioMuteStatusChanged',
- this._audioMutedListener);
- api.removeListener('videoMuteStatusChanged',
- this._videoMutedListener);
- api.removeListener('audioAvailabilityChanged',
- this._audioAvailabilityListener);
- api.removeListener('videoAvailabilityChanged',
- this._videoAvailabilityListener);
- window.removeEventListener('mousemove', this._mouseMove);
- }
-
- /**
- * Sets a timeout to hide the toolbar when the toolbar is shown.
- *
- * @inheritdoc
- * @returns {void}
- */
- componentWillUpdate(nextProps, nextState) {
- if (!this.state.visible && nextState.visible) {
- this._hideToolbarAfterTimeout();
- }
- }
-
- /**
- * Implements React's {@link Component#render()}.
- *
- * @inheritdoc
- * @returns {ReactElement}
- */
- render() {
- const className
- = `toolbar_primary always-on-top ${
- this.state.visible ? 'fadeIn' : 'fadeOut'}`;
-
- return (
- <StatelessToolbar
- className = { className }
- onMouseOut = { this._onMouseOut }
- onMouseOver = { this._onMouseOver }>
- {
- Object.entries(toolbarButtons).map(([ key, button ]) => {
- const { onClick } = button;
- let enabled = false, toggled = false;
-
- switch (key) {
- case 'microphone':
- enabled = this.state.audioAvailable;
- toggled = enabled ? this.state.audioMuted : true;
- break;
- case 'camera':
- enabled = this.state.videoAvailable;
- toggled = enabled ? this.state.videoMuted : true;
- break;
- default: // hangup button
- toggled = false;
- enabled = true;
- }
-
- const updatedButton = {
- ...button,
- enabled,
- toggled
- };
-
- return (
- <StatelessToolbarButton
- button = { updatedButton }
- key = { key }
- onClick = { onClick } />
- );
- })
- }
- </StatelessToolbar>
- );
- }
- }
|