summaryrefslogtreecommitdiff
path: root/animism-align/frontend/views/align/containers/timeline.container.js
diff options
context:
space:
mode:
Diffstat (limited to 'animism-align/frontend/views/align/containers/timeline.container.js')
-rw-r--r--animism-align/frontend/views/align/containers/timeline.container.js129
1 files changed, 129 insertions, 0 deletions
diff --git a/animism-align/frontend/views/align/containers/timeline.container.js b/animism-align/frontend/views/align/containers/timeline.container.js
new file mode 100644
index 0000000..3795751
--- /dev/null
+++ b/animism-align/frontend/views/align/containers/timeline.container.js
@@ -0,0 +1,129 @@
+import React, { Component } from 'react'
+// import { Link } from 'react-router-dom'
+import { bindActionCreators } from 'redux'
+import { connect } from 'react-redux'
+
+import actions from '../../../actions'
+// import * as alignActions from '../align.actions'
+
+import Annotations from '../containers/annotations.container'
+import Waveform from '../components/timeline/waveform.component'
+import Ticks from '../components/timeline/ticks.component'
+import Cursor from '../components/timeline/cursor.component'
+import PlayButton from '../components/timeline/playButton.component'
+import PlayCursor from '../components/timeline/playCursor.component'
+
+import { WAVEFORM_SIZE, ZOOM_STEPS } from '../constants'
+import { clamp } from '../../../util'
+import { positionToTime } from '../align.util'
+
+class Timeline extends Component {
+ constructor(props){
+ super(props)
+ this.handleKeydown = this.handleKeydown.bind(this)
+ this.handleMouseMove = this.handleMouseMove.bind(this)
+ this.handleWheel = this.handleWheel.bind(this)
+ this.handleClick = this.handleClick.bind(this)
+ }
+ componentDidMount() {
+ this.bind()
+ }
+ componentWillUnmount() {
+ this.unbind()
+ }
+ bind() {
+ document.addEventListener('keydown', this.handleKeydown)
+ }
+ unbind() {
+ document.removeEventListener('keydown', this.handleKeydown)
+ }
+ handleKeydown(e) {
+ if (document.activeElement !== document.body) {
+ 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 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 secondsPerPixel = ZOOM_STEPS[zoom] * 0.1 // 0.1 sec / step
+ let widthTimeDuration = window.innerHeight * secondsPerPixel // secs per pixel
+
+ start_ts = clamp(start_ts + e.deltaY * ZOOM_STEPS[zoom], 0, Math.max(0, duration - widthTimeDuration / 2))
+ if (e.shiftKey) {
+ if (Math.abs(e.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)
+ }
+ }
+ handleMouseMove(e) {
+ const cursor_ts = positionToTime(e.pageY, this.props.timeline)
+ actions.align.setCursor(cursor_ts)
+ }
+ handleClick(e) {
+ const play_ts = positionToTime(e.pageY, this.props.timeline)
+ if (e.pageX > WAVEFORM_SIZE * 0.67) {
+ actions.align.showNewTimestampForm(play_ts, this.props.text)
+ } else {
+ actions.audio.seek(play_ts)
+ }
+ }
+ render() {
+ return (
+ <div
+ className='timeline'
+ onWheel={this.handleWheel}
+ onMouseMove={this.handleMouseMove}
+ >
+ <div className='timelineColumn'>
+ <Waveform onClick={this.handleClick} />
+ <Ticks timeline={this.props.timeline} />
+ <Cursor timeline={this.props.timeline} annotation={this.props.annotation} />
+ </div>
+ <Annotations timeline={this.props.timeline} />
+ <PlayCursor />
+ <PlayButton />
+ </div>
+ )
+ }
+}
+
+const mapStateToProps = state => ({
+ timeline: state.align.timeline,
+ annotation: state.align.annotation,
+ text: state.site.text,
+})
+
+const mapDispatchToProps = dispatch => ({
+ // alignActions: bindActionCreators({ ...alignActions }, dispatch),
+})
+
+export default connect(mapStateToProps, mapDispatchToProps)(Timeline)