Skip to content

Commit 9c1e4a6

Browse files
committed
fix: cpu leak in footer
1 parent f83348c commit 9c1e4a6

File tree

2 files changed

+76
-37
lines changed

2 files changed

+76
-37
lines changed

src/components/CurrentSong.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const CurrentSong = props => (
1515
<progress
1616
data-meta='duration'
1717
max={props.songDuration}
18-
value={props.durationVal}
18+
value={props.progressVal}
1919
/>
2020
<div data-meta='title'>{props.currentSong.title}</div>
2121
<div data-meta='artist'>{props.currentSong.artist}</div>
@@ -28,7 +28,7 @@ const CurrentSong = props => (
2828

2929
CurrentSong.propTypes = {
3030
currentSong: PropTypes.object,
31-
durationVal: PropTypes.number,
31+
progressVal: PropTypes.number,
3232
fastConnection: PropTypes.bool,
3333
listeners: PropTypes.number,
3434
mountOptions: PropTypes.node,

src/components/Footer.js

Lines changed: 74 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,81 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
3-
3+
import PageVisibility from 'react-page-visibility';
44
import CurrentSong from './CurrentSong';
55
import Slider from './Slider';
66
import PlayPauseButton from './PlayPauseButton';
77

8-
export default class Footer extends React.Component {
8+
export default class Footer extends React.PureComponent {
99
constructor(props) {
1010
super(props);
1111
this.state = {
12-
durationVal: 0,
12+
progressVal: 0,
1313
currentSong: {},
1414
progressInterval: null,
15-
alternativeMounts: null
15+
alternativeMounts: null,
16+
isTabVisible: true
1617
};
1718
this.updateProgress = this.updateProgress.bind(this);
1819
}
1920

20-
componentWillReceiveProps(nextProps) {
21+
componentDidUpdate(prevProps) {
2122
// if the song is new and we have all required props,
2223
// reset setInterval and currentSong
2324
if (
24-
this.state.currentSong.id !== nextProps.currentSong.id &&
25-
nextProps.songStartedAt
25+
this.state.currentSong.id !== prevProps.currentSong.id &&
26+
this.props.songStartedAt &&
27+
this.props.playing
2628
) {
2729
this.setState({
28-
currentSong: nextProps.currentSong,
29-
progressInterval: setInterval(this.updateProgress, 100),
30-
alternativeMounts: [].concat(nextProps.remotes, nextProps.mounts)
30+
currentSong: this.props.currentSong,
31+
alternativeMounts: [].concat(this.props.remotes, this.props.mounts)
3132
});
33+
this.toggleIntterval();
34+
} else if (prevProps.playing !== this.props.playing) {
35+
this.toggleIntterval();
3236
}
3337
}
3438

35-
updateProgress() {
39+
startInterval() {
40+
this.stopCurrenttInterval();
3641
this.setState({
37-
durationVal: (new Date().valueOf() - this.props.songStartedAt) / 1000
42+
progressInterval: setInterval(this.updateProgress, 100)
3843
});
3944
}
4045

46+
stopCurrenttInterval() {
47+
if (this.state.progressInterval) {
48+
clearInterval(this.state.progressInterval);
49+
}
50+
}
51+
52+
toggleIntterval() {
53+
if (this.props.playing && this.state.isTabVisible) this.startInterval();
54+
else this.stopCurrenttInterval();
55+
}
56+
57+
updateProgress() {
58+
let progressVal = parseInt(
59+
((new Date().valueOf() - this.props.songStartedAt) / 1000).toFixed(2),
60+
10
61+
);
62+
this.setState({ progressVal });
63+
}
64+
4165
handleChange(e) {
4266
let { value } = e.target;
4367
this.props.setUrl(value);
4468
}
4569

46-
render() {
47-
let { alternativeMounts } = this.state;
48-
let mountOptions = '';
70+
handleVisibilityChange = isTabVisible => {
71+
this.setState({ isTabVisible }, () => {
72+
this.toggleIntterval();
73+
});
74+
};
4975

76+
getMountOptions() {
77+
let mountOptions = '';
78+
let { alternativeMounts } = this.state;
5079
if (alternativeMounts && this.props.url) {
5180
mountOptions = (
5281
<select
@@ -62,29 +91,39 @@ export default class Footer extends React.Component {
6291
</select>
6392
);
6493
}
94+
return mountOptions;
95+
}
6596

66-
let durationVal = parseInt(this.state.durationVal.toFixed(2), 10);
97+
render() {
98+
let { progressVal, currentSong, fastConnection } = this.state;
99+
let {
100+
playing,
101+
songDuration,
102+
togglePlay,
103+
currentVolume,
104+
setTargetVolume,
105+
listeners
106+
} = this.props;
67107

68108
return (
69-
<footer>
70-
<CurrentSong
71-
currentSong={this.state.currentSong}
72-
durationVal={durationVal}
73-
fastConnection={this.props.fastConnection}
74-
listeners={this.props.listeners}
75-
mountOptions={mountOptions}
76-
playing={this.props.playing}
77-
songDuration={this.props.songDuration}
78-
/>
79-
<PlayPauseButton
80-
playing={this.props.playing}
81-
togglePlay={this.props.togglePlay}
82-
/>
83-
<Slider
84-
currentVolume={this.props.currentVolume}
85-
setTargetVolume={this.props.setTargetVolume}
86-
/>
87-
</footer>
109+
<PageVisibility onChange={this.handleVisibilityChange}>
110+
<footer>
111+
<CurrentSong
112+
currentSong={currentSong}
113+
progressVal={progressVal}
114+
fastConnection={fastConnection}
115+
listeners={listeners}
116+
mountOptions={this.getMountOptions()}
117+
playing={playing}
118+
songDuration={songDuration}
119+
/>
120+
<PlayPauseButton playing={playing} togglePlay={togglePlay} />
121+
<Slider
122+
currentVolume={currentVolume}
123+
setTargetVolume={setTargetVolume}
124+
/>
125+
</footer>
126+
</PageVisibility>
88127
);
89128
}
90129
}

0 commit comments

Comments
 (0)