feat(narrow-layout) Use drawer menus on desktop narrow mode (#12799)

This commit is contained in:
Horatiu Muresan 2023-01-25 17:02:26 +02:00 committed by GitHub
parent cf7e692186
commit 3e58cd8af3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 90 additions and 25 deletions

View File

@ -52,3 +52,15 @@ export const SET_REDUCED_UI = 'SET_REDUCED_UI';
*/ */
export const SET_CONTEXT_MENU_OPEN = 'SET_CONTEXT_MENU_OPEN'; export const SET_CONTEXT_MENU_OPEN = 'SET_CONTEXT_MENU_OPEN';
/**
* The type of redux action which signals whether we are in narrow layout.
*
* {
* type: SET_NARROW_LAYOUT,
* isNarrow: boolean
* }
*
* @public
*/
export const SET_NARROW_LAYOUT = 'SET_NARROW_LAYOUT';

View File

@ -10,6 +10,7 @@ import {
SAFE_AREA_INSETS_CHANGED, SAFE_AREA_INSETS_CHANGED,
SET_ASPECT_RATIO, SET_ASPECT_RATIO,
SET_CONTEXT_MENU_OPEN, SET_CONTEXT_MENU_OPEN,
SET_NARROW_LAYOUT,
SET_REDUCED_UI SET_REDUCED_UI
} from './actionTypes'; } from './actionTypes';
import { ASPECT_RATIO_NARROW, ASPECT_RATIO_WIDE } from './constants'; import { ASPECT_RATIO_NARROW, ASPECT_RATIO_WIDE } from './constants';
@ -143,3 +144,19 @@ export function setSafeAreaInsets(insets: Object) {
insets insets
}; };
} }
/**
* Sets narrow layout.
*
* @param {boolean} isNarrow - Whether is narrow layout.
* @returns {{
* type: SET_NARROW_LAYOUT,
* isNarrow: boolean
* }}
*/
export function setNarrowLayout(isNarrow: boolean) {
return {
type: SET_NARROW_LAYOUT,
isNarrow
};
}

View File

