Skip to content

Commit b5625ae

Browse files
authored
feat(mute): Add mute functionality (#9)
1 parent 54a11e2 commit b5625ae

File tree

6 files changed

+77
-26
lines changed

6 files changed

+77
-26
lines changed

src/client/redux/ducks/peer.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import { SOCKET_STREAM } from './socket'
22
import createObjectUrl from '../../utils/create-object-url'
3+
import { VIDEO_MUTE } from './room'
34
export const PEER_ADD = 'PEER_ADD'
45
export const PEER_REMOVE = 'PEER_REMOVE'
56

67
let initialState = {
78
/*
89
'peer-x': {
910
socketId: null,
10-
channel: null
11+
channel: null,
12+
muted: false
1113
}
1214
*/
1315
}
@@ -19,7 +21,8 @@ const peerReducer = (state = initialState, action) => {
1921
...state,
2022
[action.peerId]: {
2123
channel: action.channel,
22-
socketId: action.peerId
24+
socketId: action.peerId,
25+
muted: false
2326
}
2427
}
2528
case PEER_REMOVE:
@@ -39,6 +42,14 @@ const peerReducer = (state = initialState, action) => {
3942
streamUrl: createObjectUrl(action.stream)
4043
}
4144
}
45+
case VIDEO_MUTE:
46+
return {
47+
...state,
48+
[action.peerId]: {
49+
...state[action.peerId],
50+
muted: !state[action.peerId].muted
51+
}
52+
}
4253
default:
4354
return state
4455
}

src/client/redux/ducks/room.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ export const INITIALIZE = 'INITIALIZE'
44
export const INITIALIZE_SUCCESS = 'INITIALIZE_SUCCESS'
55
export const INITIALIZE_FAILED = 'INITIALIZE_FAILED'
66
export const SHUTDOWN = 'SHUTDOWN'
7+
export const VIDEO_MUTE = 'VIDEO_MUTE'
8+
9+
export const onMute = (peerId) => ({
10+
type: VIDEO_MUTE,
11+
peerId
12+
})
713

