summaryrefslogtreecommitdiff
path: root/animism-align/frontend/app/views/viewer/transcript/transcript.container.js
diff options
context:
space:
mode:
Diffstat (limited to 'animism-align/frontend/app/views/viewer/transcript/transcript.container.js')
-rw-r--r--animism-align/frontend/app/views/viewer/transcript/transcript.container.js88
1 files changed, 86 insertions, 2 deletions
diff --git a/animism-align/frontend/app/views/viewer/transcript/transcript.container.js b/animism-align/frontend/app/views/viewer/transcript/transcript.container.js
index 2dd8402..3cc23bd 100644
--- a/animism-align/frontend/app/views/viewer/transcript/transcript.container.js
+++ b/animism-align/frontend/app/views/viewer/transcript/transcript.container.js
@@ -5,24 +5,107 @@ import { connect } from 'react-redux'
import actions from 'app/actions'
+import { toArray, floatInRange } from 'app/utils'
+import oktween from 'app/utils/oktween'
import ParagraphList from 'app/views/paragraph/components/paragraph.list'
import { transcriptElementLookup } from './components'
class Transcript extends Component {
+ state = {
+ built: false,
+ paragraphs: [],
+ windowHeight: 0.0,
+ scrolling: false,
+ }
+
constructor(props){
super(props)
this.handleClose = this.handleClose.bind(this)
this.handleAnnotationClick = this.handleAnnotationClick.bind(this)
this.handleParagraphDoubleClick = this.handleParagraphDoubleClick.bind(this)
+ this.containerRef = React.createRef()
}
componentDidMount() {
actions.transcript.buildAllParagraphs()
+ this.setState({
+ built: true,
+ windowHeight: window.innerHeight * 0.6 - 48,
+ })
+ }
+
+ componentDidUpdate(prevProps, prevState) {
+ if (this.state.built !== prevState.built) {
+ setTimeout(() => {
+ this.cacheScrollPositions()
+ }, 1000)
+ }
+ if (!this.state.scrolling) {
+ this.updateScrollPosition(this.props.play_ts)
+ }
+ }
+
+ cacheScrollPositions() {
+ let paragraphs = toArray(this.containerRef.current.querySelectorAll('.content > div')).map(el => {
+ const isHeading = el.classList.contains('section_heading')
+ const isMedia = el.dataset.media === 'true'
+ const scrollTop = isHeading ? el.offsetTop : el.offsetTop - 16 // 1.5rem
+ const start_ts = parseFloat(el.dataset.startts)
+ let end_ts = parseFloat(el.dataset.endts)
+ if (isHeading) console.log(scrollTop, start_ts, end_ts)
+ if (!start_ts || !end_ts) return null
+ if (end_ts < start_ts) {
+ end_ts = start_ts + 0.5
+ }
+ return { start_ts, end_ts, scrollTop }
+ }).filter(el => !!el)
+ this.setState({ paragraphs })
+ }
+
+ updateScrollPosition(play_ts, forceScroll) {
+ const { paragraphs, windowHeight, currentParagraph } = this.state
+ const scrollTop = this.containerRef.current.scrollTop
+ if (!forceScroll && currentParagraph && floatInRange(currentParagraph.start_ts, play_ts, currentParagraph.end_ts)) return
+ let nextParagraph;
+ const insideParagraph = paragraphs.some(paragraph => {
+ if (floatInRange(paragraph.start_ts, play_ts, paragraph.end_ts)) {
+ nextParagraph = paragraph
+ return true
+ }
+ return false
+ })
+ if (insideParagraph && nextParagraph) {
+ console.log(nextParagraph.scrollTop)
+ if (!floatInRange(scrollTop, nextParagraph.scrollTop, scrollTop + windowHeight) || forceScroll) {
+ this.setState({ currentParagraph: nextParagraph, scrolling: true })
+ this.scrollToParagraph(scrollTop, nextParagraph.scrollTop)
+ } else {
+ this.setState({ currentParagraph: nextParagraph })
+ }
+ }
+ }
+
+ scrollToParagraph(scrollFrom, scrollTo) {
+ if (this.state.scrolling) return
+ console.log('scrolling!', scrollFrom, scrollTo)
+ oktween.add({
+ from: { scrollTop: scrollFrom },
+ to: { scrollTop: scrollTo },
+ duration: 1000,
+ easing: oktween.easing.quad_in_out,
+ update: obj => {
+ this.containerRef.current.scrollTo(0, obj.scrollTop)
+ },
+ finished: tween => {
+ this.containerRef.current.scrollTo(0, tween.obj.scrollTop)
+ this.setState({ scrolling: false })
+ }
+ })
}
handleAnnotationClick(e, paragraph, annotation) {
- // console.log(annotation)
actions.viewer.seekToTimestamp(paragraph.start_ts)
+ this.updateScrollPosition(paragraph.start_ts + 0.1, annotation.type === 'section_heading')
}
handleParagraphDoubleClick(e, paragraph) {
@@ -37,7 +120,7 @@ class Transcript extends Component {
const { viewer, paragraphs } = this.props
return (
<div className="transcript">
- <div className='content'>
+ <div className='content' ref={this.containerRef}>
<ParagraphList
paragraphs={paragraphs}
paragraphElementLookup={transcriptElementLookup}
@@ -59,6 +142,7 @@ class Transcript extends Component {
const mapStateToProps = state => ({
viewer: state.viewer,
+ play_ts: state.audio.play_ts,
paragraphs: state.paragraph.paragraphs,
})