Fix button sizes and take care not to overflow container in filmstrip, ref #115

auto_join_3.3
Håvar Aambø Fosstveit 2020-05-05 14:29:54 +02:00
parent 3f75a6c506
commit 2bb64596b0
3 changed files with 474 additions and 210 deletions

View File

@ -10,6 +10,7 @@ import { useIntl, FormattedMessage } from 'react-intl';
import VideoView from '../VideoContainers/VideoView'; import VideoView from '../VideoContainers/VideoView';
import Volume from './Volume'; import Volume from './Volume';
import Fab from '@material-ui/core/Fab'; import Fab from '@material-ui/core/Fab';
import IconButton from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip'; import Tooltip from '@material-ui/core/Tooltip';
import MicIcon from '@material-ui/icons/Mic'; import MicIcon from '@material-ui/icons/Mic';
import MicOffIcon from '@material-ui/icons/MicOff'; import MicOffIcon from '@material-ui/icons/MicOff';
@ -59,6 +60,19 @@ const styles = (theme) =>
margin : theme.spacing(1), margin : theme.spacing(1),
pointerEvents : 'auto' pointerEvents : 'auto'
}, },
smallContainer :
{
backgroundColor : 'rgba(255, 255, 255, 0.9)',
margin : theme.spacing(0.25),
padding : theme.spacing(0.75),
boxShadow : '0px 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 6px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 18px 0px rgba(0, 0, 0, 0.12)',
pointerEvents : 'auto',
transition : 'background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
'&:hover' :
{
backgroundColor : 'rgba(213, 213, 213, 1)'
}
},
viewContainer : viewContainer :
{ {
position : 'relative', position : 'relative',
@ -102,6 +116,10 @@ const styles = (theme) =>
'&.hover' : '&.hover' :
{ {
opacity : 1 opacity : 1
},
'&.smallContainer' :
{
fontSize : '3em'
} }
} }
}, },
@ -145,7 +163,7 @@ const Me = (props) =>
activeSpeaker, activeSpeaker,
spacing, spacing,
style, style,
smallButtons, smallContainer,
advancedMode, advancedMode,
micProducer, micProducer,
webcamProducer, webcamProducer,
@ -300,16 +318,18 @@ const Me = (props) =>
style={spacingStyle} style={spacingStyle}
> >
<div className={classes.viewContainer} style={style}> <div className={classes.viewContainer} style={style}>
<div className={classnames( { !smallContainer &&
classes.ptt, <div className={classnames(
(micState === 'muted' && me.isSpeaking) ? 'enabled' : null classes.ptt,
)} (micState === 'muted' && me.isSpeaking) ? 'enabled' : null
> )}
<FormattedMessage >
id='me.mutedPTT' <FormattedMessage
defaultMessage='You are muted, hold down SPACE-BAR to talk' id='me.mutedPTT'
/> defaultMessage='You are muted, hold down SPACE-BAR to talk'
</div> />
</div>
}
<div <div
className={classnames( className={classnames(
classes.controls, classes.controls,
@ -336,7 +356,12 @@ const Me = (props) =>
}, 2000); }, 2000);
}} }}
> >
<p className={hover ? 'hover' : null}> <p className={
classnames(
hover ? 'hover' : null,
smallContainer ? 'smallContainer' : null
)}
>
<FormattedMessage <FormattedMessage
id='room.me' id='room.me'
defaultMessage='ME' defaultMessage='ME'
@ -346,103 +371,201 @@ const Me = (props) =>
<React.Fragment> <React.Fragment>
<Tooltip title={micTip} placement='left'> <Tooltip title={micTip} placement='left'>
<div> <div>
<Fab { smallContainer ?
aria-label={intl.formatMessage({ <IconButton
id : 'device.muteAudio', aria-label={intl.formatMessage({
defaultMessage : 'Mute audio' id : 'device.muteAudio',
})} defaultMessage : 'Mute audio'
className={classes.fab} })}
disabled={!me.canSendMic || me.audioInProgress} className={classes.smallContainer}
color={micState === 'on' ? 'default' : 'secondary'} disabled={!me.canSendMic || me.audioInProgress}
size={smallButtons ? 'small' : 'large'} color={micState === 'on' ? 'primary' : 'secondary'}
onClick={() => size='small'
{ onClick={() =>
if (micState === 'off') {
roomClient.enableMic(); if (micState === 'off')
else if (micState === 'on') roomClient.enableMic();
roomClient.muteMic(); else if (micState === 'on')
else roomClient.muteMic();
roomClient.unmuteMic(); else
}} roomClient.unmuteMic();
> }}
{ micState === 'on' ? >
<MicIcon /> { micState === 'on' ?
: <MicIcon />
<MicOffIcon /> :
} <MicOffIcon />
</Fab> }
</IconButton>
:
<Fab
aria-label={intl.formatMessage({
id : 'device.muteAudio',
defaultMessage : 'Mute audio'
})}
className={classes.fab}
disabled={!me.canSendMic || me.audioInProgress}
color={micState === 'on' ? 'default' : 'secondary'}
size='large'
onClick={() =>
{
if (micState === 'off')
roomClient.enableMic();
else if (micState === 'on')
roomClient.muteMic();
else
roomClient.unmuteMic();
}}
>
{ micState === 'on' ?
<MicIcon />
:
<MicOffIcon />
}
</Fab>
}
</div> </div>
</Tooltip> </Tooltip>
<Tooltip title={webcamTip} placement='left'> <Tooltip title={webcamTip} placement='left'>
<div> <div>
<Fab { smallContainer ?
aria-label={intl.formatMessage({ <IconButton
id : 'device.startVideo', aria-label={intl.formatMessage({
defaultMessage : 'Start video' id : 'device.startVideo',
})} defaultMessage : 'Start video'
className={classes.fab} })}
disabled={!me.canSendWebcam || me.webcamInProgress} className={classes.smallContainer}
color={webcamState === 'on' ? 'default' : 'secondary'} disabled={!me.canSendWebcam || me.webcamInProgress}
size={smallButtons ? 'small' : 'large'} color={webcamState === 'on' ? 'primary' : 'secondary'}
onClick={() => size='small'
{ onClick={() =>
webcamState === 'on' ? {
roomClient.disableWebcam() : webcamState === 'on' ?
roomClient.enableWebcam(); roomClient.disableWebcam() :
}} roomClient.enableWebcam();
> }}
{ webcamState === 'on' ? >
<VideoIcon /> { webcamState === 'on' ?
: <VideoIcon />
<VideoOffIcon /> :
} <VideoOffIcon />
</Fab> }
</IconButton>
:
<Fab
aria-label={intl.formatMessage({
id : 'device.startVideo',
defaultMessage : 'Start video'
})}
className={classes.fab}
disabled={!me.canSendWebcam || me.webcamInProgress}
color={webcamState === 'on' ? 'default' : 'secondary'}
size='large'
onClick={() =>
{
webcamState === 'on' ?
roomClient.disableWebcam() :
roomClient.enableWebcam();
}}
>
{ webcamState === 'on' ?
<VideoIcon />
:
<VideoOffIcon />
}
</Fab>
}
</div> </div>
</Tooltip> </Tooltip>
{ me.browser.platform !== 'mobile' && { me.browser.platform !== 'mobile' &&
<Tooltip title={screenTip} placement='left'> <Tooltip title={screenTip} placement='left'>
<div> <div>
<Fab { smallContainer ?
aria-label={intl.formatMessage({ <IconButton
id : 'device.startScreenSharing', aria-label={intl.formatMessage({
defaultMessage : 'Start screen sharing' id : 'device.startScreenSharing',
})} defaultMessage : 'Start screen sharing'
className={classes.fab} })}
disabled={ className={classes.smallContainer}
!canShareScreen || disabled={
!me.canShareScreen || !canShareScreen ||
me.screenShareInProgress !me.canShareScreen ||
} me.screenShareInProgress
color={screenState === 'on' ? 'primary' : 'default'}
size={smallButtons ? 'small' : 'large'}
onClick={() =>
{
switch (screenState)
{
case 'on':
{
roomClient.disableScreenSharing();
break;
}
case 'off':
{
roomClient.enableScreenSharing();
break;
}
default:
{
break;
}
} }
}} color='primary'
> size='small'
{ (screenState === 'on' || screenState === 'unsupported') && onClick={() =>
<ScreenOffIcon/> {
} switch (screenState)
{ screenState === 'off' && {
<ScreenIcon/> case 'on':
} {
</Fab> roomClient.disableScreenSharing();
break;
}
case 'off':
{
roomClient.enableScreenSharing();
break;
}
default:
{
break;
}
}
}}
>
{ (screenState === 'on' || screenState === 'unsupported') &&
<ScreenOffIcon/>
}
{ screenState === 'off' &&
<ScreenIcon/>
}
</IconButton>
:
<Fab
aria-label={intl.formatMessage({
id : 'device.startScreenSharing',
defaultMessage : 'Start screen sharing'
})}
className={classes.fab}
disabled={
!canShareScreen ||
!me.canShareScreen ||
me.screenShareInProgress
}
color={screenState === 'on' ? 'primary' : 'default'}
size='large'
onClick={() =>
{
switch (screenState)
{
case 'on':
{
roomClient.disableScreenSharing();
break;
}
case 'off':
{
roomClient.enableScreenSharing();
break;
}
default:
{
break;
}
}
}}
>
{ (screenState === 'on' || screenState === 'unsupported') &&
<ScreenOffIcon/>
}
{ screenState === 'off' &&
<ScreenIcon/>
}
</Fab>
}
</div> </div>
</Tooltip> </Tooltip>
} }
@ -537,21 +660,41 @@ const Me = (props) =>
<Tooltip title={webcamTip} placement='left'> <Tooltip title={webcamTip} placement='left'>
<div> <div>
<Fab { smallContainer ?
aria-label={intl.formatMessage({ <IconButton
id : 'device.stopVideo', aria-label={intl.formatMessage({
defaultMessage : 'Stop video' id : 'device.stopVideo',
})} defaultMessage : 'Stop video'
className={classes.fab} })}
disabled={!me.canSendWebcam || me.webcamInProgress} className={classes.smallContainer}
size={smallButtons ? 'small' : 'large'} disabled={!me.canSendWebcam || me.webcamInProgress}
onClick={() => size='small'
{ color='primary'
roomClient.disableExtraVideo(producer.id); onClick={() =>
}} {
> roomClient.disableExtraVideo(producer.id);
<VideoIcon /> }}
</Fab> >
<VideoIcon />
</IconButton>
:
<Fab
aria-label={intl.formatMessage({
id : 'device.stopVideo',
defaultMessage : 'Stop video'
})}
className={classes.fab}
disabled={!me.canSendWebcam || me.webcamInProgress}
size={smallContainer ? 'small' : 'large'}
onClick={() =>
{
roomClient.disableExtraVideo(producer.id);
}}
>
<VideoIcon />
</Fab>
}
</div> </div>
</Tooltip> </Tooltip>
</div> </div>
@ -663,7 +806,7 @@ Me.propTypes =
extraVideoProducers : PropTypes.arrayOf(appPropTypes.Producer), extraVideoProducers : PropTypes.arrayOf(appPropTypes.Producer),
spacing : PropTypes.number, spacing : PropTypes.number,
style : PropTypes.object, style : PropTypes.object,
smallButtons : PropTypes.bool, smallContainer : PropTypes.bool,
canShareScreen : PropTypes.bool.isRequired, canShareScreen : PropTypes.bool.isRequired,
classes : PropTypes.object.isRequired, classes : PropTypes.object.isRequired,
theme : PropTypes.object.isRequired theme : PropTypes.object.isRequired