@ -6,6 +6,7 @@ import {
SAFE_AREA_INSETS_CHANGED, SAFE_AREA_INSETS_CHANGED,
SET_ASPECT_RATIO, SET_ASPECT_RATIO,
SET_CONTEXT_MENU_OPEN, SET_CONTEXT_MENU_OPEN,
SET_NARROW_LAYOUT,
SET_REDUCED_UI SET_REDUCED_UI
} from './actionTypes'; } from './actionTypes';
import { ASPECT_RATIO_NARROW } from './constants'; import { ASPECT_RATIO_NARROW } from './constants';
@ -22,6 +23,7 @@ const DEFAULT_STATE = {
aspectRatio: ASPECT_RATIO_NARROW, aspectRatio: ASPECT_RATIO_NARROW,
clientHeight: innerHeight, clientHeight: innerHeight,
clientWidth: innerWidth, clientWidth: innerWidth,
isNarrowLayout: false,
reducedUI: false, reducedUI: false,
contextMenuOpened: false contextMenuOpened: false
}; };
@ -31,6 +33,7 @@ export interface IResponsiveUIState {
clientHeight: number; clientHeight: number;
clientWidth: number; clientWidth: number;
contextMenuOpened: boolean; contextMenuOpened: boolean;
isNarrowLayout: boolean;
reducedUI: boolean; reducedUI: boolean;
safeAreaInsets?: { safeAreaInsets?: {
bottom: number; bottom: number;
@ -65,6 +68,9 @@ ReducerRegistry.register<IResponsiveUIState>('features/base/responsive-ui',
case SET_CONTEXT_MENU_OPEN: case SET_CONTEXT_MENU_OPEN:
return set(state, 'contextMenuOpened', action.isOpen); return set(state, 'contextMenuOpened', action.isOpen);
case SET_NARROW_LAYOUT:
return set(state, 'isNarrowLayout', action.isNarrow);
} }
return state; return state;

View File

@ -81,6 +81,11 @@ type Props = AbstractProps & {
*/ */
_enableSaveLogs: boolean, _enableSaveLogs: boolean,
/**
* Whether is narrow layout or not.
*/
_isNarrowLayout: boolean,
/** /**
* Whether or not the displays stats are for local video. * Whether or not the displays stats are for local video.
*/ */
@ -193,6 +198,7 @@ class ConnectionIndicatorContent extends AbstractConnectionIndicator<Props, Stat
enableSaveLogs = { this.props._enableSaveLogs } enableSaveLogs = { this.props._enableSaveLogs }
framerate = { framerate } framerate = { framerate }
isLocalVideo = { this.props._isLocalVideo } isLocalVideo = { this.props._isLocalVideo }
isNarrowLayout = { this.props._isNarrowLayout }
isVirtualScreenshareParticipant = { this.props._isVirtualScreenshareParticipant } isVirtualScreenshareParticipant = { this.props._isVirtualScreenshareParticipant }
maxEnabledResolution = { maxEnabledResolution } maxEnabledResolution = { maxEnabledResolution }
onSaveLogs = { this.props._onSaveLogs } onSaveLogs = { this.props._onSaveLogs }
@ -312,6 +318,7 @@ export function _mapStateToProps(state: Object, ownProps: Props) {
const conference = state['features/base/conference'].conference; const conference = state['features/base/conference'].conference;
const participant const participant
= participantId ? getParticipantById(state, participantId) : getLocalParticipant(state); = participantId ? getParticipantById(state, participantId) : getLocalParticipant(state);
const { isNarrowLayout } = state['features/base/responsive-ui'];
const tracks = state['features/base/tracks']; const tracks = state['features/base/tracks'];
const audioTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.AUDIO, participantId); const audioTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.AUDIO, participantId);
let videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, participantId); let videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, participantId);
@ -330,6 +337,7 @@ export function _mapStateToProps(state: Object, ownProps: Props) {
_isConnectionStatusInactive, _isConnectionStatusInactive,
_isConnectionStatusInterrupted, _isConnectionStatusInterrupted,
_isE2EEVerified: participant?.e2eeVerified, _isE2EEVerified: participant?.e2eeVerified,
_isNarrowLayout: isNarrowLayout,
_isVirtualScreenshareParticipant: isScreenShareParticipant(participant), _isVirtualScreenshareParticipant: isScreenShareParticipant(participant),
_isLocalVideo: participant?.local, _isLocalVideo: participant?.local,
_region: participant?.region, _region: participant?.region,

View File

@ -98,6 +98,11 @@ interface IProps extends WithTranslation {
*/ */
isLocalVideo: boolean; isLocalVideo: boolean;
/**
* Whether we are in narrow layout mode or not.
*/
isNarrowLayout: boolean;
/** /**
* Whether or not the statistics are for screen share. * Whether or not the statistics are for screen share.
*/ */
@ -261,9 +266,10 @@ class ConnectionStatsTable extends Component<IProps> {
disableShowMoreStats, disableShowMoreStats,
enableSaveLogs, enableSaveLogs,
isVirtualScreenshareParticipant, isVirtualScreenshareParticipant,
isLocalVideo isLocalVideo,
isNarrowLayout
} = this.props; } = this.props;
const className = clsx(classes.connectionStatsTable, { [classes.mobile]: isMobileBrowser() }); const className = clsx(classes.connectionStatsTable, { [classes.mobile]: isMobileBrowser() || isNarrowLayout });
if (isVirtualScreenshareParticipant) { if (isVirtualScreenshareParticipant) {
return this._renderScreenShareStatus(); return this._renderScreenShareStatus();

View File

@ -1,8 +1,7 @@
import { isMobileBrowser } from '../base/environment/utils';
import { pinParticipant } from '../base/participants/actions'; import { pinParticipant } from '../base/participants/actions';
import { getParticipantCountWithFake } from '../base/participants/functions'; import { getParticipantCountWithFake } from '../base/participants/functions';
import StateListenerRegistry from '../base/redux/StateListenerRegistry'; import StateListenerRegistry from '../base/redux/StateListenerRegistry';
import { clientResized } from '../base/responsive-ui/actions'; import { clientResized, setNarrowLayout } from '../base/responsive-ui/actions';
import { shouldHideSelfView } from '../base/settings/functions.web'; import { shouldHideSelfView } from '../base/settings/functions.web';
import { selectParticipantInLargeVideo } from '../large-video/actions.any'; import { selectParticipantInLargeVideo } from '../large-video/actions.any';
import { getParticipantsPaneOpen } from '../participants-pane/functions'; import { getParticipantsPaneOpen } from '../participants-pane/functions';
@ -136,9 +135,8 @@ StateListenerRegistry.register(
StateListenerRegistry.register( StateListenerRegistry.register(
/* selector */ state => state['features/base/responsive-ui'].clientWidth < DISPLAY_DRAWER_THRESHOLD, /* selector */ state => state['features/base/responsive-ui'].clientWidth < DISPLAY_DRAWER_THRESHOLD,
/* listener */ (widthBelowThreshold, store) => { /* listener */ (widthBelowThreshold, store) => {
if (isMobileBrowser()) { store.dispatch(setOverflowDrawer(widthBelowThreshold));
store.dispatch(setOverflowDrawer(widthBelowThreshold)); store.dispatch(setNarrowLayout(widthBelowThreshold));
}
}); });
/** /**

View File

@ -3,6 +3,7 @@
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { isMobileBrowser } from '../../../../../base/environment/utils';
import { isLocalParticipantModerator } from '../../../../../base/participants'; import { isLocalParticipantModerator } from '../../../../../base/participants';
import { equals } from '../../../../../base/redux'; import { equals } from '../../../../../base/redux';
import useContextMenu from '../../../../../base/ui/hooks/useContextMenu.web'; import useContextMenu from '../../../../../base/ui/hooks/useContextMenu.web';
@ -40,10 +41,11 @@ export const RoomList = ({ searchString }: Props) => {
const isLocalModerator = useSelector(isLocalParticipantModerator); const isLocalModerator = useSelector(isLocalParticipantModerator);
const showAutoAssign = useSelector(isAutoAssignParticipantsVisible); const showAutoAssign = useSelector(isAutoAssignParticipantsVisible);
const { hideJoinRoomButton } = useSelector(getBreakoutRoomsConfig); const { hideJoinRoomButton } = useSelector(getBreakoutRoomsConfig);
const _overflowDrawer = useSelector(showOverflowDrawer); const overflowDrawer = useSelector(showOverflowDrawer);
const [ lowerMenu, raiseMenu, toggleMenu, menuEnter, menuLeave, raiseContext ] = useContextMenu(); const [ lowerMenu, raiseMenu, toggleMenu, menuEnter, menuLeave, raiseContext ] = useContextMenu();
const [ lowerParticipantMenu, raiseParticipantMenu, toggleParticipantMenu, const [ lowerParticipantMenu, raiseParticipantMenu, toggleParticipantMenu,
participantMenuEnter, participantMenuLeave, raiseParticipantContext ] = useContextMenu(); participantMenuEnter, participantMenuLeave, raiseParticipantContext ] = useContextMenu();
const hideMenu = useCallback(() => !overflowDrawer && lowerMenu(), [ overflowDrawer, lowerMenu ]);
const onRaiseMenu = useCallback(room => target => raiseMenu(room, target), [ raiseMenu ]); const onRaiseMenu = useCallback(room => target => raiseMenu(room, target), [ raiseMenu ]);
return ( return (
@ -55,14 +57,14 @@ export const RoomList = ({ searchString }: Props) => {
<React.Fragment key = { room.id }> <React.Fragment key = { room.id }>
<CollapsibleRoom <CollapsibleRoom
isHighlighted = { raiseContext.entity === room } isHighlighted = { raiseContext.entity === room }
onLeave = { lowerMenu } onLeave = { hideMenu }
onRaiseMenu = { onRaiseMenu(room) } onRaiseMenu = { onRaiseMenu(room) }
participantContextEntity = { raiseParticipantContext.entity } participantContextEntity = { raiseParticipantContext.entity }
raiseParticipantContextMenu = { raiseParticipantMenu } raiseParticipantContextMenu = { raiseParticipantMenu }
room = { room } room = { room }
searchString = { searchString } searchString = { searchString }
toggleParticipantMenu = { toggleParticipantMenu }> toggleParticipantMenu = { toggleParticipantMenu }>
{!_overflowDrawer && <> {!isMobileBrowser() && <>
{!hideJoinRoomButton && <JoinActionButton room = { room } />} {!hideJoinRoomButton && <JoinActionButton room = { room } />}
{isLocalModerator && !room.isMainRoom {isLocalModerator && !room.isMainRoom
&& <RoomActionEllipsis onClick = { toggleMenu(room) } />} && <RoomActionEllipsis onClick = { toggleMenu(room) } />}

View File

@ -236,10 +236,11 @@ class ReactionsMenu extends Component<IProps> {
*/ */
function mapStateToProps(state: IReduxState) { function mapStateToProps(state: IReduxState) {
const localParticipant = getLocalParticipant(state); const localParticipant = getLocalParticipant(state);
const { isNarrowLayout } = state['features/base/responsive-ui'];
return { return {
_localParticipantID: localParticipant?.id, _localParticipantID: localParticipant?.id,
_isMobile: isMobileBrowser(), _isMobile: isMobileBrowser() || isNarrowLayout,
_isGifEnabled: isGifEnabled(state), _isGifEnabled: isGifEnabled(state),
_isGifMenuVisible: isGifsMenuOpen(state), _isGifMenuVisible: isGifsMenuOpen(state),
_raisedHand: hasRaisedHand(localParticipant) _raisedHand: hasRaisedHand(localParticipant)

View File

@ -43,9 +43,9 @@ interface IProps extends WithTranslation {
handleClick: Function; handleClick: Function;
/** /**
* Whether or not it's a mobile browser. * Whether or not it's narrow mode or mobile browser.
*/ */
isMobile: boolean; isNarrow: boolean;
/** /**
* Whether or not the reactions menu is open. * Whether or not the reactions menu is open.
@ -75,7 +75,7 @@ function ReactionsMenuButton({
dispatch, dispatch,
handleClick, handleClick,
isOpen, isOpen,
isMobile, isNarrow,
notifyMode, notifyMode,
reactionsQueue, reactionsQueue,
t t
@ -95,7 +95,7 @@ function ReactionsMenuButton({
return ( return (
<div className = 'reactions-menu-popup-container'> <div className = 'reactions-menu-popup-container'>
{!_reactionsEnabled || isMobile ? ( {!_reactionsEnabled || isNarrow ? (
<RaiseHandButton <RaiseHandButton
buttonKey = { buttonKey } buttonKey = { buttonKey }
handleClick = { handleClick } handleClick = { handleClick }
@ -135,10 +135,12 @@ function ReactionsMenuButton({
* @returns {Object} * @returns {Object}
*/ */
function mapStateToProps(state: IReduxState) { function mapStateToProps(state: IReduxState) {
const { isNarrowLayout } = state['features/base/responsive-ui'];
return { return {
_reactionsEnabled: isReactionsEnabled(state), _reactionsEnabled: isReactionsEnabled(state),
isOpen: getReactionsMenuVisibility(state), isOpen: getReactionsMenuVisibility(state),
isMobile: isMobileBrowser(), isNarrow: isMobileBrowser() || isNarrowLayout,
reactionsQueue: getReactionsQueue(state) reactionsQueue: getReactionsQueue(state)
}; };
} }

View File

@ -155,12 +155,13 @@ class AudioSettingsButton extends Component<Props> {
*/ */
function mapStateToProps(state) { function mapStateToProps(state) {
const { permissions = {} } = state['features/base/devices']; const { permissions = {} } = state['features/base/devices'];
const { isNarrowLayout } = state['features/base/responsive-ui'];
return { return {
hasPermissions: permissions.audio, hasPermissions: permissions.audio,
isDisabled: isAudioSettingsButtonDisabled(state), isDisabled: isAudioSettingsButtonDisabled(state),
isOpen: getAudioSettingsVisibility(state), isOpen: getAudioSettingsVisibility(state),
visible: !isMobileBrowser() visible: !isMobileBrowser() && !isNarrowLayout
}; };
} }

View File

@ -5,13 +5,13 @@ import { makeStyles } from 'tss-react/mui';
import { createToolbarEvent } from '../../../analytics/AnalyticsEvents'; import { createToolbarEvent } from '../../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../../analytics/functions'; import { sendAnalytics } from '../../../analytics/functions';
import { IReduxState } from '../../../app/types';
import Popover from '../../../base/popover/components/Popover.web'; import Popover from '../../../base/popover/components/Popover.web';
// @ts-ignore // @ts-ignore
import { ReactionEmoji, ReactionsMenu } from '../../../reactions/components'; import { ReactionEmoji, ReactionsMenu } from '../../../reactions/components';
import { REACTIONS_MENU_HEIGHT } from '../../../reactions/constants'; import { REACTIONS_MENU_HEIGHT } from '../../../reactions/constants';
import { getReactionsQueue } from '../../../reactions/functions.any'; import { getReactionsQueue } from '../../../reactions/functions.any';
import { DRAWER_MAX_HEIGHT } from '../../constants'; import { DRAWER_MAX_HEIGHT } from '../../constants';
import { showOverflowDrawer } from '../../functions.web';
// @ts-ignore // @ts-ignore
import Drawer from './Drawer'; import Drawer from './Drawer';
@ -67,7 +67,7 @@ const OverflowMenuButton = ({
showMobileReactions showMobileReactions
}: IProps) => { }: IProps) => {
const { classes } = useStyles(); const { classes } = useStyles();
const overflowDrawer = useSelector((state: IReduxState) => state['features/toolbox'].overflowDrawer); const overflowDrawer = useSelector(showOverflowDrawer);
const reactionsQueue = useSelector(getReactionsQueue); const reactionsQueue = useSelector(getReactionsQueue);
const onCloseDialog = useCallback(() => { const onCloseDialog = useCallback(() => {

View File

@ -231,6 +231,11 @@ interface IProps extends WithTranslation {
*/ */
_isMobile: boolean; _isMobile: boolean;
/**
* Whether we are in narrow layout mode.
*/
_isNarrowLayout: boolean;
/** /**
* Whether or not the profile is disabled. * Whether or not the profile is disabled.
*/ */
@ -710,8 +715,10 @@ class Toolbox extends Component<IProps> {
_hasSalesforce, _hasSalesforce,
_isIosMobile, _isIosMobile,
_isMobile, _isMobile,
_isNarrowLayout,
_isSpeakerStatsDisabled, _isSpeakerStatsDisabled,
_multiStreamModeEnabled, _multiStreamModeEnabled,
_reactionsEnabled,
_screenSharing, _screenSharing,
_whiteboardEnabled _whiteboardEnabled
} = this.props; } = this.props;
@ -748,7 +755,7 @@ class Toolbox extends Component<IProps> {
group: 2 group: 2
}; };
const raisehand = { const raisehand = (!_reactionsEnabled || (!_isNarrowLayout && !_isMobile)) && {
key: 'raisehand', key: 'raisehand',
Content: ReactionsMenuButton, Content: ReactionsMenuButton,
handleClick: this._onToolbarToggleRaiseHand, handleClick: this._onToolbarToggleRaiseHand,
@ -1387,6 +1394,7 @@ class Toolbox extends Component<IProps> {
_endConferenceSupported, _endConferenceSupported,
_hangupMenuVisible, _hangupMenuVisible,
_isMobile, _isMobile,
_isNarrowLayout,
_overflowDrawer, _overflowDrawer,
_overflowMenuVisible, _overflowMenuVisible,
_reactionsEnabled, _reactionsEnabled,
@ -1396,7 +1404,7 @@ class Toolbox extends Component<IProps> {
} = this.props; } = this.props;
const toolbarAccLabel = 'toolbar.accessibilityLabel.moreActionsMenu'; const toolbarAccLabel = 'toolbar.accessibilityLabel.moreActionsMenu';
const containerClassName = `toolbox-content${_isMobile ? ' toolbox-content-mobile' : ''}`; const containerClassName = `toolbox-content${_isMobile || _isNarrowLayout ? ' toolbox-content-mobile' : ''}`;
const { mainMenuButtons, overflowMenuButtons } = this._getVisibleButtons(); const { mainMenuButtons, overflowMenuButtons } = this._getVisibleButtons();
@ -1424,7 +1432,7 @@ class Toolbox extends Component<IProps> {
key = 'overflow-menu' key = 'overflow-menu'
onVisibilityChange = { this._onSetOverflowVisible } onVisibilityChange = { this._onSetOverflowVisible }
showMobileReactions = { showMobileReactions = {
_reactionsEnabled && overflowMenuButtons.find(({ key }) => key === 'raisehand') _reactionsEnabled && (_isMobile || _isNarrowLayout)
}> }>
<ContextMenu <ContextMenu
accessibilityLabel = { t(toolbarAccLabel) } accessibilityLabel = { t(toolbarAccLabel) }
@ -1509,6 +1517,7 @@ class Toolbox extends Component<IProps> {
*/ */
function _mapStateToProps(state: IReduxState, ownProps: Partial<IProps>) { function _mapStateToProps(state: IReduxState, ownProps: Partial<IProps>) {
const { conference } = state['features/base/conference']; const { conference } = state['features/base/conference'];
const { isNarrowLayout } = state['features/base/responsive-ui'];
const endConferenceSupported = conference?.isEndConferenceSupported(); const endConferenceSupported = conference?.isEndConferenceSupported();
const { const {
@ -1551,6 +1560,7 @@ function _mapStateToProps(state: IReduxState, ownProps: Partial<IProps>) {
_jwtDisabledButons: getJwtDisabledButtons(state), _jwtDisabledButons: getJwtDisabledButtons(state),
_hasSalesforce: isSalesforceEnabled(state), _hasSalesforce: isSalesforceEnabled(state),
_hangupMenuVisible: hangupMenuVisible, _hangupMenuVisible: hangupMenuVisible,
_isNarrowLayout: isNarrowLayout,
_localParticipantID: localParticipant?.id, _localParticipantID: localParticipant?.id,
_localVideo: localVideo, _localVideo: localVideo,
_multiStreamModeEnabled: getMultipleVideoSendingSupportFeatureFlag(state), _multiStreamModeEnabled: getMultipleVideoSendingSupportFeatureFlag(state),

View File

@ -170,13 +170,14 @@ class VideoSettingsButton extends Component<Props> {
*/ */
function mapStateToProps(state) { function mapStateToProps(state) {
const { permissions = {} } = state['features/base/devices']; const { permissions = {} } = state['features/base/devices'];
const { isNarrowLayout } = state['features/base/responsive-ui'];
return { return {
hasPermissions: permissions.video, hasPermissions: permissions.video,
hasVideoTrack: Boolean(getLocalJitsiVideoTrack(state)), hasVideoTrack: Boolean(getLocalJitsiVideoTrack(state)),
isDisabled: isVideoSettingsButtonDisabled(state), isDisabled: isVideoSettingsButtonDisabled(state),
isOpen: getVideoSettingsVisibility(state), isOpen: getVideoSettingsVisibility(state),
visible: !isMobileBrowser() visible: !isMobileBrowser() && !isNarrowLayout
}; };
} }

View File

@ -221,7 +221,7 @@ class LocalVideoMenuTriggerButton extends Component<IProps> {
overflowDrawer = { _overflowDrawer } overflowDrawer = { _overflowDrawer }
position = { _menuPosition } position = { _menuPosition }
visible = { popoverVisible }> visible = { popoverVisible }>
{!_overflowDrawer && buttonVisible && !isMobileBrowser() && ( {buttonVisible && !isMobileBrowser() && (
<Button <Button
accessibilityLabel = { t('dialog.localUserControls') } accessibilityLabel = { t('dialog.localUserControls') }
className = { classes.triggerButton } className = { classes.triggerButton }

View File

@ -192,9 +192,10 @@ class RemoteVideoMenuTriggerButton extends Component<IProps> {
id = 'remote-video-menu-trigger' id = 'remote-video-menu-trigger'
onPopoverClose = { this._onPopoverClose } onPopoverClose = { this._onPopoverClose }
onPopoverOpen = { this._onPopoverOpen } onPopoverOpen = { this._onPopoverOpen }
overflowDrawer = { _overflowDrawer }
position = { this.props._menuPosition } position = { this.props._menuPosition }
visible = { popoverVisible }> visible = { popoverVisible }>
{!_overflowDrawer && buttonVisible && !_disabled && ( { buttonVisible && !_disabled && (
!isMobileBrowser() && <Button !isMobileBrowser() && <Button
accessibilityLabel = { this.props.t('dialog.remoteUserControls', { username }) } accessibilityLabel = { this.props.t('dialog.remoteUserControls', { username }) }
className = { classes.triggerButton } className = { classes.triggerButton }