diff options
| author | Andrej Mihajlov <and@codeispoetry.ru> | 2017-02-17 15:17:20 +0000 |
|---|---|---|
| committer | Andrej Mihajlov <and@codeispoetry.ru> | 2017-02-17 15:17:20 +0000 |
| commit | 00b82cb3aa904b34d7000854bcecd3b72e012c8e (patch) | |
| tree | ac314579a84d6c5b6fbbda8f0a0984f023364870 /app/components/Switch.js | |
| parent | e88018b890c8ddf62895101439d57ca206d9379b (diff) | |
| download | mullvadvpn-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.js | 107 |
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 |
