From 5cf16a20d3f7e1d772f52953cca6b4573bd30bc1 Mon Sep 17 00:00:00 2001 From: Leonard Kim Date: Thu, 12 Apr 2018 14:14:14 -0700 Subject: [PATCH] ref(always-on-top): refactor to stop using old toolbar components --- css/_toolbars.scss | 46 ++++- react/features/always-on-top/AlwaysOnTop.js | 106 +----------- .../always-on-top/ToolboxAlwaysOnTop.js | 159 ++++++++++++++++++ .../toolbox/components/ToolbarButton.web.js | 12 +- 4 files changed, 215 insertions(+), 108 deletions(-) create mode 100644 react/features/always-on-top/ToolboxAlwaysOnTop.js diff --git a/css/_toolbars.scss b/css/_toolbars.scss index a505f568b..29c392a96 100644 --- a/css/_toolbars.scss +++ b/css/_toolbars.scss @@ -440,6 +440,7 @@ } } +.always-on-top-toolbox, .filmstrip-toolbox { background-color: $newToolbarBackgroundColor; box-sizing: border-box; @@ -450,10 +451,6 @@ i { cursor: pointer; display: block; - font-size: 1.9em; - height: 37px; - line-height: 37px; - width: 37px; } i:hover { @@ -464,7 +461,7 @@ background: $newToolbarButtonToggleColor; } - i.toggled:hover { + i.toggled:hover:not(.disabled) { background-color: $newToolbarButtonHoverColor; } @@ -479,6 +476,45 @@ } border-radius: 3px; +} + +.always-on-top-toolbox { + flex-direction: row; + left: 50%; + position: absolute; + top: 10px; + transform: translateX(-50%); + z-index: $toolbarZ; + + i { + font-size: $alwaysOnTopToolbarFontSize; + height: $alwaysOnTopToolbarSize; + line-height: $alwaysOnTopToolbarSize; + width: $alwaysOnTopToolbarSize; + } + + .disabled { + cursor: initial; + } + + .toolbox-button:first-child i { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + } + + .toolbox-button:last-child i { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + } +} + +.filmstrip-toolbox { + i { + font-size: 1.9em; + height: 37px; + line-height: 37px; + width: 37px; + } .toolbox-button:first-child i { border-top-left-radius: 3px; diff --git a/react/features/always-on-top/AlwaysOnTop.js b/react/features/always-on-top/AlwaysOnTop.js index 44645beb9..cd5d93981 100644 --- a/react/features/always-on-top/AlwaysOnTop.js +++ b/react/features/always-on-top/AlwaysOnTop.js @@ -2,54 +2,10 @@ import React, { Component } from 'react'; -import StatelessToolbar from '../toolbox/components/StatelessToolbar'; -import StatelessToolbarButton - from '../toolbox/components/StatelessToolbarButton'; +import ToolboxAlwaysOnTop from './ToolboxAlwaysOnTop'; const { api } = window.alwaysOnTop; -/** - * Map with toolbar button descriptors. - */ -const TOOLBAR_BUTTONS = { - /** - * 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'); - } - } -}; - /** * The timeout in ms for hidding the toolbar. */ @@ -385,62 +341,16 @@ export default class AlwaysOnTop extends Component<*, State> { * @returns {ReactElement} */ render() { - const className - = `toolbar_primary always-on-top ${ - this.state.visible ? 'fadeIn' : 'fadeOut'}`; - return (
- - { - Object.entries(TOOLBAR_BUTTONS).map( - ([ key, button ]) => { - // XXX The following silences a couple of flow - // errors: - if (button === null - || typeof button !== 'object') { - return null; - } - - const { onClick } = button; - let enabled = false; - let 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 ( - - ); - } - ) - } - + onMouseOver = { this._onMouseOver } + videoAvailable = { this.state.videoAvailable } + videoMuted = { this.state.videoMuted } /> { this._renderVideoNotAvailableScreen() } diff --git a/react/features/always-on-top/ToolboxAlwaysOnTop.js b/react/features/always-on-top/ToolboxAlwaysOnTop.js new file mode 100644 index 000000000..e3e5f5727 --- /dev/null +++ b/react/features/always-on-top/ToolboxAlwaysOnTop.js @@ -0,0 +1,159 @@ +// @flow + +import React, { Component } from 'react'; + +// FIXME: 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. +import ToolbarButton from '../toolbox/components/ToolbarButton'; + +const { api } = window.alwaysOnTop; + +/** + * The type of the React {@code Component} props of {@link ToolboxAlwaysOnTop}. + */ +type Props = { + + /** + * Whether or not microphone access is available. + */ + audioAvailable: boolean, + + /** + * Whether or not the user is currently audio muted. + */ + audioMuted: boolean, + + /** + * Additional CSS class names to add to the root of the toolbar. + */ + className: string, + + /** + * Callback invoked when no longer moused over the toolbar. + */ + onMouseOut: Function, + + /** + * Callback invoked when the mouse has moved over the toolbar. + */ + onMouseOver: Function, + + /** + * Whether or not camera access is available. + */ + videoAvailable: boolean, + + /** + * Whether or not the user is currently video muted. + */ + videoMuted: boolean +}; + +/** + * Represents the toolbar in the Always On Top window. + * + * @extends Component + */ +export default class ToolboxAlwaysOnTop extends Component { + /** + * Initializes a new {@code ToolboxAlwaysOnTop} instance. + * + * @param {Props} props - The read-only properties with which the new + * instance is to be initialized. + */ + constructor(props: Props) { + super(props); + + // Bind event handlers so they are only bound once per instance. + this._onToolbarHangup = this._onToolbarHangup.bind(this); + this._onToolbarToggleAudio = this._onToolbarToggleAudio.bind(this); + this._onToolbarToggleVideo = this._onToolbarToggleVideo.bind(this); + } + + /** + * Implements React's {@link Component#render()}. + * + * @inheritdoc + * @returns {ReactElement} + */ + render() { + const { + audioAvailable, + audioMuted, + className = '', + onMouseOut, + onMouseOver, + videoAvailable, + videoMuted + } = this.props; + + const videoMuteIcon = `${videoMuted || !videoAvailable + ? 'icon-camera-disabled toggled' : 'icon-camera'} ${ + videoAvailable ? '' : 'disabled'}`; + const audioMuteIcon = `${audioMuted || !audioAvailable + ? 'icon-mic-disabled toggled' : 'icon-microphone'} ${ + audioAvailable ? '' : 'disabled'}`; + + return ( +
+ + + +
+ ); + } + + _onToolbarHangup: () => void; + + /** + * Ends the conference call and closes the always on top window. + * + * @private + * @returns {void} + */ + _onToolbarHangup() { + api.executeCommand('hangup'); + window.close(); + } + + _onToolbarToggleAudio: () => void; + + /** + * Toggles audio mute if audio is avaiable. + * + * @private + * @returns {void} + */ + _onToolbarToggleAudio() { + if (this.props.audioAvailable) { + api.executeCommand('toggleAudio'); + } + } + + _onToolbarToggleVideo: () => void; + + /** + * Toggles video mute if video is avaiable. + * + * @private + * @returns {void} + */ + _onToolbarToggleVideo() { + if (this.props.videoAvailable) { + api.executeCommand('toggleVideo'); + } + } +} diff --git a/react/features/toolbox/components/ToolbarButton.web.js b/react/features/toolbox/components/ToolbarButton.web.js index 541ea8cad..03bd272c7 100644 --- a/react/features/toolbox/components/ToolbarButton.web.js +++ b/react/features/toolbox/components/ToolbarButton.web.js @@ -53,11 +53,13 @@ class ToolbarButton extends AbstractToolbarButton { aria-label = { this.props.accessibilityLabel } className = 'toolbox-button' onClick = { this.props.onClick }> - - { children } - + { this.props.tooltip + ? + { children } + + : children }
); }