| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 | 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 ${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>
        );
    }
}
 |