View File

@ -12,6 +12,7 @@ import { useIntl, FormattedMessage } from 'react-intl';
import VideoView from '../VideoContainers/VideoView'; import VideoView from '../VideoContainers/VideoView';
import Tooltip from '@material-ui/core/Tooltip'; import Tooltip from '@material-ui/core/Tooltip';
import Fab from '@material-ui/core/Fab'; import Fab from '@material-ui/core/Fab';
import IconButton from '@material-ui/core/IconButton';
import VolumeUpIcon from '@material-ui/icons/VolumeUp'; import VolumeUpIcon from '@material-ui/icons/VolumeUp';
import VolumeOffIcon from '@material-ui/icons/VolumeOff'; import VolumeOffIcon from '@material-ui/icons/VolumeOff';
import NewWindowIcon from '@material-ui/icons/OpenInNew'; import NewWindowIcon from '@material-ui/icons/OpenInNew';
@ -59,6 +60,19 @@ const styles = (theme) =>
{ {
margin : theme.spacing(1) margin : theme.spacing(1)
}, },
smallContainer :
{
backgroundColor : 'rgba(255, 255, 255, 0.9)',
margin : theme.spacing(0.25),
padding : theme.spacing(0.75),
boxShadow : '0px 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 6px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 18px 0px rgba(0, 0, 0, 0.12)',
pointerEvents : 'auto',
transition : 'background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
'&:hover' :
{
backgroundColor : 'rgba(213, 213, 213, 1)'
}
},
viewContainer : viewContainer :
{ {
position : 'relative', position : 'relative',
@ -130,7 +144,7 @@ const Peer = (props) =>
toggleConsumerWindow, toggleConsumerWindow,
spacing, spacing,
style, style,
smallButtons, smallContainer,
windowConsumer, windowConsumer,
classes, classes,
theme theme
@ -236,28 +250,53 @@ const Peer = (props) =>
placement={smallScreen ? 'top' : 'left'} placement={smallScreen ? 'top' : 'left'}
> >
<div> <div>
<Fab { smallContainer ?
aria-label={intl.formatMessage({ <IconButton
id : 'device.muteAudio', aria-label={intl.formatMessage({
defaultMessage : 'Mute audio' id : 'device.muteAudio',
})} defaultMessage : 'Mute audio'
className={classes.fab} })}
disabled={!micConsumer} className={classes.smallContainer}
color={micEnabled ? 'default' : 'secondary'} disabled={!micConsumer}
size={smallButtons ? 'small' : 'large'} color='primary'
onClick={() => size='small'
{ onClick={() =>
micEnabled ? {
roomClient.modifyPeerConsumer(peer.id, 'mic', true) : micEnabled ?
roomClient.modifyPeerConsumer(peer.id, 'mic', false); roomClient.modifyPeerConsumer(peer.id, 'mic', true) :
}} roomClient.modifyPeerConsumer(peer.id, 'mic', false);
> }}
{ micEnabled ? >
<VolumeUpIcon /> { micEnabled ?
: <VolumeUpIcon />
<VolumeOffIcon /> :
} <VolumeOffIcon />
</Fab> }
</IconButton>
:
<Fab
aria-label={intl.formatMessage({
id : 'device.muteAudio',
defaultMessage : 'Mute audio'
})}
className={classes.fab}
disabled={!micConsumer}
color={micEnabled ? 'default' : 'secondary'}
size='large'
onClick={() =>
{
micEnabled ?
roomClient.modifyPeerConsumer(peer.id, 'mic', true) :
roomClient.modifyPeerConsumer(peer.id, 'mic', false);
}}
>
{ micEnabled ?
<VolumeUpIcon />
:
<VolumeOffIcon />
}
</Fab>
}
</div> </div>
</Tooltip> </Tooltip>
@ -270,24 +309,46 @@ const Peer = (props) =>
placement={smallScreen ? 'top' : 'left'} placement={smallScreen ? 'top' : 'left'}
> >
<div> <div>
<Fab { smallContainer ?
aria-label={intl.formatMessage({ <IconButton
id : 'label.newWindow', aria-label={intl.formatMessage({
defaultMessage : 'New window' id : 'label.newWindow',
})} defaultMessage : 'New window'
className={classes.fab} })}
disabled={ className={classes.smallContainer}
!videoVisible || disabled={
(windowConsumer === webcamConsumer.id) !videoVisible ||
} (windowConsumer === webcamConsumer.id)
size={smallButtons ? 'small' : 'large'} }
onClick={() => size='small'
{ color='primary'
toggleConsumerWindow(webcamConsumer); onClick={() =>
}} {
> toggleConsumerWindow(webcamConsumer);
<NewWindowIcon /> }}
</Fab> >
<NewWindowIcon />
</IconButton>
:
<Fab
aria-label={intl.formatMessage({
id : 'label.newWindow',
defaultMessage : 'New window'
})}
className={classes.fab}
disabled={
!videoVisible ||
(windowConsumer === webcamConsumer.id)
}
size='large'
onClick={() =>
{
toggleConsumerWindow(webcamConsumer);
}}
>
<NewWindowIcon />
</Fab>
}
</div> </div>
</Tooltip> </Tooltip>
} }
@ -300,21 +361,40 @@ const Peer = (props) =>
placement={smallScreen ? 'top' : 'left'} placement={smallScreen ? 'top' : 'left'}
> >
<div> <div>
<Fab { smallContainer ?
aria-label={intl.formatMessage({ <IconButton
id : 'label.fullscreen', aria-label={intl.formatMessage({
defaultMessage : 'Fullscreen' id : 'label.fullscreen',
})} defaultMessage : 'Fullscreen'
className={classes.fab} })}
disabled={!videoVisible} className={classes.smallContainer}
size={smallButtons ? 'small' : 'large'} disabled={!videoVisible}
onClick={() => size='small'
{ color='primary'
toggleConsumerFullscreen(webcamConsumer); onClick={() =>
}} {
> toggleConsumerFullscreen(webcamConsumer);
<FullScreenIcon /> }}
</Fab> >
<FullScreenIcon />
</IconButton>
:
<Fab
aria-label={intl.formatMessage({
id : 'label.fullscreen',
defaultMessage : 'Fullscreen'
})}
className={classes.fab}
disabled={!videoVisible}
size='large'
onClick={() =>
{
toggleConsumerFullscreen(webcamConsumer);
}}
>
<FullScreenIcon />
</Fab>
}
</div> </div>
</Tooltip> </Tooltip>
</div> </div>
@ -428,24 +508,46 @@ const Peer = (props) =>
placement={smallScreen ? 'top' : 'left'} placement={smallScreen ? 'top' : 'left'}
> >
<div> <div>
<Fab { smallContainer ?
aria-label={intl.formatMessage({ <IconButton
id : 'label.newWindow', aria-label={intl.formatMessage({
defaultMessage : 'New window' id : 'label.newWindow',
})} defaultMessage : 'New window'
className={classes.fab} })}
disabled={ className={classes.smallContainer}
!videoVisible || disabled={
(windowConsumer === consumer.id) !videoVisible ||
} (windowConsumer === consumer.id)
size={smallButtons ? 'small' : 'large'} }
onClick={() => size='small'
{ color='primary'
toggleConsumerWindow(consumer); onClick={() =>
}} {
> toggleConsumerWindow(consumer);
<NewWindowIcon /> }}
</Fab> >
<NewWindowIcon />
</IconButton>
:
<Fab
aria-label={intl.formatMessage({
id : 'label.newWindow',
defaultMessage : 'New window'
})}
className={classes.fab}
disabled={
!videoVisible ||
(windowConsumer === consumer.id)
}
size='large'
onClick={() =>
{
toggleConsumerWindow(consumer);
}}
>
<NewWindowIcon />
</Fab>
}
</div> </div>
</Tooltip> </Tooltip>
} }
@ -458,21 +560,40 @@ const Peer = (props) =>
placement={smallScreen ? 'top' : 'left'} placement={smallScreen ? 'top' : 'left'}
> >
<div> <div>
<Fab { smallContainer ?
aria-label={intl.formatMessage({ <IconButton
id : 'label.fullscreen', aria-label={intl.formatMessage({
defaultMessage : 'Fullscreen' id : 'label.fullscreen',
})} defaultMessage : 'Fullscreen'
className={classes.fab} })}
disabled={!videoVisible} className={classes.smallContainer}
size={smallButtons ? 'small' : 'large'} disabled={!videoVisible}
onClick={() => size='small'
{ color='primary'
toggleConsumerFullscreen(consumer); onClick={() =>
}} {
> toggleConsumerFullscreen(consumer);
<FullScreenIcon /> }}
</Fab> >
<FullScreenIcon />
</IconButton>
:
<Fab
aria-label={intl.formatMessage({
id : 'label.fullscreen',
defaultMessage : 'Fullscreen'
})}
className={classes.fab}
disabled={!videoVisible}
size='large'
onClick={() =>
{
toggleConsumerFullscreen(consumer);
}}
>
<FullScreenIcon />
</Fab>
}
</div> </div>
</Tooltip> </Tooltip>
</div> </div>
@ -584,7 +705,7 @@ const Peer = (props) =>
!screenVisible || !screenVisible ||
(windowConsumer === screenConsumer.id) (windowConsumer === screenConsumer.id)
} }
size={smallButtons ? 'small' : 'large'} size={smallContainer ? 'small' : 'large'}
onClick={() => onClick={() =>
{ {
toggleConsumerWindow(screenConsumer); toggleConsumerWindow(screenConsumer);
@ -611,7 +732,7 @@ const Peer = (props) =>
})} })}
className={classes.fab} className={classes.fab}
disabled={!screenVisible} disabled={!screenVisible}
size={smallButtons ? 'small' : 'large'} size={smallContainer ? 'small' : 'large'}
onClick={() => onClick={() =>
{ {
toggleConsumerFullscreen(screenConsumer); toggleConsumerFullscreen(screenConsumer);
@ -670,7 +791,7 @@ Peer.propTypes =
browser : PropTypes.object.isRequired, browser : PropTypes.object.isRequired,
spacing : PropTypes.number, spacing : PropTypes.number,
style : PropTypes.object, style : PropTypes.object,
smallButtons : PropTypes.bool, smallContainer : PropTypes.bool,
toggleConsumerFullscreen : PropTypes.func.isRequired, toggleConsumerFullscreen : PropTypes.func.isRequired,
toggleConsumerWindow : PropTypes.func.isRequired, toggleConsumerWindow : PropTypes.func.isRequired,
classes : PropTypes.object.isRequired, classes : PropTypes.object.isRequired,

View File

@ -49,7 +49,7 @@ const styles = () =>
}, },
'&.active' : '&.active' :
{ {
opacity : '0.6' borderColor : 'var(--selected-peer-border-color)'
} }
}, },
hiddenToolBar : hiddenToolBar :
@ -279,7 +279,7 @@ class Filmstrip extends React.PureComponent
<Me <Me
advancedMode={advancedMode} advancedMode={advancedMode}
style={peerStyle} style={peerStyle}
smallButtons smallContainer
/> />
</div> </div>
</Grid> </Grid>
@ -302,7 +302,7 @@ class Filmstrip extends React.PureComponent
advancedMode={advancedMode} advancedMode={advancedMode}
id={peerId} id={peerId}
style={peerStyle} style={peerStyle}
smallButtons smallContainer
/> />
</div> </div>
</Grid> </Grid>