summaryrefslogtreecommitdiffhomepage
path: root/app/components/Switch.js
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@codeispoetry.ru>2017-02-17 15:17:20 +0000
committerAndrej Mihajlov <and@codeispoetry.ru>2017-02-17 15:17:20 +0000
commit00b82cb3aa904b34d7000854bcecd3b72e012c8e (patch)
treeac314579a84d6c5b6fbbda8f0a0984f023364870 /app/components/Switch.js
parente88018b890c8ddf62895101439d57ca206d9379b (diff)
downloadmullvadvpn-00b82cb3aa904b34d7000854bcecd3b72e012c8e.tar.xz
mullvadvpn-00b82cb3aa904b34d7000854bcecd3b72e012c8e.zip
Add switch control and hook up settings reducer & actions
Diffstat (limited to 'app/components/Switch.js')
-rw-r--r--app/components/Switch.js107
1 files changed, 107 insertions, 0 deletions
diff --git a/app/components/Switch.js b/app/components/Switch.js
new file mode 100644
index 0000000000..16b64b2211
--- /dev/null
+++ b/app/components/Switch.js
@@ -0,0 +1,107 @@
+import React, { Component, PropTypes } from 'react';
+
+export default class Switch extends Component {
+
+ static propTypes = {
+ isOn: PropTypes.bool,
+ onChange: PropTypes.func
+ }
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ isTracking: false,
+ ignoreChange: false,
+ initialPos: null,
+ startTime: null,
+ target: null
+ };
+ }
+
+ handleMouseDown(e) {
+ const { pageX: x, pageY: y } = e;
+ this.setState({
+ isTracking: true,
+ initialPos: { x, y },
+ startTime: e.timeStamp
+ });
+ }
+
+ handleMouseMove(e) {
+ if(!this.state.isTracking) {
+ return;
+ }
+
+ const thresholdX = 10, thresholdY = 50;
+ const { x: x0, y: y0 } = this.state.initialPos;
+ const { pageX: x, pageY: y } = e;
+
+ const dx = Math.abs(x0 - x);
+ const dy = Math.abs(y0 - y);
+
+ if(dx < thresholdX || dy > thresholdY) {
+ return;
+ }
+
+ const isOn = !!this.props.isOn;
+ let nextOn = isOn;
+
+ if(x < x0 && isOn) {
+ nextOn = false;
+ } else if(x > x0 && !isOn) {
+ nextOn = true;
+ }
+
+ if(isOn !== nextOn) {
+ this.setState({ initialPos: { x, y } });
+ this.refs.input.checked = nextOn;
+ this.notify(nextOn);
+ this.setState({ ignoreChange: true });
+ }
+ }
+
+ handleMouseUp() {
+ if(this.state.isTracking) {
+ this.setState({ isTracking: false, initialPos: null });
+ console.log('mouseup');
+ }
+ }
+
+ handleChange(e) {
+ console.log('ONCHANGE ' + e.target.checked);
+ const delta = e.timeStamp - this.state.startTime;
+ const threshold = 1000;
+
+ if(this.state.ignoreChange) {
+ e.preventDefault();
+ this.setState({ ignoreChange: false });
+ } else if(delta > threshold) {
+ e.preventDefault();
+ } else {
+ this.notify(e.target.checked);
+ }
+ }
+
+ notify(isOn) {
+ if(this.props.onChange) {
+ this.props.onChange(isOn);
+ }
+ }
+
+ componentDidMount() {
+ document.addEventListener('mousemove', ::this.handleMouseMove);
+ document.addEventListener('mouseup', ::this.handleMouseUp);
+ }
+
+ componentWillUnmount() {
+ document.removeEventListener('mousemove', ::this.handleMouseMove);
+ document.removeEventListener('mouseup', ::this.handleMouseUp);
+ }
+
+ render() {
+ return (
+ <input type="checkbox" ref="input" className="switch" checked={ this.props.isOn }
+ onMouseDown={ ::this.handleMouseDown } onChange={ ::this.handleChange } />
+ );
+ }
+} \ No newline at end of file