From e7297714c6bb58f10262e6527139f2142105eccb Mon Sep 17 00:00:00 2001 From: Vlad Piersec Date: Mon, 22 Mar 2021 11:02:57 +0200 Subject: [PATCH] feat(toolbox): Adaptive toolbar on mobile --- .../styles/components/styles/ColorPalette.js | 1 + .../toolbox/components/native/OverflowMenu.js | 20 ++- .../toolbox/components/native/Toolbox.js | 138 +++++++++--------- .../toolbox/components/native/styles.js | 19 +-- react/features/toolbox/functions.native.js | 45 ++++++ 5 files changed, 132 insertions(+), 91 deletions(-) diff --git a/react/features/base/styles/components/styles/ColorPalette.js b/react/features/base/styles/components/styles/ColorPalette.js index dd54c3e149..a60aff4729 100644 --- a/react/features/base/styles/components/styles/ColorPalette.js +++ b/react/features/base/styles/components/styles/ColorPalette.js @@ -29,6 +29,7 @@ export const ColorPalette = { overflowMenuItemUnderlay: '#EEEEEE', red: '#D00000', transparent: 'rgba(0, 0, 0, 0)', + toggled: 'rgba(255,255,255,.15)', warning: 'rgb(215, 121, 118)', white: '#FFFFFF', diff --git a/react/features/toolbox/components/native/OverflowMenu.js b/react/features/toolbox/components/native/OverflowMenu.js index a07b3952bb..35ca303428 100644 --- a/react/features/toolbox/components/native/OverflowMenu.js +++ b/react/features/toolbox/components/native/OverflowMenu.js @@ -18,6 +18,7 @@ import { RoomLockButton } from '../../../room-lock'; import { SharedVideoButton } from '../../../shared-video/components'; import { ClosedCaptionButton } from '../../../subtitles'; import { TileViewButton } from '../../../video-layout'; +import { getMovableButtons } from '../../functions.native'; import HelpButton from '../HelpButton'; import MuteEveryoneButton from '../MuteEveryoneButton'; @@ -48,6 +49,11 @@ type Props = { */ _recordingEnabled: boolean, + /** + * The width of the screen. + */ + _width: number, + /** * Used for hiding the dialog when the selection was completed. */ @@ -108,8 +114,9 @@ class OverflowMenu extends PureComponent { * @returns {ReactElement} */ render() { - const { _bottomSheetStyles } = this.props; + const { _bottomSheetStyles, _width } = this.props; const { showMore } = this.state; + const toolbarButtons = getMovableButtons(_width); const buttonProps = { afterClick: this._onCancel, @@ -129,15 +136,15 @@ class OverflowMenu extends PureComponent { onSwipe = { this._onSwipe } renderHeader = { this._renderMenuExpandToggle }> - + {!toolbarButtons.has('invite') && } - + {!toolbarButtons.has('raisehand') && } - - + {!toolbarButtons.has('togglecamera') && } + {!toolbarButtons.has('tileview') && } @@ -244,7 +251,8 @@ class OverflowMenu extends PureComponent { function _mapStateToProps(state) { return { _bottomSheetStyles: ColorSchemeRegistry.get(state, 'BottomSheet'), - _isOpen: isDialogOpen(state, OverflowMenu_) + _isOpen: isDialogOpen(state, OverflowMenu_), + _width: state['features/base/responsive-ui'].clientWidth }; } diff --git a/react/features/toolbox/components/native/Toolbox.js b/react/features/toolbox/components/native/Toolbox.js index b2634823ea..01fa8fe549 100644 --- a/react/features/toolbox/components/native/Toolbox.js +++ b/react/features/toolbox/components/native/Toolbox.js @@ -1,18 +1,22 @@ // @flow -import React, { PureComponent } from 'react'; +import React from 'react'; import { SafeAreaView, View } from 'react-native'; import { ColorSchemeRegistry } from '../../../base/color-scheme'; import { connect } from '../../../base/redux'; import { StyleType } from '../../../base/styles'; import { ChatButton } from '../../../chat'; -import { isToolboxVisible } from '../../functions'; +import { InviteButton } from '../../../invite'; +import { TileViewButton } from '../../../video-layout'; +import { isToolboxVisible, getMovableButtons } from '../../functions.native'; import AudioMuteButton from '../AudioMuteButton'; import HangupButton from '../HangupButton'; import VideoMuteButton from '../VideoMuteButton'; import OverflowMenuButton from './OverflowMenuButton'; +import RaiseHandButton from './RaiseHandButton'; +import ToggleCameraButton from './ToggleCameraButton'; import styles from './styles'; /** @@ -30,6 +34,11 @@ type Props = { */ _visible: boolean, + /** + * The width of the screen. + */ + _width: number, + /** * The redux {@code dispatch} function. */ @@ -37,80 +46,64 @@ type Props = { }; /** - * Implements the conference toolbox on React Native. + * Implements the conference Toolbox on React Native. + * + * @param {Object} props - The props of the component. + * @returns {React$Element}. */ -class Toolbox extends PureComponent { - /** - * Implements React's {@link Component#render()}. - * - * @inheritdoc - * @returns {ReactElement} - */ - render() { - if (!this.props._visible) { - return null; - } - - const { _styles } = this.props; - const { buttonStylesBorderless, hangupButtonStyles, toggledButtonStyles } = _styles; - - return ( - - - - - - - - - - ); +function Toolbox(props: Props) { + if (!props._visible) { + return null; } - /** - * Constructs the toggled style of the chat button. This cannot be done by - * simple style inheritance due to the size calculation done in this - * component. - * - * @param {Object} baseStyle - The base style that was originally - * calculated. - * @returns {Object | Array} - */ - _getChatButtonToggledStyle(baseStyle) { - const { _styles } = this.props; + const { _styles, _width } = props; + const { buttonStylesBorderless, hangupButtonStyles, toggledButtonStyles } = _styles; + const additionalButtons = getMovableButtons(_width); + const backgroundToggledStyle = { + ...toggledButtonStyles, + style: [ + toggledButtonStyles.style, + _styles.backgroundToggle + ] + }; - if (Array.isArray(baseStyle.style)) { - return { - ...baseStyle, - style: [ - ...baseStyle.style, - _styles.chatButtonOverride.toggled - ] - }; - } + return ( + + + + + { additionalButtons.has('chat') + && } - return { - ...baseStyle, - style: [ - baseStyle.style, - _styles.chatButtonOverride.toggled - ] - }; - } + { additionalButtons.has('raisehand') + && } + {additionalButtons.has('tileview') && } + {additionalButtons.has('invite') && } + {additionalButtons.has('togglecamera') + && } + + + + + ); } /** @@ -125,7 +118,8 @@ class Toolbox extends PureComponent { function _mapStateToProps(state: Object): Object { return { _styles: ColorSchemeRegistry.get(state, 'Toolbox'), - _visible: isToolboxVisible(state) + _visible: isToolboxVisible(state), + _width: state['features/base/responsive-ui'].clientWidth }; } diff --git a/react/features/toolbox/components/native/styles.js b/react/features/toolbox/components/native/styles.js index adee0a735b..52cc3bf390 100644 --- a/react/features/toolbox/components/native/styles.js +++ b/react/features/toolbox/components/native/styles.js @@ -17,10 +17,8 @@ const toolbarButton = { flexDirection: 'row', height: BUTTON_SIZE, justifyContent: 'center', - - // XXX We probably tested BoxModel.margin and discovered it to be too small - // for our taste. - marginHorizontal: 7, + marginHorizontal: 6, + marginTop: 6, width: BUTTON_SIZE }; @@ -65,7 +63,8 @@ const styles = { toolbox: { alignItems: 'center', backgroundColor: ColorPalette.darkBackground, - borderRadius: 3, + borderTopLeftRadius: 3, + borderTopRightRadius: 3, flexDirection: 'row', flexGrow: 0, justifyContent: 'space-between', @@ -108,14 +107,8 @@ ColorSchemeRegistry.register('Toolbox', { } }, - /** - * Overrides to the standard styles that we apply to the chat button, as - * that behaves slightly differently to other buttons. - */ - chatButtonOverride: { - toggled: { - backgroundColor: ColorPalette.blue - } + backgroundToggle: { + backgroundColor: ColorPalette.toggled }, hangupButtonStyles: { diff --git a/react/features/toolbox/functions.native.js b/react/features/toolbox/functions.native.js index 961cc12e44..e12b86745b 100644 --- a/react/features/toolbox/functions.native.js +++ b/react/features/toolbox/functions.native.js @@ -5,6 +5,51 @@ import { TOOLBOX_ALWAYS_VISIBLE, getFeatureFlag, TOOLBOX_ENABLED } from '../base import { toState } from '../base/redux'; import { isLocalVideoTrackDesktop } from '../base/tracks'; +const WIDTH = { + FIT_9_ICONS: 560, + FIT_8_ICONS: 500, + FIT_7_ICONS: 440, + FIT_6_ICONS: 380 +}; + +/** + * Returns a set of the buttons that are shown in the toolbar + * but removed from the overflow menu, based on the width of the screen. + * + * @param {number} width - The width of the screen. + * @returns {Set} + */ +export function getMovableButtons(width: number): Set { + let buttons = []; + + switch (true) { + case width >= WIDTH.FIT_9_ICONS: { + buttons = [ 'togglecamera', 'chat', 'invite', 'raisehand', 'tileview' ]; + break; + } + case width >= WIDTH.FIT_8_ICONS: { + buttons = [ 'chat', 'invite', 'raisehand', 'tileview' ]; + break; + } + + case width >= WIDTH.FIT_7_ICONS: { + buttons = [ 'chat', 'raisehand', 'invite' ]; + break; + } + + case width >= WIDTH.FIT_6_ICONS: { + buttons = [ 'chat', 'raisehand' ]; + break; + } + + default: { + buttons = [ 'chat' ]; + } + } + + return new Set(buttons); +} + /** * Returns true if the toolbox is visible. *