-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathplayerComponent.jsx
142 lines (128 loc) · 5.25 KB
/
playerComponent.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import React from "react";
import { Component } from "react";
import SetVolume from "../ControlAPIs/setVolume";
import GetPlayerVolume from "../ControlAPIs/getPlayerVolume";
import HelperControls from "../ControlAPIs/playerControls";
import PlayerVolumeSubscribe from "../UserDetails/playerVolumeSubscribe";
import {debounce} from "lodash"
/**
* Class component for a single player
* Has grouping/ungrouping functionality on click and shows volume slider when grouped
*/
class PlayerComponent extends Component {
/**
* @param props.state {JSON} accesses the state of this player's Atom in playerVolumeAtomFamily
* @param props.setState modifies the state of this player's Atom in playerVolumeAtomFamily
* @param props.inGroup {boolean} True if player is in the currently displayed group, false otherwise. Obtained from groupsInfoAtom
* @param props.group {JSON} Contains current group's information
* @param props.playerId {string} This player's playerId
* @param props.museClientConfig {JSON} Contains Sonos API access token and configuration
*/
constructor(props) {
super(props);
this.volumeSlider = React.createRef();
// Allows this.handleGroupChange to be an onClick listener
this.handleGroupChange = this.handleGroupChange.bind(this);
// Used for Sonos API calls
this.ControlOptions = new HelperControls();
// Sets initial state of player
// getStartVolumeFlag = true ensures that current volume value is fetched on instantiation
this.props.setState({
getStartVolumeFlag: true,
volumeVal: this.props.state.volumeVal,
});
}
/**
* When this player is clicked, if this player is not in the current group, it is added to the current group
* If this player is in the current group, it is removed from the current group
*/
handleGroupChange() {
// Both arrays are required for the API call even if one array is empty
const data = {
// All players in playerIdsToAdd are added to the specified group
playerIdsToAdd:[],
// All players in playerIdsToRemove are removed from the specified group
playerIdsToRemove:[]
}
// If player is not in current group, player is added to current group. Otherwise, player is removed from current group
if(!this.props.inGroup) {
data.playerIdsToAdd = [this.props.playerId];
} else {
data.playerIdsToRemove = [this.props.playerId];
}
// Executes Sonos API call
this.ControlOptions.helperControls("groups/modifyGroupMembers", this.props.group.id, data);
}
/**
* Calls Sonos API to set player volume after volume slider value hasn't changed for 300ms
* Stops user from spamming Sonos API, which also reduces number of volume events received and helps prevent volume slider
* from attempting to update while user is still changing it
* @type {DebouncedFunc<function(*): void>}
*/
debouncedSetVolume = debounce(volume => SetVolume(volume, this.props.playerId, "PLAYER", this.props.museClientConfig), 300);
/**
* onChange handler for volume slider. Updates playerVolumeAtomFamily Atom's (and volume slider's) state and calls Sonos API to set player volume
*/
onSetVolume = () => {
const volume = this.volumeSlider.current.value;
this.props.setState({
getStartVolumeFlag: this.props.state.getStartVolumeFlag,
volumeVal: volume,
});
this.debouncedSetVolume(volume);
}
render() {
return (
<div className="player_component">
<div>
{/* On instantiation, gets current player volume from Sonos API. GetPlayerVolume finishes by setting getStartVolumeFlag to false */}
{this.props.state.getStartVolumeFlag && (
<GetPlayerVolume
playerId={this.props.playerId}
museClientConfig={this.props.museClientConfig}
/>
)}
</div>
<div className="playerVolumeSubscribe">
{/* When player is in current group, player's volume is subscribed to */}
{this.props.inGroup && (
<PlayerVolumeSubscribe
museClientConfig={this.props.museClientConfig}
playerId={this.props.playerId}
/>
)}
</div>
{/* Checkbox displays if player is in current group, and clicking the checkbox or text calls handleGroupChange */}
<div className="checkbox">
<label>
<input
type="checkbox"
checked={this.props.inGroup}
onChange={this.handleGroupChange}
/>
<span>{this.props.playerName}</span>
</label>
</div>
{/* Player volume slider shows if player is in current group. Slider value updates corresponding to playerVolumeAtomFamily Atom's state */}
{this.props.inGroup && (
<div className="player_slider_container">
<i className="fa fa-volume-down"></i>
<input
type="range"
min="0"
max="100"
value={this.props.state.volumeVal}
step="1"
ref={this.volumeSlider}
className="volumeSlider"
onChange={this.onSetVolume}
/>
<i className="fa fa-volume-up"></i>
</div>
)}
<br />
</div>
);
}
}
export default PlayerComponent;