import React, { Component } from 'react' // import { Link } from 'react-router-dom' import { connect } from 'react-redux' import actions from 'app/actions' import Annotations from 'app/views/editor/align/containers/annotations.container' import Waveform from 'app/views/editor/align/components/timeline/waveform.component' import Ticks from 'app/views/editor/align/components/timeline/ticks.component' import Cursor from 'app/views/editor/align/components/timeline/cursor.component' import PlayCursor from 'app/views/editor/align/components/timeline/playCursor.component' import CursorRegion from 'app/views/editor/align/components/timeline/cursorRegion.component' import { WAVEFORM_SIZE, ZOOM_STEPS, INNER_HEIGHT } from 'app/constants' import { clamp } from 'app/utils' import { positionToTime } from 'app/utils/align.utils' class Timeline extends Component { state = { dragging: false, a_ts: -1, } constructor(props){ super(props) this.handleKeydown = this.handleKeydown.bind(this) this.handleMouseMove = this.handleMouseMove.bind(this) this.handleWheel = this.handleWheel.bind(this) this.handleContainerClick = this.handleContainerClick.bind(this) this.handleTimelineMouseDown = this.handleTimelineMouseDown.bind(this) this.handleTimelineMouseUp = this.handleTimelineMouseUp.bind(this) } componentDidMount() { this.bind() } componentWillUnmount() { this.unbind() } shouldComponentUpdate(nextProps) { return ( nextProps.timeline !== this.props.timeline || nextProps.annotation !== this.props.annotation ) } bind() { document.addEventListener('keydown', this.handleKeydown) } unbind() { document.removeEventListener('keydown', this.handleKeydown) } handleKeydown(e) { if (document.activeElement !== document.body) { return } console.log(e.keyCode) if (e.metaKey && this.props.selectedAnnotation.id) { const { selectedAnnotation } = this.props switch (e.keyCode) { case 38: // up e.preventDefault() selectedAnnotation.start_ts = Math.max(selectedAnnotation.start_ts - (e.shiftKey ? 1 : 0.1), 0) actions.align.updateSelectedAnnotation(selectedAnnotation) actions.audio.seek(selectedAnnotation.start_ts) actions.align.setCursor(selectedAnnotation.start_ts) break case 40: // down e.preventDefault() selectedAnnotation.start_ts += e.shiftKey ? 1 : 0.1 actions.align.updateSelectedAnnotation(selectedAnnotation) actions.audio.seek(selectedAnnotation.start_ts) actions.align.setCursor(selectedAnnotation.start_ts) break case 68: // D e.preventDefault() actions.align.cloneSelectedAnnotation(selectedAnnotation) } return } if (e.shiftKey) { switch (e.keyCode) { case 187: // plus actions.align.setZoom(this.props.timeline.zoom - 1) break case 189: // minus actions.align.setZoom(this.props.timeline.zoom + 1) break } } else { // console.log(e.keyCode) switch (e.keyCode) { case 27: // escape actions.align.hideAnnotationForm() break case 65: // A - add e.preventDefault() actions.align.showNewAnnotationForm(this.props.audio.play_ts, this.props.text) break case 32: // spacebar actions.audio.toggle() break case 38: // up actions.audio.jump(- ZOOM_STEPS[this.props.timeline.zoom] * 0.1) break case 40: // down actions.audio.jump(ZOOM_STEPS[this.props.timeline.zoom] * 0.1) break } } } handleWheel(e) { let { start_ts, zoom, duration } = this.props.timeline let { deltaY } = e let secondsPerPixel = ZOOM_STEPS[zoom] * 0.1 // 0.1 sec / step let widthTimeDuration = INNER_HEIGHT * secondsPerPixel // secs per pixel start_ts += Math.round((deltaY) * ZOOM_STEPS[zoom]) start_ts = clamp(start_ts, 0, Math.max(0, duration - widthTimeDuration / 2)) if (e.shiftKey) { if (Math.abs(deltaY) < 2) return if (e.deltaY > 0) { actions.align.throttledSetZoom(this.props.timeline.zoom + 1) } else { actions.align.throttledSetZoom(this.props.timeline.zoom - 1) } } else if (e.altKey) { actions.audio.jump(e.deltaY * ZOOM_STEPS[zoom]) } else { actions.align.setScrollPosition(start_ts) } } handleContainerClick(e) { actions.align.clearSelectedAnnotation() actions.align.clearSelectedParagraph() } handleTimelineMouseDown(e) { const cursor_ts = positionToTime(e.pageY, this.props.timeline) actions.align.clearCursorRegion() actions.align.setCursor(cursor_ts) this.setState({ dragging: true, a_ts: cursor_ts, }) } handleMouseMove(e) { const cursor_ts = positionToTime(e.pageY, this.props.timeline) if (this.state.dragging) { actions.align.setCursorRegion( Math.min(this.state.a_ts, cursor_ts), Math.max(this.state.a_ts, cursor_ts), ) } else { actions.align.setCursor(cursor_ts) } } handleTimelineMouseUp(e) { this.setState({ dragging: false }) const play_ts = positionToTime(e.pageY, this.props.timeline) if (e.metaKey) { actions.align.spliceTime(play_ts) } else if (e.pageX < WAVEFORM_SIZE * 0.67) { actions.audio.seek(play_ts) } else { actions.align.showNewAnnotationForm(play_ts, this.props.text) } } render() { return (