Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ Icon
# Thumbnails
._*

# Webstorm Directories
.idea

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ Monitor [Reddit](//www.reddit.com/)'s [/r/thebutton](//www.reddit.com/r/thebutto
- [x] Import historical data on first load
- [x] Replay functionality (started as [a pull request from jmlsteele](//github.com/treyp/thebutton/pull/5))
- [x] Show time zone on time axes
- [x] Beep support like Squire
- [X] Cookie to save settings [ implemented as localStorage ]
- [ ] Dual chart display (request from [/u/argash](//www.reddit.com/user/argash))
- [ ] Breakdown of percentage of time spent in each color (request from [/u/carpevirginem](//www.reddit.com/user/carpevirginem))
- [ ] Beep support like Squire
- [ ] Scroll to zoom, or at least support clamping to start/end times selectable in options bar
- [ ] Horizontal option for log chart
- [ ] Export graph to an image
- [ ] Make header responsive
- [ ] Replace pulse dot with a clearer "live" text that fades out after 1 second (with a 1 second fade)
- [ ] Auto dot size and bar height option: starts large, shrinks down based on window size, minimum of 1
- [ ] Add pause button
- [ ] Cookie to save settings

129 changes: 128 additions & 1 deletion react-components/button-snitch.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
var ButtonSnitch = React.createClass({
getInitialState: function () {
return this.getInitialStateReal();
// Alter this to get the local storage settings and merge them into the state.
var initialState = this.getInitialStateReal();
var savedSettings = this.loadLocalSettings();

for(var s in savedSettings) {
initialState[s] = savedSettings[s];
}

return initialState;
// return this.getInitialStateFake(5e3);
},
parseJson: function (serializedJson) {
Expand Down Expand Up @@ -213,6 +221,15 @@ var ButtonSnitch = React.createClass({
notifiedForCurrentClick: false,
lastTimeTrackedForCurrentClick: 60,
beep: false,
beepOnce: false,
beepOnceTime: 50,
beepOnceMuted: false,
beepTwice: false,
beepTwiceTime: 40,
beepTwiceMuted: false,
beepThrice: false,
beepThriceTime: 30,
beepThriceMuted: false,
discardAfter: false,
nightMode: false,
displayImportNotice: false,
Expand Down Expand Up @@ -254,6 +271,15 @@ var ButtonSnitch = React.createClass({
notifiedForCurrentClick: false,
lastTimeTrackedForCurrentClick: 60,
beep: false,
beepOnce: false,
beepOnceTime: 50,
beepOnceMuted: false,
beepTwice: false,
beepTwiceTime: 40,
beepTwiceMuted: false,
beepThrice: false,
beepThriceTime: 30,
beepThriceMuted: false,
discardAfter: false,
nightMode: false,
displayImportNotice: false,
Expand Down Expand Up @@ -322,6 +348,18 @@ var ButtonSnitch = React.createClass({
if (this.state.beep) {
React.findDOMNode(this.refs.audio).play();
}

/* Reset beeps when clicked */
if(this.state.beepOnce && this.state.beepOnceMuted) {
this.state.beepOnceMuted = false;
}
if(this.state.beepTwice && this.state.beepTwiceMuted) {
this.state.beepTwiceMuted = false;
}
if(this.state.beepThrice && this.state.beepThriceMuted) {
this.state.beepThriceMuted = false;
}

},
flairClass: function (seconds) {
if (seconds > 51) {
Expand Down Expand Up @@ -387,6 +425,54 @@ var ButtonSnitch = React.createClass({
midRangeBottom = (histogramIndex + 1);
return (midRangeTop + midRangeBottom) / 2;
},
playBeep: function() {
React.findDOMNode(this.refs.audio).play();
},
playNumBeeps: function(number) {
for (var i = 0; i < number; i++) {
window.setTimeout(this.playBeep, 500 * i);
}
},
loadLocalSettings: function() {
// Load settings out of local storage
var snitchSettings = localStorage.getItem('button-snitch-settings');
return JSON.parse(snitchSettings);
},
saveLocalSettings: function() {
// Build a list of settings we want to save.
var snitchSettings = {
alertTime: this.state.alertTime,
beep: this.state.beep,
beepOnce: this.state.beepOnce,
beepOnceTime: this.state.beepOnceTime,
beepTwice: this.state.beepTwice,
beepTwiceTime: this.state.beepTwiceTime,
beepThrice: this.state.beepThrice,
beepThriceTime: this.state.beepThriceTime,
nightMode: this.state.nightMode
};

// Persist settings to local storage
localStorage.setItem('button-snitch-settings', JSON.stringify(snitchSettings));
},
sendBeeps: function(seconds) {
if (this.state.beepOnce && seconds <= this.state.beepOnceTime && !this.state.beepOnceMuted) {
this.playNumBeeps(1);
this.state.beepOnceMuted = true;
}
if (this.state.beepTwice && seconds <= this.state.beepTwiceTime && !this.state.beepTwiceMuted) {
this.playNumBeeps(2);
this.state.beepTwiceMuted = true;
}
if (this.state.beepThrice && seconds <= this.state.beepThriceTime && !this.state.beepThriceMuted) {
this.playNumBeeps(3);
this.state.beepThriceMuted = true;
}
},
setupInitialSettingsLeftovers : function() {
// call the things that need to be done after the initial state load
this.updateNightMode(this.state.nightMode);
},
updateChartSelection: function (chart) {
this.setState({chartSelected: chart});
},
Expand Down Expand Up @@ -421,6 +507,27 @@ var ButtonSnitch = React.createClass({
updateBeep: function (beep) {
this.setState({beep: beep});
},
updateBeepOnce: function(beepOnce, beepOnceTime) {
this.setState({
beepOnce: beepOnce,
beepOnceTime: beepOnceTime,
beepOnceMuted: false
});
},
updateBeepTwice: function(beepTwice, beepTwiceTime) {
this.setState({
beepTwice: beepTwice,
beepTwiceTime: beepTwiceTime,
beepTwiceMuted: false
});
},
updateBeepThrice: function(beepThrice, beepThriceTime) {
this.setState({
beepThrice: beepThrice,
beepThriceTime: beepThriceTime,
beepThriceMuted: false
});
},
updateDiscardAfter: function (clicks) {
clicks = parseInt(clicks, 10) || false;
this.setState({discardAfter: clicks});
Expand Down Expand Up @@ -565,6 +672,8 @@ var ButtonSnitch = React.createClass({

self.sendNecessaryNotifications(tick.seconds_left);

self.sendBeeps(tick.seconds_left);

currentParticipants = parseInt(
tick.participants_text.replace(/,/g, ""),
10
Expand Down Expand Up @@ -622,6 +731,9 @@ var ButtonSnitch = React.createClass({
this.findWebSocketFromReddit();

this.downloadClickHistory();

// Finish the load from local storage by calling the extras.
this.setupInitialSettingsLeftovers();
},
componentWillUnmount: function () {
clearInterval(this.interval);
Expand Down Expand Up @@ -669,7 +781,22 @@ var ButtonSnitch = React.createClass({
alertTime={this.state.alertTime}
updateAlertTime={this.updateAlertTime}
beep={this.state.beep}
beepOnce={this.state.beepOnce}
beepOnceTime={this.state.beepOnceTime}
beepOnceMuted={this.state.beepOnceMuted}

beepTwice={this.state.beepTwice}
beepTwiceTime={this.state.beepTwiceTime}
beepTwiceMuted={this.state.beepTwiceMuted}

beepThrice={this.state.beepThrice}
beepThriceTime={this.state.beepThriceTime}
beepThriceMuted={this.state.beepThriceMuted}
saveLocalSettings={this.saveLocalSettings}
updateBeep={this.updateBeep}
updateBeepOnce={this.updateBeepOnce}
updateBeepTwice={this.updateBeepTwice}
updateBeepThrice={this.updateBeepThrice}
discardAfter={this.state.discardAfter}
updateDiscardAfter={this.updateDiscardAfter}
nightMode={this.state.nightMode}
Expand Down
80 changes: 80 additions & 0 deletions react-components/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ var Settings = React.createClass({
this.setState({discardAfter: newProps.discardAfter});
}
},
componentDidUpdate: function(prevOps, prevState){
// After we update the settings, persist them to local storage.
this.props.saveLocalSettings();
},
updateAlertTime: function () {
this.props.updateAlertTime(
React.findDOMNode(this.refs.time).value.trim()
Expand All @@ -30,6 +34,15 @@ var Settings = React.createClass({
updateBeep: function () {
this.props.updateBeep(React.findDOMNode(this.refs.beep).checked);
},
updateBeepOnce: function() {
this.props.updateBeepOnce(React.findDOMNode(this.refs.beepOnce).checked, React.findDOMNode(this.refs.beepOnceTime).value);
},
updateBeepTwice: function() {
this.props.updateBeepTwice(React.findDOMNode(this.refs.beepTwice).checked, React.findDOMNode(this.refs.beepTwiceTime).value);
},
updateBeepThrice: function() {
this.props.updateBeepThrice(React.findDOMNode(this.refs.beepThrice).checked, React.findDOMNode(this.refs.beepThriceTime).value);
},
submitDiscard: function (e) {
e.preventDefault();
this.props.updateDiscardAfter(
Expand Down Expand Up @@ -119,6 +132,73 @@ var Settings = React.createClass({
Play a beep for new clicks
</label>
</div>
<div className="row">
<input
type="checkbox"
defaultChecked={this.props.beepOnce}
id="alert-beep-once"
ref="beepOnce"
onChange={this.updateBeepOnce} />
<label htmlFor="alert-beep-once">
Play 1 beeps &lt; &nbsp;
</label>
<input
type="number"
min="0"
max="60"
value={this.props.beepOnceTime}
id="alert-beep-once-time"
ref="beepOnceTime"
onChange={this.updateBeepOnce}
/>
<label>seconds</label>

</div>
<div className="row">

<input
type="checkbox"
defaultChecked={this.props.beepTwice}
id="alert-beep-twice"
ref="beepTwice"
onChange={this.updateBeepTwice} />
<label htmlFor="alert-beep-twice">
Play 2 beeps &lt; &nbsp;
</label>

<input
type="number"
min="0"
max="60"
value={this.props.beepTwiceTime}
id="alert-beep-Twice-time"
ref="beepTwiceTime"
onChange={this.updateBeepTwice}
/>
<label>seconds</label>
</div>
<div className="row">
<input
type="checkbox"
defaultChecked={this.props.beepThrice}
id="alert-beep-thrice"
ref="beepThrice"
onChange={this.updateBeepThrice} />
<label htmlFor="alert-beep-thrice">
Play 3 beeps &lt; &nbsp;
</label>
<input
type="number"
min="0"
max="60"
value={this.props.beepThriceTime}
id="alert-beep-Thrice-time"
ref="beepThriceTime"
onChange={this.updateBeepThrice}
/>
<label>seconds</label>

</div>
</div>
<div className="setting">
<div className="row">
Expand Down