diff options
Diffstat (limited to 'animism-align/frontend/app/views/viewer')
6 files changed, 100 insertions, 3 deletions
diff --git a/animism-align/frontend/app/views/viewer/player/components.media/media.vitrine.js b/animism-align/frontend/app/views/viewer/player/components.media/media.vitrine.js index 2033465..4fc3964 100644 --- a/animism-align/frontend/app/views/viewer/player/components.media/media.vitrine.js +++ b/animism-align/frontend/app/views/viewer/player/components.media/media.vitrine.js @@ -6,7 +6,7 @@ import actions from 'app/actions' export const Vitrine = ({ media }) => { const { image_order, image_lookup, thumbnail_lookup } = media.settings - const width = (Math.floor(100 / image_order.length * 2) - 2) + 'vw' + const width = (Math.floor(100 / image_order.length * 2) - 2) + '%' // console.log(width) return ( <div className='vitrine-items'> diff --git a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.gallery.js b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.gallery.js index 6d6db2d..d21cc79 100644 --- a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.gallery.js +++ b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.gallery.js @@ -14,6 +14,9 @@ export const MediaGallery = ({ paragraph, media, currentParagraph, currentAnnota return ( <div className={className} + data-startts={paragraph.start_ts} + data-endts={paragraph.end_ts} + data-media={true} onClick={e => onAnnotationClick(e, paragraph, annotation)} > {"["} diff --git a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.image.js b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.image.js index 64de3a2..6eef6a0 100644 --- a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.image.js +++ b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.image.js @@ -39,6 +39,9 @@ export const MediaImage = ({ paragraph, media, currentParagraph, currentAnnotati return ( <div className={className} + data-startts={paragraph.start_ts} + data-endts={paragraph.end_ts} + data-media={true} onClick={e => onAnnotationClick(e, paragraph, annotation)} > {"["} diff --git a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.text.js b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.text.js index 292eec8..5ea12da 100644 --- a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.text.js +++ b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.text.js @@ -9,6 +9,8 @@ export const Paragraph = ({ paragraph, currentParagraph, currentAnnotation, onAn return ( <div className={className} + data-startts={paragraph.start_ts} + data-endts={paragraph.end_ts} > {paragraph.annotations.map(annotation => ( <span @@ -29,6 +31,8 @@ export const ParagraphHeading = ({ paragraph, currentParagraph, currentAnnotatio return ( <div className={className} + data-startts={paragraph.start_ts} + data-endts={paragraph.end_ts} onClick={e => onAnnotationClick(e, paragraph, firstAnnotation)} > <span>{ROMAN_NUMERALS[paragraph.sectionIndex]}{'. '}{text}</span> diff --git a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.video.js b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.video.js index 423a055..1c1b3cc 100644 --- a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.video.js +++ b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.video.js @@ -14,6 +14,9 @@ export const MediaVideo = ({ paragraph, media, currentParagraph, currentAnnotati return ( <div className={className} + data-startts={paragraph.start_ts} + data-endts={paragraph.end_ts} + data-media={true} onClick={e => onAnnotationClick(e, paragraph, annotation)} > {"["} 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, }) |
