parent
202f64024d
commit
37446bb804
12 changed files with 388 additions and 56 deletions
@ -0,0 +1,60 @@ |
||||
|
||||
import React, { Component } from 'react'; |
||||
import { withStyles } from "@material-ui/core/styles"; |
||||
import Switch from "@material-ui/core/Switch"; |
||||
|
||||
|
||||
const IOSSwitch = withStyles((theme) => ({ |
||||
root: { |
||||
width: 42, |
||||
height: 26, |
||||
padding: 0, |
||||
margin: theme.spacing(1), |
||||
}, |
||||
switchBase: { |
||||
padding: 1, |
||||
"&$checked": { |
||||
transform: "translateX(16px)", |
||||
color: theme.palette.common.white, |
||||
"& + $track": { |
||||
backgroundColor: "#52d869", |
||||
opacity: 1, |
||||
border: "none", |
||||
}, |
||||
}, |
||||
"&$focusVisible $thumb": { |
||||
color: "#52d869", |
||||
border: "6px solid #fff", |
||||
}, |
||||
}, |
||||
thumb: { |
||||
width: 24, |
||||
height: 24, |
||||
}, |
||||
track: { |
||||
borderRadius: 26 / 2, |
||||
border: `1px solid ${theme.palette.grey[400]}`, |
||||
backgroundColor: theme.palette.grey[50], |
||||
opacity: 1, |
||||
transition: theme.transitions.create(["background-color", "border"]), |
||||
}, |
||||
checked: {}, |
||||
focusVisible: {}, |
||||
}))(({ classes, ...props }) => { |
||||
return ( |
||||
<Switch |
||||
focusVisibleClassName={classes.focusVisible} |
||||
disableRipple |
||||
classes={{ |
||||
root: classes.root, |
||||
switchBase: classes.switchBase, |
||||
thumb: classes.thumb, |
||||
track: classes.track, |
||||
checked: classes.checked, |
||||
}} |
||||
{...props} |
||||
/> |
||||
); |
||||
}); |
||||
|
||||
export default IOSSwitch; |
@ -0,0 +1,67 @@ |
||||
import React from "react"; |
||||
import Badge from "@material-ui/core/Badge"; |
||||
import Avatar from "@material-ui/core/Avatar"; |
||||
import { makeStyles, withStyles } from "@material-ui/core/styles"; |
||||
|
||||
const StyledBadge = withStyles((theme) => ({ |
||||
badge: { |
||||
backgroundColor: "#44b700", |
||||
color: "#44b700", |
||||
boxShadow: `0 0 0 2px ${theme.palette.background.paper}`, |
||||
"&::after": { |
||||
position: "absolute", |
||||
top: 0, |
||||
left: 0, |
||||
width: "100%", |
||||
height: "100%", |
||||
borderRadius: "50%", |
||||
animation: "$ripple 1.2s infinite ease-in-out", |
||||
border: "1px solid currentColor", |
||||
content: '""', |
||||
}, |
||||
}, |
||||
"@keyframes ripple": { |
||||
"0%": { |
||||
transform: "scale(.8)", |
||||
opacity: 1, |
||||
}, |
||||
"100%": { |
||||
transform: "scale(2.4)", |
||||
opacity: 0, |
||||
}, |
||||
}, |
||||
}))(Badge); |
||||
|
||||
const useStyles = makeStyles((theme) => ({ |
||||
root: { |
||||
display: "flex", |
||||
"& > *": { |
||||
margin: 0, |
||||
}, |
||||
}, |
||||
})); |
||||
|
||||
export default function StatusAvatar(props) { |
||||
const classes = useStyles(); |
||||
|
||||
return ( |
||||
<div className={classes.root}> |
||||
{props.status ? ( |
||||
<StyledBadge |
||||
overlap="circle" |
||||
anchorOrigin={{ |
||||
vertical: "bottom", |
||||
horizontal: "right", |
||||
}} |
||||
variant="dot" |
||||
> |
||||
<Avatar style={{ width : 90, height :90}} alt="Remy Sharp" src={props.src} /> |
||||
</StyledBadge> |
||||
) : ( |
||||
<StyledBadge> |
||||
<Avatar style={{ width : 90, height :90}} alt="Remy Sharp" src={props.src} /> |
||||
</StyledBadge> |
||||
)} |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,41 @@ |
||||
import React, { Component } from "react"; |
||||
import MicIcon from '@material-ui/icons/Mic'; |
||||
import MicOffIcon from '@material-ui/icons/MicOff'; |
||||
import VideocamOffIcon from '@material-ui/icons/VideocamOff'; |
||||
import VideocamIcon from '@material-ui/icons/Videocam'; |
||||
import FlipCameraIosIcon from "@material-ui/icons/FlipCameraIos"; |
||||
import FormControlLabel from '@material-ui/core/FormControlLabel'; |
||||
import Checkbox from '@material-ui/core/Checkbox'; |
||||
|
||||
|
||||
import "./BottomControl.scss"; |
||||
export default class BottomControl extends Component { |
||||
render() { |
||||
return ( |
||||
<div className="bottom-control d-flex"> |
||||
<FormControlLabel |
||||
control={ |
||||
<Checkbox |
||||
icon={<MicIcon style={{ width: 31, height: 31, color: "#dfdfdf" }} />} |
||||
checkedIcon={<MicOffIcon style={{ width: 31, height: 31, color: "#dfdfdf" }} />} |
||||
name="checkedI" |
||||
/> |
||||
} |
||||
label="" |
||||
/> |
||||
<FormControlLabel |
||||
control={ |
||||
<Checkbox |
||||
icon={<VideocamIcon style={{ width: 31, height: 31, color: "#dfdfdf" }} />} |
||||
checkedIcon={<VideocamOffIcon style={{ width: 31, height: 31, color: "#dfdfdf" }} />} |
||||
name="checkedI" |
||||
/> |
||||
} |
||||
label="" |
||||
/> |
||||
<FlipCameraIosIcon style={{ width: 31, height: 31, color: "#dfdfdf" }} /> |
||||
|
||||
</div> |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,16 @@ |
||||
.bottom-control{ |
||||
width: 100%; |
||||
height: 70px; |
||||
align-items: center; |
||||
justify-content:space-between; |
||||
padding : 0px 30px; |
||||
position: fixed; |
||||
bottom: 0px; |
||||
left : 0px; |
||||
.MuiFormControlLabel-root{ |
||||
margin : 0px !important; |
||||
} |
||||
.PrivateSwitchBase-root-4{ |
||||
padding : 0px !important; |
||||
} |
||||
} |
@ -0,0 +1,26 @@ |
||||
import React, { Component } from "react"; |
||||
import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; |
||||
|
||||
import StatusAvatar from '../Avatar/Avatar'; |
||||
|
||||
export default class CallEnd extends Component { |
||||
constructor(props) { |
||||
super(props); |
||||
this.state = { |
||||
}; |
||||
} |
||||
render() { |
||||
const {brand,user} = this.props; |
||||
return ( |
||||
<div className="video-end d-flex"> |
||||
<header className="d-flex justify-content-center"> |
||||
<div className="video-calling__logo d-flex">{brand}</div> |
||||
<div className="video-calling__expand"> |
||||
<ExpandMoreIcon style={{ width : 30, height : 30 , color : 'white'}} /> |
||||
</div> |
||||
</header> |
||||
<StatusAvatar status={user.status} src={user.src} /> |
||||
</div> |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,26 @@ |
||||
import React, { Component } from "react"; |
||||
import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; |
||||
|
||||
import StatusAvatar from '../Avatar/Avatar'; |
||||
|
||||
export default class CallStart extends Component { |
||||
constructor(props) { |
||||
super(props); |
||||
this.state = { |
||||
}; |
||||
} |
||||
render() { |
||||
const {brand,user} = this.props; |
||||
return ( |
||||
<div className="video-end d-flex"> |
||||
<header className="d-flex"> |
||||
<div className="video-calling__logo">{brand}</div> |
||||
<div className="video-calling__expand"> |
||||
<ExpandMoreIcon style={{ width : 30, height : 30 , color : 'white'}} /> |
||||
</div> |
||||
</header> |
||||
<StatusAvatar status={user.status} src={user.src} /> |
||||
</div> |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
import React, { Component } from "react"; |
||||
import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; |
||||
import CallEndIcon from "@material-ui/icons/CallEnd"; |
||||
|
||||
import BottomControl from "../BottomControl/BottomControl"; |
||||
import StatusAvatar from "../Avatar/Avatar"; |
||||
|
||||
import "./Calling.scss"; |
||||
export default class Calling extends Component { |
||||
constructor(props) { |
||||
super(props); |
||||
this.state = {}; |
||||
} |
||||
render() { |
||||
const { brand, user, phase } = this.props; |
||||
return ( |
||||
<div className="video-calling d-flex flex-column"> |
||||
<header className="video-calling__header d-flex"> |
||||
<h1 className="video-calling__header--logo">{brand}</h1> |
||||
<div className="video-calling__header--expand d-flex"> |
||||
<ExpandMoreIcon style={{ width: 30, height: 30, color: "white" }} /> |
||||
</div> |
||||
</header> |
||||
<div className="video-calling__avatar d-flex"> |
||||
<StatusAvatar status={user.status} src={user.src} /> |
||||
</div> |
||||
<h2>{user.name}</h2> |
||||
<div className="video-calling__phase">{phase}</div> |
||||
<button className="video-calling__endButton"> |
||||
<CallEndIcon style={{ width: 30, height: 30, color: "white" }} /> |
||||
</button> |
||||
<BottomControl /> |
||||
</div> |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,62 @@ |
||||
.video-calling{ |
||||
width: 100%; |
||||
height: 100%; |
||||
align-items: center; |
||||
padding : 15px; |
||||
position: relative; |
||||
&__header{ |
||||
justify-content : center; |
||||
align-items: center; |
||||
width: 100%; |
||||
margin-bottom: 25px; |
||||
font-size: 16px; |
||||
position: fixed; |
||||
top : 20px; |
||||
left : 0px; |
||||
h1{ |
||||
font-size: 18px; |
||||
margin : 0px; |
||||
font-weight: 100; |
||||
letter-spacing: 1px; |
||||
// position : fixed; |
||||
// left : calc(50% - 35px); |
||||
// top : 100px; |
||||
} |
||||
&--expand{ |
||||
position: absolute; |
||||
left: 0px; |
||||
top : 0px; |
||||
} |
||||
} |
||||
&__avatar{ |
||||
position: fixed; |
||||
left: calc(50% - 45px); |
||||
top : 55px; |
||||
} |
||||
h2{ |
||||
font-size: 22px; |
||||
margin-top: 20px; |
||||
position: fixed; |
||||
left: calc(50% - 25px); |
||||
top : 140px; |
||||
} |
||||
&__phase{ |
||||
margin-top: 15px; |
||||
position: fixed; |
||||
left: calc(50% - 25px); |
||||
top : 200px; |
||||
} |
||||
&__endButton{ |
||||
width: 56px; |
||||
height: 56px; |
||||
border: none; |
||||
background-color:rgb(209, 52, 52); |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
border-radius: 50%; |
||||
position: fixed; |
||||
bottom : 100px; |
||||
left : calc(50% - 28px); |
||||
} |
||||
} |
@ -0,0 +1,42 @@ |
||||
import React, { Component } from "react"; |
||||
|
||||
import Calling from "./Calling/Calling"; |
||||
import CallStart from "./CallStart/CallStart"; |
||||
import CallEnd from "./CallEnd/CallEnd"; |
||||
|
||||
import pic from "../../assets/images/pic.png"; |
||||
|
||||
import "./VideoCall.scss"; |
||||
export default class VideoCall extends Component { |
||||
constructor(props) { |
||||
super(props); |
||||
this.state = { |
||||
phase: "Calling", |
||||
}; |
||||
} |
||||
render() { |
||||
const { phase } = this.state; |
||||
return ( |
||||
<div className="video-call d-flex"> |
||||
{phase === "Calling" ? ( |
||||
<Calling |
||||
brand={this.props.brand} |
||||
user={this.props.user} |
||||
phase={phase} |
||||
/> |
||||
) : null} |
||||
{phase === "Start" ? <CallStart /> : null} |
||||
{phase === "End" ? <CallEnd user={this.props.user} /> : null} |
||||
</div> |
||||
); |
||||
} |
||||
} |
||||
|
||||
VideoCall.defaultProps = { |
||||
brand: "نام برند", |
||||
user: { |
||||
status: 0, |
||||
src: pic, |
||||
name: "حسن", |
||||
}, |
||||
}; |
@ -0,0 +1,7 @@ |
||||
.video-call{ |
||||
height: 100vh; |
||||
width: 100vw; |
||||
overflow: hidden; |
||||
background-color: rgba(6, 14, 8, 0.849); |
||||
color: white; |
||||
} |
Loading…
Reference in new issue