814
export const initialize = (roomId) => ({
915
type: INITIALIZE,

src/client/ui-components/video-container/index.js

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import React, { Component } from 'react'
22
import VideoPlayer from '../video'
3+
import { Grid, Row, Col } from 'react-bootstrap'
34
import PropTypes from 'prop-types'
45
import { connect } from 'react-redux'
6+
import { onMute } from '../../redux/ducks/room'
57
import { map, keys, chunk } from 'lodash'
68
import createObjectUrl from '../../utils/create-object-url'
7-
import cuid from 'cuid'
8-
import { Grid, Row, Col } from 'react-bootstrap'
99
import './index.css'
1010

1111
class VideoContainer extends Component {
1212
constructor (props) {
1313
super(props)
1414
this.videoRef = null
15+
this.playStream = this.playStream.bind(this)
1516
}
1617

1718
playStream (event) {
@@ -27,13 +28,23 @@ class VideoContainer extends Component {
2728
map(rowSets, (rowUsers, index) => (
2829
<Row key={`row-${index}`} className='show-grid flex'>
2930
{map(rowUsers, userId => (
30-
<Col md={4} key={`col-${index}-${userId}`} className='video-col'>
31+
<Col md={12 / rowUsers.length} key={`col-${index}-${userId}`} className='video-col'>
3132
<VideoPlayer
32-
metadata={this.props.users[userId].socketId}
33+
metadata={{
34+
socketId: this.props.users[userId].socketId,
35+
isMuted: this.props.users[userId].muted,
36+
disableMute: this.props.users[userId].disableMute
37+
}}
3338
src={this.props.users[userId].streamUrl || (this.props.users[userId].stream ? createObjectUrl(this.props.users[userId].stream) : '')}
34-
key={cuid()}
35-
muted={this.props.users[userId].muted}
39+
key={`video-${userId}`}
3640
onLoadedMetadata={this.playStream}
41+
onMute={event => {
42+
event.preventDefault()
43+
this.props.onMute(userId)
44+
}}
45+
disableMute={this.props.users[userId].disableMute}
46+
muted={this.props.users[userId].muted}
47+
showDebugInfo
3748
/>
3849
</Col>
3950
))}
@@ -52,28 +63,27 @@ VideoContainer.propTypes = {
5263
}),
5364
peer: PropTypes.object,
5465
users: PropTypes.object,
55-
usersPerRow: PropTypes.number
66+
usersPerRow: PropTypes.number,
67+
onMute: PropTypes.func
5668
}
5769

5870
VideoContainer.defaultProps = {
5971
usersPerRow: 3
6072
}
6173

6274
function mapStateToProps (state, ownProps) {
63-
const userSocketId = state.user && state.user.socket ? state.user.socket.id : null
75+
if (!state.user || !state.user.socket) return { users: {} }
6476
return {
65-
// user: state.user,
66-
// peer: state.peer,
67-
// numberOfUsers: (state.user ? 1 : 0) + (state.peer ? keys(state.peer) : 0),
6877
users: {
6978
...state.peer,
70-
[userSocketId]: {
79+
[state.user.socket.id]: {
7180
streamUrl: state.user ? state.user.streamUrl : null,
72-
socketId: userSocketId,
73-
muted: true
81+
socketId: state.user.socket.id,
82+
muted: true,
83+
disableMute: true
7484
}
7585
}
7686
}
7787
}
7888

79-
export default connect(mapStateToProps, {})(VideoContainer)
89+
export default connect(mapStateToProps, { onMute })(VideoContainer)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.video {
2+
width: 100%;
3+
}
4+
5+
.video-controls {
6+
width: 100%;
7+
position: relative;
8+
}
Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,44 @@
11
import React, { Component } from 'react'
22
import PropTypes from 'prop-types'
3+
import { Button, ButtonGroup } from 'react-bootstrap'
4+
import './index.css'
35

46
class VideoPlayer extends Component {
57
constructor (props) {
68
super(props)
79
this.videoRef = null
810
}
911
render () {
12+
const height = this.props.height ? { height: this.props.height } : {}
13+
const width = this.props.width ? { width: this.props.width } : { }
1014
return (
1115
<div>
1216
{this.props.showDebugInfo &&
1317
<span>
14-
{`INFO>>>`}
15-
{this.props.metadata}
18+
{`${JSON.stringify(this.props.metadata, null, 2)}`}
1619
</span>
1720
}
1821
<video
19-
height={this.props.height}
20-
width={this.props.width}
22+
className='video'
2123
src={this.props.src}
2224
ref={el => { this.videoRef = el }}
2325
muted={this.props.muted}
2426
onClick={this.props.onClick}
2527
autoPlay={this.props.autoPlay}
2628
playsInline={this.props.playsInline}
2729
onLoadedMetadata={this.props.onLoadedMetadata}
30+
{...height}
31+
{...width}
2832
/>
33+
{!this.props.disableMute &&
34+
<div className='video-controls'>
35+
<ButtonGroup vertical block>
36+
<Button onClick={this.props.onMute}>
37+
Mute
38+
</Button>
39+
</ButtonGroup>
40+
</div>
41+
}
2942
</div>
3043
)
3144
}
@@ -39,18 +52,21 @@ VideoPlayer.propTypes = {
3952
playsInline: PropTypes.bool,
4053
autoPlay: PropTypes.bool,
4154
onClick: PropTypes.func,
55+
onMute: PropTypes.func,
4256
onLoadedMetadata: PropTypes.func,
4357
showDebugInfo: PropTypes.bool,
44-
metadata: PropTypes.any
58+
metadata: PropTypes.any,
59+
disableMute: PropTypes.bool
4560
}
4661

4762
VideoPlayer.defaultProps = {
48-
height: 480,
49-
width: 500,
63+
height: null,
64+
width: null,
5065
playsInline: true,
5166
autoPlay: true,
5267
muted: false,
53-
showDebugInfo: false
68+
showDebugInfo: false,
69+
disableMute: false
5470
}
5571

5672
export default VideoPlayer

src/client/views/home/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export default class App extends Component {
66
return (
77
<div className='home'>
88
<div className='splash'>
9-
Connecting Worlds.
9+
Connecting Worlds
1010
</div>
1111
</div>
1212
)

0 commit comments

Comments
 (0)