From 451567e8673f56253b97a6cc89cfd0cc7422818a Mon Sep 17 00:00:00 2001 From: Steve Jost Date: Sun, 26 Apr 2015 01:35:18 -0700 Subject: [PATCH 1/2] Added 1/2/3 beeps similar to The Squire. --- .gitignore | 3 ++ README.md | 2 +- react-components/button-snitch.js | 90 +++++++++++++++++++++++++++++++ react-components/settings.js | 76 ++++++++++++++++++++++++++ 4 files changed, 170 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 98d45fd..f56cd4e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,9 @@ Icon # Thumbnails ._* +# Webstorm Directories +.idea + # Files that might appear in the root of a volume .DocumentRevisions-V100 .fseventsd diff --git a/README.md b/README.md index 144cc4f..823074f 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ 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 - [ ] 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 diff --git a/react-components/button-snitch.js b/react-components/button-snitch.js index 9981889..05b2ccd 100644 --- a/react-components/button-snitch.js +++ b/react-components/button-snitch.js @@ -213,6 +213,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, @@ -254,6 +263,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, @@ -322,6 +340,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) { @@ -387,6 +417,28 @@ 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); + } + }, + 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; + } + }, updateChartSelection: function (chart) { this.setState({chartSelected: chart}); }, @@ -421,6 +473,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}); @@ -565,6 +638,8 @@ var ButtonSnitch = React.createClass({ self.sendNecessaryNotifications(tick.seconds_left); + self.sendBeeps(tick.seconds_left); + currentParticipants = parseInt( tick.participants_text.replace(/,/g, ""), 10 @@ -669,7 +744,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} + updateBeep={this.updateBeep} + updateBeepOnce={this.updateBeepOnce} + updateBeepTwice={this.updateBeepTwice} + updateBeepThrice={this.updateBeepThrice} discardAfter={this.state.discardAfter} updateDiscardAfter={this.updateDiscardAfter} nightMode={this.state.nightMode} diff --git a/react-components/settings.js b/react-components/settings.js index 8c23c77..4d694b6 100644 --- a/react-components/settings.js +++ b/react-components/settings.js @@ -30,6 +30,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( @@ -119,6 +128,73 @@ var Settings = React.createClass({ Play a beep for new clicks +
+ + + + + +
+
+ + + + + + +
+
+ + + + + +
From fb265a34d017ac0bf4b0a1acadb5e96f43a656e2 Mon Sep 17 00:00:00 2001 From: Steve Jost Date: Sun, 26 Apr 2015 02:27:47 -0700 Subject: [PATCH 2/2] Added localStorage support for settings. --- README.md | 3 ++- react-components/button-snitch.js | 41 +++++++++++++++++++++++++++++-- react-components/settings.js | 4 +++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 823074f..5c9315e 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Monitor [Reddit](//www.reddit.com/)'s [/r/thebutton](//www.reddit.com/r/thebutto - [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)) - [ ] Scroll to zoom, or at least support clamping to start/end times selectable in options bar @@ -36,4 +37,4 @@ Monitor [Reddit](//www.reddit.com/)'s [/r/thebutton](//www.reddit.com/r/thebutto - [ ] 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 + diff --git a/react-components/button-snitch.js b/react-components/button-snitch.js index 05b2ccd..dfae845 100644 --- a/react-components/button-snitch.js +++ b/react-components/button-snitch.js @@ -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) { @@ -425,6 +433,28 @@ var ButtonSnitch = React.createClass({ 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); @@ -439,6 +469,10 @@ var ButtonSnitch = React.createClass({ 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}); }, @@ -697,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); @@ -755,7 +792,7 @@ var ButtonSnitch = React.createClass({ beepThrice={this.state.beepThrice} beepThriceTime={this.state.beepThriceTime} beepThriceMuted={this.state.beepThriceMuted} - + saveLocalSettings={this.saveLocalSettings} updateBeep={this.updateBeep} updateBeepOnce={this.updateBeepOnce} updateBeepTwice={this.updateBeepTwice} diff --git a/react-components/settings.js b/react-components/settings.js index 4d694b6..d3f00dc 100644 --- a/react-components/settings.js +++ b/react-components/settings.js @@ -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()