Spaces:
Runtime error
Runtime error
| import React from 'react'; | |
| import PropTypes from 'prop-types'; | |
| import bindAll from 'lodash.bindall'; | |
| import AudioSelectorComponent from '../components/audio-trimmer/audio-selector.jsx'; | |
| import { getEventXY } from '../lib/touch-utils'; | |
| import DragRecognizer from '../lib/drag-recognizer'; | |
| const MIN_LENGTH = 0.01; | |
| const MIN_DURATION = 500; | |
| class AudioSelector extends React.Component { | |
| constructor(props) { | |
| super(props); | |
| bindAll(this, [ | |
| 'handleNewSelectionMouseDown', | |
| 'handleTrimStartMouseDown', | |
| 'handleTrimEndMouseDown', | |
| 'handleTrimStartMouseMove', | |
| 'handleTrimEndMouseMove', | |
| 'handleTrimStartMouseUp', | |
| 'handleTrimEndMouseUp', | |
| 'storeRef' | |
| ]); | |
| this.state = { | |
| trimStart: props.trimStart, | |
| trimEnd: props.trimEnd | |
| }; | |
| this.clickStartTime = 0; | |
| this.trimStartDragRecognizer = new DragRecognizer({ | |
| onDrag: this.handleTrimStartMouseMove, | |
| onDragEnd: this.handleTrimStartMouseUp, | |
| touchDragAngle: 90, | |
| distanceThreshold: 0 | |
| }); | |
| this.trimEndDragRecognizer = new DragRecognizer({ | |
| onDrag: this.handleTrimEndMouseMove, | |
| onDragEnd: this.handleTrimEndMouseUp, | |
| touchDragAngle: 90, | |
| distanceThreshold: 0 | |
| }); | |
| } | |
| componentWillReceiveProps(newProps) { | |
| const { trimStart, trimEnd } = this.props; | |
| if (newProps.trimStart === trimStart && newProps.trimEnd === trimEnd) return; | |
| this.setState({ | |
| trimStart: newProps.trimStart, | |
| trimEnd: newProps.trimEnd | |
| }); | |
| } | |
| clearSelection() { | |
| this.props.onSetTrim(null, null); | |
| } | |
| handleNewSelectionMouseDown(e) { | |
| const { width, left } = this.containerElement.getBoundingClientRect(); | |
| this.initialTrimEnd = (getEventXY(e).x - left) / width; | |
| this.initialTrimStart = this.initialTrimEnd; | |
| this.props.onSetTrim(this.initialTrimStart, this.initialTrimEnd); | |
| this.clickStartTime = Date.now(); | |
| this.containerSize = width; | |
| this.trimEndDragRecognizer.start(e); | |
| e.preventDefault(); | |
| } | |
| handleTrimStartMouseMove(currentOffset, initialOffset) { | |
| const dx = (currentOffset.x - initialOffset.x) / this.containerSize; | |
| const newTrim = Math.max(0, Math.min(1, this.initialTrimStart + dx)); | |
| if (newTrim > this.initialTrimEnd) { | |
| this.setState({ | |
| trimStart: this.initialTrimEnd, | |
| trimEnd: newTrim | |
| }); | |
| } else { | |
| this.setState({ | |
| trimStart: newTrim, | |
| trimEnd: this.initialTrimEnd | |
| }); | |
| } | |
| } | |
| handleTrimEndMouseMove(currentOffset, initialOffset) { | |
| const dx = (currentOffset.x - initialOffset.x) / this.containerSize; | |
| const newTrim = Math.min(1, Math.max(0, this.initialTrimEnd + dx)); | |
| if (newTrim < this.initialTrimStart) { | |
| this.setState({ | |
| trimStart: newTrim, | |
| trimEnd: this.initialTrimStart | |
| }); | |
| } else { | |
| this.setState({ | |
| trimStart: this.initialTrimStart, | |
| trimEnd: newTrim | |
| }); | |
| } | |
| } | |
| handleTrimStartMouseUp() { | |
| this.props.onSetTrim(this.state.trimStart, this.state.trimEnd); | |
| } | |
| handleTrimEndMouseUp() { | |
| // If the selection was made quickly (tooFast) and is small (tooShort), | |
| // deselect instead. This allows click-to-deselect even if you drag | |
| // a little bit by accident. It also allows very quickly making a | |
| // selection, as long as it is above a minimum length. | |
| const tooFast = (Date.now() - this.clickStartTime) < MIN_DURATION; | |
| const tooShort = (this.state.trimEnd - this.state.trimStart) < MIN_LENGTH; | |
| if (tooFast && tooShort) { | |
| this.clearSelection(); | |
| } else { | |
| this.props.onSetTrim(this.state.trimStart, this.state.trimEnd); | |
| } | |
| } | |
| handleTrimStartMouseDown(e) { | |
| this.containerSize = this.containerElement.getBoundingClientRect().width; | |
| this.trimStartDragRecognizer.start(e); | |
| this.initialTrimStart = this.props.trimStart; | |
| this.initialTrimEnd = this.props.trimEnd; | |
| e.stopPropagation(); | |
| e.preventDefault(); | |
| } | |
| handleTrimEndMouseDown(e) { | |
| this.containerSize = this.containerElement.getBoundingClientRect().width; | |
| this.trimEndDragRecognizer.start(e); | |
| this.initialTrimEnd = this.props.trimEnd; | |
| this.initialTrimStart = this.props.trimStart; | |
| e.stopPropagation(); | |
| e.preventDefault(); | |
| } | |
| storeRef(el) { | |
| this.containerElement = el; | |
| } | |
| render() { | |
| return ( | |
| <AudioSelectorComponent | |
| containerRef={this.storeRef} | |
| playhead={this.props.playhead} | |
| trimEnd={this.state.trimEnd} | |
| trimStart={this.state.trimStart} | |
| onNewSelectionMouseDown={this.handleNewSelectionMouseDown} | |
| onTrimEndMouseDown={this.handleTrimEndMouseDown} | |
| onTrimStartMouseDown={this.handleTrimStartMouseDown} | |
| /> | |
| ); | |
| } | |
| } | |
| AudioSelector.propTypes = { | |
| onSetTrim: PropTypes.func, | |
| playhead: PropTypes.number, | |
| trimEnd: PropTypes.number, | |
| trimStart: PropTypes.number | |
| }; | |
| export default AudioSelector; | |