refactor(virtual-background): use jss instead of sass (#11152)
This commit is contained in:
parent
3eafaeeedd
commit
70efa31c16
|
@ -40,7 +40,6 @@ $flagsImagePath: "../images/";
|
|||
@import 'modals/invite/info';
|
||||
@import 'modals/screen-share/share-audio';
|
||||
@import 'modals/screen-share/share-screen-warning';
|
||||
@import 'modals/virtual-background/virtual-background';
|
||||
@import 'modals/local-recording/local-recording';
|
||||
@import 'videolayout_default';
|
||||
@import 'notice';
|
||||
|
|
|
@ -1,207 +0,0 @@
|
|||
.virtual-background-dialog {
|
||||
margin-left: -10px;
|
||||
position: relative;
|
||||
max-height: 300px;
|
||||
color: white;
|
||||
display: inline-grid;
|
||||
grid-template-columns: auto auto auto auto auto;
|
||||
column-gap: 9px;
|
||||
cursor: pointer;
|
||||
.desktop-share:hover,
|
||||
.thumbnail:hover,
|
||||
.blur:hover,
|
||||
.slight-blur:hover,
|
||||
.virtual-background-none:hover {
|
||||
opacity: 0.5;
|
||||
border: 2px solid #99bbf3;
|
||||
@media (max-width: 632px) {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
}
|
||||
}
|
||||
.background-option {
|
||||
margin-top: 8px;
|
||||
border-radius: 6px;
|
||||
height: 60px;
|
||||
width: 107px;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.thumbnail {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.thumbnail:hover ~ .delete-image-icon {
|
||||
display: block;
|
||||
}
|
||||
.thumbnail-selected {
|
||||
object-fit: cover;
|
||||
border: 2px solid #246fe5;
|
||||
}
|
||||
.blur {
|
||||
box-shadow: inset 0 0 12px #000000;
|
||||
background: #7e8287;
|
||||
padding: 0 10px;
|
||||
}
|
||||
.blur-selected {
|
||||
box-shadow: inset 0 0 12px #000000;
|
||||
background: #7e8287;
|
||||
border: 2px solid #246fe5;
|
||||
padding: 0 10px;
|
||||
}
|
||||
.slight-blur {
|
||||
box-shadow: inset 0 0 12px #000000;
|
||||
background: #a4a4a4;
|
||||
padding: 0 10px;
|
||||
}
|
||||
.slight-blur-selected {
|
||||
box-shadow: inset 0 0 12px #000000;
|
||||
background: #a4a4a4;
|
||||
border: 2px solid #246fe5;
|
||||
padding: 0 10px;
|
||||
}
|
||||
.virtual-background-none {
|
||||
background: #525252;
|
||||
padding: 0 10px;
|
||||
}
|
||||
.none-selected {
|
||||
background: #525252;
|
||||
border: 2px solid #246fe5;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.desktop-share {
|
||||
background: #525252;
|
||||
}
|
||||
.desktop-share-selected {
|
||||
background: #525252;
|
||||
border: 2px solid #246fe5;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 632px) {
|
||||
font-size: 1.5vw;
|
||||
.desktop-share,
|
||||
.virtual-background-none,
|
||||
.thumbnail,
|
||||
.blur,
|
||||
.slight-blur {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
}
|
||||
.desktop-share-selected,
|
||||
.thumbnail-selected,
|
||||
.none-selected,
|
||||
.blur-selected,
|
||||
.slight-blur-selected {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 360px) {
|
||||
grid-template-columns: auto auto auto;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-dialog-form .virtual-background-loading {
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
margin-top: 10px;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.modal-dialog-form .video-preview {
|
||||
height: 250px;
|
||||
}
|
||||
.file-upload-btn {
|
||||
display: none;
|
||||
}
|
||||
.file-upload-label {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
margin-left: -10px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 8px;
|
||||
color: #669aec;
|
||||
display: inline-flex;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.delete-image-icon {
|
||||
background: #3d3d3d;
|
||||
position: absolute;
|
||||
display: none;
|
||||
left: 96;
|
||||
bottom: 51;
|
||||
@media (max-width: 632px) {
|
||||
left: 51px;
|
||||
}
|
||||
}
|
||||
|
||||
.delete-image-icon:hover {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.thumbnail-container {
|
||||
position: relative;
|
||||
&:focus-within {
|
||||
.thumbnail ~ .delete-image-icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-background {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.apply-background-btn {
|
||||
margin-top: 16px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.video-background-preview-entry {
|
||||
margin-left: -10px;
|
||||
height: 250px;
|
||||
width: 570px;
|
||||
margin-bottom: 8px;
|
||||
z-index: 2;
|
||||
@media (max-width: 632px) {
|
||||
max-width: 336;
|
||||
}
|
||||
}
|
||||
|
||||
.virtual-background-preview-video {
|
||||
margin-left: -10;
|
||||
border-radius: 6px;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
width: 100%;
|
||||
}
|
||||
.video-preview-loader {
|
||||
border-radius: 6px;
|
||||
background-color: transparent;
|
||||
height: 250px;
|
||||
margin-bottom: 8px;
|
||||
width: 572px;
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
@media (min-width: 432px) and (max-width: 632px) {
|
||||
width: 340px;
|
||||
}
|
||||
}
|
||||
|
||||
.video-preview-loader svg {
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 45%;
|
||||
}
|
||||
|
||||
.dialog-margin-top{
|
||||
margin-top: 44px;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
// @flow
|
||||
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
|
@ -42,6 +43,28 @@ type Props = {
|
|||
t: Function
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
return {
|
||||
addBackground: {
|
||||
marginRight: `${theme.spacing(2)}px`
|
||||
},
|
||||
button: {
|
||||
display: 'none'
|
||||
},
|
||||
label: {
|
||||
fontSize: '14px',
|
||||
fontWeight: '600',
|
||||
lineHeight: '20px',
|
||||
marginLeft: '-10px',
|
||||
marginTop: `${theme.spacing(3)}px`,
|
||||
marginBottom: `${theme.spacing(2)}px`,
|
||||
color: '#669aec',
|
||||
display: 'inline-flex',
|
||||
cursor: 'pointer'
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Component used to upload an image.
|
||||
*
|
||||
|
@ -56,6 +79,7 @@ function UploadImageButton({
|
|||
storedImages,
|
||||
t
|
||||
}: Props) {
|
||||
const classes = useStyles();
|
||||
const uploadImageButton: Object = useRef(null);
|
||||
const uploadImageKeyPress = useCallback(e => {
|
||||
if (uploadImageButton.current && (e.key === ' ' || e.key === 'Enter')) {
|
||||
|
@ -100,12 +124,12 @@ function UploadImageButton({
|
|||
<>
|
||||
{showLabel && <label
|
||||
aria-label = { t('virtualBackground.uploadImage') }
|
||||
className = 'file-upload-label'
|
||||
className = { classes.label }
|
||||
htmlFor = 'file-upload'
|
||||
onKeyPress = { uploadImageKeyPress }
|
||||
tabIndex = { 0 } >
|
||||
<Icon
|
||||
className = { 'add-background' }
|
||||
className = { classes.addBackground }
|
||||
size = { 20 }
|
||||
src = { IconPlusCircle } />
|
||||
{t('virtualBackground.addBackground')}
|
||||
|
@ -113,7 +137,7 @@ function UploadImageButton({
|
|||
|
||||
<input
|
||||
accept = 'image/*'
|
||||
className = 'file-upload-btn'
|
||||
className = { classes.button }
|
||||
id = 'file-upload'
|
||||
onChange = { uploadImage }
|
||||
ref = { uploadImageButton }
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
import Spinner from '@atlaskit/spinner';
|
||||
import Bourne from '@hapi/bourne';
|
||||
import { jitsiLocalStorage } from '@jitsi/js-utils/jitsi-local-storage';
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import clsx from 'clsx';
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
|
@ -106,6 +108,142 @@ function _mapStateToProps(state): Object {
|
|||
|
||||
const VirtualBackgroundDialog = translate(connect(_mapStateToProps)(VirtualBackground));
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
return {
|
||||
dialog: {
|
||||
marginLeft: '-10px',
|
||||
position: 'relative',
|
||||
maxHeight: '300px',
|
||||
color: 'white',
|
||||
display: 'inline-grid',
|
||||
gridTemplateColumns: 'auto auto auto auto auto',
|
||||
columnGap: '9px',
|
||||
cursor: 'pointer',
|
||||
[[ '& .desktop-share:hover',
|
||||
'& .thumbnail:hover',
|
||||
'& .blur:hover',
|
||||
'& .slight-blur:hover',
|
||||
'& .virtual-background-none:hover' ]]: {
|
||||
opacity: 0.5,
|
||||
border: '2px solid #99bbf3'
|
||||
},
|
||||
'& .background-option': {
|
||||
marginTop: `${theme.spacing(2)}px`,
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
height: '60px',
|
||||
width: '107px',
|
||||
textAlign: 'center',
|
||||
justifyContent: 'center',
|
||||
fontWeight: 'bold',
|
||||
boxSizing: 'border-box',
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
},
|
||||
'& thumbnail-container': {
|
||||
position: 'relative',
|
||||
'&:focus-within .thumbnail ~ .delete-image-icon': {
|
||||
display: 'block'
|
||||
}
|
||||
},
|
||||
'& .thumbnail': {
|
||||
objectFit: 'cover'
|
||||
},
|
||||
'& .thumbnail:hover ~ .delete-image-icon': {
|
||||
display: 'block'
|
||||
},
|
||||
'& .thumbnail-selected': {
|
||||
objectFit: 'cover',
|
||||
border: '2px solid #246fe5'
|
||||
},
|
||||
'& .blur': {
|
||||
boxShadow: 'inset 0 0 12px #000000',
|
||||
background: '#7e8287',
|
||||
padding: '0 10px'
|
||||
},
|
||||
'& .blur-selected': {
|
||||
border: '2px solid #246fe5'
|
||||
},
|
||||
'& .slight-blur': {
|
||||
boxShadow: 'inset 0 0 12px #000000',
|
||||
background: '#a4a4a4',
|
||||
padding: '0 10px'
|
||||
},
|
||||
'& .slight-blur-selected': {
|
||||
border: '2px solid #246fe5'
|
||||
},
|
||||
'& .virtual-background-none': {
|
||||
background: '#525252',
|
||||
padding: '0 10px'
|
||||
},
|
||||
'& .none-selected': {
|
||||
border: '2px solid #246fe5'
|
||||
},
|
||||
'& .desktop-share': {
|
||||
background: '#525252'
|
||||
},
|
||||
'& .desktop-share-selected': {
|
||||
border: '2px solid #246fe5',
|
||||
padding: '0 10px'
|
||||
},
|
||||
'& delete-image-icon': {
|
||||
background: '#3d3d3d',
|
||||
position: 'absolute',
|
||||
display: 'none',
|
||||
left: '96px',
|
||||
bottom: '51px',
|
||||
'&:hover': {
|
||||
display: 'block'
|
||||
},
|
||||
'@media (max-width: 632px)': {
|
||||
left: '51px'
|
||||
}
|
||||
},
|
||||
'@media (max-width: 360px)': {
|
||||
gridTemplateColumns: 'auto auto auto'
|
||||
},
|
||||
'@media (max-width: 632px)': {
|
||||
fontSize: '1.5vw',
|
||||
|
||||
[[ '& .desktop-share:hover',
|
||||
'& .thumbnail:hover',
|
||||
'& .blur:hover',
|
||||
'& .slight-blur:hover',
|
||||
'& .virtual-background-none:hover' ]]: {
|
||||
height: '60px',
|
||||
width: '60px'
|
||||
},
|
||||
|
||||
[[ '& .desktop-share',
|
||||
'& .virtual-background-none,',
|
||||
'& .thumbnail,',
|
||||
'& .blur,',
|
||||
'& .slight-blur' ]]: {
|
||||
height: '60px',
|
||||
width: '60px'
|
||||
},
|
||||
[[ '& .desktop-share-selected',
|
||||
'& .thumbnail-selected',
|
||||
'& .none-selected',
|
||||
'& .blur-selected',
|
||||
'& .slight-blur-selected' ]]: {
|
||||
height: '60px',
|
||||
width: '60px'
|
||||
}
|
||||
}
|
||||
},
|
||||
dialogMarginTop: {
|
||||
marginTop: '44px'
|
||||
},
|
||||
virtualBackgroundLoading: {
|
||||
overflow: 'hidden',
|
||||
position: 'fixed',
|
||||
left: '50%',
|
||||
marginTop: '10px',
|
||||
transform: 'translateX(-50%)'
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Renders virtual background dialog.
|
||||
*
|
||||
|
@ -122,6 +260,7 @@ function VirtualBackground({
|
|||
initialOptions,
|
||||
t
|
||||
}: Props) {
|
||||
const classes = useStyles();
|
||||
const [ previewIsLoaded, setPreviewIsLoaded ] = useState(false);
|
||||
const [ options, setOptions ] = useState({ ...initialOptions });
|
||||
const localImages = jitsiLocalStorage.getItem('virtualBackgrounds');
|
||||
|
@ -382,7 +521,7 @@ function VirtualBackground({
|
|||
loadedPreview = { loadedPreviewState }
|
||||
options = { options } />
|
||||
{loading ? (
|
||||
<div className = 'virtual-background-loading'>
|
||||
<div className = { classes.virtualBackgroundLoading }>
|
||||
<Spinner
|
||||
isCompleting = { false }
|
||||
size = 'medium' />
|
||||
|
@ -397,7 +536,7 @@ function VirtualBackground({
|
|||
showLabel = { previewIsLoaded }
|
||||
storedImages = { storedImages } />}
|
||||
<div
|
||||
className = { `virtual-background-dialog${previewIsLoaded ? '' : ' dialog-margin-top'}` }
|
||||
className = { clsx(classes.dialog, { [classes.dialogMarginTop]: previewIsLoaded }) }
|
||||
role = 'radiogroup'
|
||||
tabIndex = '-1'>
|
||||
<Tooltip
|
||||
|
@ -406,8 +545,9 @@ function VirtualBackground({
|
|||
<div
|
||||
aria-checked = { _selectedThumbnail === 'none' }
|
||||
aria-label = { t('virtualBackground.removeBackground') }
|
||||
className = { _selectedThumbnail === 'none' ? 'background-option none-selected'
|
||||
: 'background-option virtual-background-none' }
|
||||
className = { clsx('background-option', 'virtual-background-none', {
|
||||
'none-selected': _selectedThumbnail === 'none'
|
||||
}) }
|
||||
onClick = { removeBackground }
|
||||
onKeyPress = { removeBackgroundKeyPress }
|
||||
role = 'radio'
|
||||
|
@ -421,8 +561,9 @@ function VirtualBackground({
|
|||
<div
|
||||
aria-checked = { _selectedThumbnail === 'slight-blur' }
|
||||
aria-label = { t('virtualBackground.slightBlur') }
|
||||
className = { _selectedThumbnail === 'slight-blur'
|
||||
? 'background-option slight-blur-selected' : 'background-option slight-blur' }
|
||||
className = { clsx('background-option', 'slight-blur', {
|
||||
'slight-blur-selected': _selectedThumbnail === 'slight-blur'
|
||||
}) }
|
||||
onClick = { enableSlideBlur }
|
||||
onKeyPress = { enableSlideBlurKeyPress }
|
||||
role = 'radio'
|
||||
|
@ -436,8 +577,9 @@ function VirtualBackground({
|
|||
<div
|
||||
aria-checked = { _selectedThumbnail === 'blur' }
|
||||
aria-label = { t('virtualBackground.blur') }
|
||||
className = { _selectedThumbnail === 'blur' ? 'background-option blur-selected'
|
||||
: 'background-option blur' }
|
||||
className = { clsx('background-option', 'blur', {
|
||||
'blur-selected': _selectedThumbnail === 'blur'
|
||||
}) }
|
||||
onClick = { enableBlur }
|
||||
onKeyPress = { enableBlurKeyPress }
|
||||
role = 'radio'
|
||||
|
@ -452,9 +594,9 @@ function VirtualBackground({
|
|||
<div
|
||||
aria-checked = { _selectedThumbnail === 'desktop-share' }
|
||||
aria-label = { t('virtualBackground.desktopShare') }
|
||||
className = { _selectedThumbnail === 'desktop-share'
|
||||
? 'background-option desktop-share-selected'
|
||||
: 'background-option desktop-share' }
|
||||
className = { clsx('background-option', 'desktop-share', {
|
||||
'desktop-share-selected': _selectedThumbnail === 'desktop-share'
|
||||
}) }
|
||||
onClick = { shareDesktop }
|
||||
onKeyPress = { shareDesktopKeyPress }
|
||||
role = 'radio'
|
||||
|
@ -494,8 +636,10 @@ function VirtualBackground({
|
|||
<img
|
||||
alt = { t('virtualBackground.uploadedImage', { index: index + 1 }) }
|
||||
aria-checked = { _selectedThumbnail === image.id }
|
||||
className = { _selectedThumbnail === image.id
|
||||
? 'background-option thumbnail-selected' : 'background-option thumbnail' }
|
||||
className = { clsx('background-option', {
|
||||
'thumbnail-selected': _selectedThumbnail === image.id,
|
||||
'thumbnail': _selectedThumbnail !== image.id
|
||||
}) }
|
||||
data-imageid = { image.id }
|
||||
onClick = { setUploadedImageBackground }
|
||||
onError = { onError }
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import Spinner from '@atlaskit/spinner';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
import { hideDialog } from '../../base/dialog';
|
||||
|
@ -29,6 +30,11 @@ export type Props = {
|
|||
*/
|
||||
_currentCameraDeviceId: string,
|
||||
|
||||
/**
|
||||
* An object containing the CSS classes.
|
||||
*/
|
||||
classes: Object,
|
||||
|
||||
/**
|
||||
* The redux {@code dispatch} function.
|
||||
*/
|
||||
|
@ -71,6 +77,55 @@ type State = {
|
|||
jitsiTrack: Object
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates the styles for the component.
|
||||
*
|
||||
* @param {Object} theme - The current UI theme.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
const styles = theme => {
|
||||
return {
|
||||
virtualBackgroundPreview: {
|
||||
'& .video-preview': {
|
||||
height: '250px'
|
||||
},
|
||||
|
||||
'& .video-background-preview-entry': {
|
||||
marginLeft: '-10px',
|
||||
height: '250px',
|
||||
width: '570px',
|
||||
marginBottom: `${theme.spacing(2)}px`,
|
||||
zIndex: 2,
|
||||
|
||||
'@media (max-width: 632px)': {
|
||||
maxWidth: '336px'
|
||||
}
|
||||
},
|
||||
|
||||
'& .video-preview-loader': {
|
||||
borderRadius: '6px',
|
||||
backgroundColor: 'transparent',
|
||||
height: '250px',
|
||||
marginBottom: `${theme.spacing(2)}px`,
|
||||
width: '572px',
|
||||
position: 'fixed',
|
||||
zIndex: 2,
|
||||
|
||||
'& svg': {
|
||||
position: 'absolute',
|
||||
top: '40%',
|
||||
left: '45%'
|
||||
},
|
||||
|
||||
'@media (min-width: 432px) and (max-width: 632px)': {
|
||||
width: '340px'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements a React {@link PureComponent} which displays the virtual
|
||||
* background preview.
|
||||
|
@ -264,12 +319,13 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
|
|||
* @inheritdoc
|
||||
*/
|
||||
render() {
|
||||
const { jitsiTrack } = this.state;
|
||||
const { classes, jitsiTrack } = this.state;
|
||||
|
||||
return jitsiTrack
|
||||
? <div className = 'video-preview'>{this._renderPreviewEntry(jitsiTrack)}</div>
|
||||
: <div className = 'video-preview-loader'>{this._loadVideoPreview()}</div>
|
||||
;
|
||||
return (<div className = { classes.virtualBackgroundPreview }>
|
||||
{jitsiTrack
|
||||
? <div className = 'video-preview'>{this._renderPreviewEntry(jitsiTrack)}</div>
|
||||
: <div className = 'video-preview-loader'>{this._loadVideoPreview()}</div>
|
||||
}</div>);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,4 +343,4 @@ function _mapStateToProps(state): Object {
|
|||
};
|
||||
}
|
||||
|
||||
export default translate(connect(_mapStateToProps)(VirtualBackgroundPreview));
|
||||
export default translate(connect(_mapStateToProps)(withStyles(styles)(VirtualBackgroundPreview)));
|
||||
|
|
Loading…
Reference in New Issue