summaryrefslogtreecommitdiff
path: root/animism-align
diff options
context:
space:
mode:
Diffstat (limited to 'animism-align')
-rw-r--r--animism-align/frontend/app/utils/transcript.utils.js22
-rw-r--r--animism-align/frontend/app/utils/viewer.utils.js1
-rw-r--r--animism-align/frontend/app/views/viewer/nav/nav.parent.js2
-rw-r--r--animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.video.js8
-rw-r--r--animism-align/frontend/app/views/viewer/player/components.inline/inline.text.js5
-rw-r--r--animism-align/frontend/app/views/viewer/player/components.inline/inline.video.js1
-rw-r--r--animism-align/frontend/app/views/viewer/player/components.media/video.scrubber.js3
-rw-r--r--animism-align/frontend/app/views/viewer/player/components.media/video.subtitles.js24
-rw-r--r--animism-align/frontend/app/views/viewer/player/player.transcript.css8
-rw-r--r--animism-align/frontend/app/views/viewer/transcript/components/elementTypes.video.js76
-rw-r--r--animism-align/frontend/app/views/viewer/transcript/transcript.css1
-rw-r--r--animism-align/frontend/app/views/viewer/viewer.actions.js2
12 files changed, 124 insertions, 29 deletions
diff --git a/animism-align/frontend/app/utils/transcript.utils.js b/animism-align/frontend/app/utils/transcript.utils.js
index 258afa1..115eace 100644
--- a/animism-align/frontend/app/utils/transcript.utils.js
+++ b/animism-align/frontend/app/utils/transcript.utils.js
@@ -150,3 +150,25 @@ const getParagraphType = (annotation, paragraph) => {
}
return paragraph.type
}
+
+const REGEXP_ALL_COMMAS = new RegExp(',', 'g')
+
+export const parseSubtitles = (mediaItem, timeOffset) => {
+ if (!mediaItem || !mediaItem.settings.subtitles) return
+ const groups = mediaItem.settings.subtitles.split("\n\n")
+ const subtitles = groups.map((group) => {
+ if (!group) return
+ const lines = group.trim().split("\n")
+ if (!lines.length || !parseInt(lines[0])) {
+ return null
+ }
+ let ts_parts = lines[1].replace(REGEXP_ALL_COMMAS, '.').split(" --> ").map(timestampToSeconds)
+ return {
+ id: parseInt(lines[0]),
+ start_ts: ts_parts[0] + timeOffset,
+ end_ts: ts_parts[1] + timeOffset,
+ lines: lines.slice(2),
+ }
+ }).filter(a => !!a)
+ return subtitles
+}
diff --git a/animism-align/frontend/app/utils/viewer.utils.js b/animism-align/frontend/app/utils/viewer.utils.js
index 9cf8e8f..efb50d6 100644
--- a/animism-align/frontend/app/utils/viewer.utils.js
+++ b/animism-align/frontend/app/utils/viewer.utils.js
@@ -39,4 +39,3 @@ export const groupColumns = (lines, cols) => {
}
return columns
}
-
diff --git a/animism-align/frontend/app/views/viewer/nav/nav.parent.js b/animism-align/frontend/app/views/viewer/nav/nav.parent.js
index 3df2ce4..abe4871 100644
--- a/animism-align/frontend/app/views/viewer/nav/nav.parent.js
+++ b/animism-align/frontend/app/views/viewer/nav/nav.parent.js
@@ -61,7 +61,7 @@ class NavParent extends Component {
e && e.preventDefault()
e && e.stopPropagation()
const { viewer } = this.props
- console.log('>> SEEK')
+ // console.log('>> SEEK')
if (viewer.nextSection) {
actions.viewer.seekToSection(viewer.nextSection)
} else {
diff --git a/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.video.js b/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.video.js
index 252a278..da1e0ed 100644
--- a/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.video.js
+++ b/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.video.js
@@ -34,11 +34,11 @@ class FullscreenVideo extends Component {
this.handleEnd = this.handleEnd.bind(this)
}
componentDidMount() {
- const { video_start_ts } = this.props.element.settings
- const seconds = timestampToSeconds(video_start_ts) || 0.0
+ const video_start_ts = timestampToSeconds(this.props.element.settings.video_start_ts) || 0.0
+ // TODO: here you can add the current play time modulo ...
this.setState({
- video_start_ts: seconds,
- seek: seconds,
+ seek: video_start_ts,
+ video_start_ts,
})
}
componentDidUpdate(prevProps) {
diff --git a/animism-align/frontend/app/views/viewer/player/components.inline/inline.text.js b/animism-align/frontend/app/views/viewer/player/components.inline/inline.text.js
index 2475801..b2633a4 100644
--- a/animism-align/frontend/app/views/viewer/player/components.inline/inline.text.js
+++ b/animism-align/frontend/app/views/viewer/player/components.inline/inline.text.js
@@ -61,17 +61,18 @@ export const Pullquote = ({ paragraph, currentParagraph, currentAnnotation, onAn
/>
)
}
+ const isPullquoteCredit = annotation.type === 'pullquote_credit'
return (
<span
key={annotation.id}
className={
- annotation.type === 'pullquote_credit'
+ isPullquoteCredit
? 'pullquote_credit'
: annotation.id === currentAnnotation
? 'current'
: ''
}
- onClick={e => onAnnotationClick(e, paragraph, annotation)}
+ onClick={e => !isPullquoteCredit && onAnnotationClick(e, paragraph, annotation)}
dangerouslySetInnerHTML={{ __html: ' ' + annotation.text + ' ' }}
/>
)
diff --git a/animism-align/frontend/app/views/viewer/player/components.inline/inline.video.js b/animism-align/frontend/app/views/viewer/player/components.inline/inline.video.js
index d6de779..9a0ff7a 100644
--- a/animism-align/frontend/app/views/viewer/player/components.inline/inline.video.js
+++ b/animism-align/frontend/app/views/viewer/player/components.inline/inline.video.js
@@ -70,6 +70,7 @@ export class MediaVideo extends Component {
)
}
+ // otherwise, inline the vimeo player
const poster = annotation.settings.poster ? {
backgroundImage: 'url(' + posterURL(item) + ')',
} : {}
diff --git a/animism-align/frontend/app/views/viewer/player/components.media/video.scrubber.js b/animism-align/frontend/app/views/viewer/player/components.media/video.scrubber.js
index f866628..e1b22a7 100644
--- a/animism-align/frontend/app/views/viewer/player/components.media/video.scrubber.js
+++ b/animism-align/frontend/app/views/viewer/player/components.media/video.scrubber.js
@@ -73,6 +73,9 @@ class VideoScrubber extends Component {
}
handleMouseMove(e) {
e.stopPropagation()
+ if (e.pageY < window.innerHeight / 2) {
+ return
+ }
// console.log('move', this.defer)
if (this.defer) {
this.defer = false
diff --git a/animism-align/frontend/app/views/viewer/player/components.media/video.subtitles.js b/animism-align/frontend/app/views/viewer/player/components.media/video.subtitles.js
index dfa7a85..f056168 100644
--- a/animism-align/frontend/app/views/viewer/player/components.media/video.subtitles.js
+++ b/animism-align/frontend/app/views/viewer/player/components.media/video.subtitles.js
@@ -3,8 +3,7 @@ import { connect } from 'react-redux'
import actions from 'app/actions'
import { timestampToSeconds, floatInRange } from 'app/utils'
-
-const REGEXP_ALL_COMMAS = new RegExp(',', 'g')
+import { parseSubtitles } from 'app/utils/transcript.utils'
export default class VideoSubtitles extends Component {
state = {
@@ -20,23 +19,10 @@ export default class VideoSubtitles extends Component {
}
}
loadSubtitles() {
- if (!this.props.mediaItem || !this.props.mediaItem.settings.subtitles) return;
- const groups = this.props.mediaItem.settings.subtitles.split("\n\n")
- const subtitles = groups.map((group) => {
- if (!group) return
- const lines = group.trim().split("\n")
- if (!lines.length || !parseInt(lines[0])) {
- return null
- }
- let ts_parts = lines[1].replace(REGEXP_ALL_COMMAS, '.').split(" --> ").map(timestampToSeconds)
- return {
- id: parseInt(lines[0]),
- start_ts: ts_parts[0],
- end_ts: ts_parts[1],
- lines: lines.slice(2),
- }
- }).filter(a => !!a)
- this.setState({ subtitles, current: null })
+ const subtitles = parseSubtitles(this.props.mediaItem, 0)
+ if (subtitles) {
+ this.setState({ subtitles, current: null })
+ }
}
updateCurrentSubtitle() {
const { play_ts } = this.props
diff --git a/animism-align/frontend/app/views/viewer/player/player.transcript.css b/animism-align/frontend/app/views/viewer/player/player.transcript.css
index 5c7056b..dcdcabb 100644
--- a/animism-align/frontend/app/views/viewer/player/player.transcript.css
+++ b/animism-align/frontend/app/views/viewer/player/player.transcript.css
@@ -157,6 +157,14 @@
cursor: pointer;
transition: all 0.1s;
}
+.player-transcript .pullquote span.pullquote_credit,
+.player-transcript .pullquote span.pullquote_credit.current,
+.player-transcript .pullquote span.pullquote_credit.current:hover {
+ box-shadow: 0 0 0 rgba(255,255,255,0.0);
+ background: transparent;
+ color: inherit;
+ cursor: default;
+}
.player-transcript .paragraph {
position: relative;
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 1c1b3cc..8e65843 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
@@ -1,5 +1,9 @@
import React, { Component } from 'react'
+import actions from 'app/actions'
+import { timestampToSeconds, floatInRange } from 'app/utils'
+import { parseSubtitles } from 'app/utils/transcript.utils'
+
import { MediaCitation } from './elementTypes.image'
export const MediaVideo = ({ paragraph, media, currentParagraph, currentAnnotation, onAnnotationClick }) => {
@@ -11,7 +15,7 @@ export const MediaVideo = ({ paragraph, media, currentParagraph, currentAnnotati
}
const item = media.lookup[annotation.settings.media_id]
if (!item) return <div>Media not found: {annotation.settings.media_id}</div>
- return (
+ const el = (
<div
className={className}
data-startts={paragraph.start_ts}
@@ -24,4 +28,74 @@ export const MediaVideo = ({ paragraph, media, currentParagraph, currentAnnotati
{"]"}
</div>
)
+ if (item.settings.subtitles) {
+ return (
+ <div>
+ {el}
+ <TranscriptVideoSubtitles
+ annotation={annotation}
+ mediaItem={item}
+ />
+ </div>
+ )
+ }
+ return el
+}
+
+class TranscriptVideoSubtitles extends Component {
+ state = {
+ subtitles: [],
+ current: null,
+ }
+ componentDidMount() {
+ this.loadSubtitles()
+ }
+ componentDidUpdate(prevProps) {
+ if (this.props.play_ts !== prevProps.play_ts) {
+ this.updateCurrentSubtitle()
+ }
+ }
+ loadSubtitles() {
+ const { annotation, mediaItem, } = this.props
+ const { start_ts } = annotation
+ const video_start_ts = timestampToSeconds(annotation.settings.video_start_ts) || 0.0
+ const subtitles = parseSubtitles(mediaItem, start_ts - video_start_ts)
+ console.log('subtitles', start_ts, video_start_ts, subtitles)
+ if (subtitles) {
+ this.setState({ subtitles, current: null })
+ }
+ }
+ updateCurrentSubtitle() {
+ const { play_ts } = this.props
+ const current = this.state.subtitles.filter(({ start_ts, end_ts }) => (
+ floatInRange(start_ts, play_ts, end_ts)
+ )).slice(-1)
+ if (!current.length) {
+ this.setState({ current: null })
+ } else {
+ this.setState({ current: current[0] })
+ }
+ }
+ render() {
+ const { subtitles, current } = this.state
+ if (!subtitles) return
+ return (
+ <div className="paragraph pullquote subtitles">
+ {subtitles.map(subtitle => {
+ return (
+ <span
+ onClick={e => {
+ e && e.stopPropagation()
+ console.log(subtitle, e)
+ actions.viewer.seekToTimestamp(subtitle.start_ts)
+ }}
+ className={subtitle === current ? 'current' : ""}
+ >
+ {subtitle.lines.join(" ")}
+ </span>
+ )
+ })}
+ </div>
+ )
+ }
}
diff --git a/animism-align/frontend/app/views/viewer/transcript/transcript.css b/animism-align/frontend/app/views/viewer/transcript/transcript.css
index 1649f94..8b2903e 100644
--- a/animism-align/frontend/app/views/viewer/transcript/transcript.css
+++ b/animism-align/frontend/app/views/viewer/transcript/transcript.css
@@ -119,6 +119,7 @@
}
.transcript .pullquote {
border-left: 2px solid #ddd;
+ margin-top: 1rem;
padding-left: 1rem;
}
.transcript .pullquote + .pullquote {
diff --git a/animism-align/frontend/app/views/viewer/viewer.actions.js b/animism-align/frontend/app/views/viewer/viewer.actions.js
index d0e0b3a..86c8d2d 100644
--- a/animism-align/frontend/app/views/viewer/viewer.actions.js
+++ b/animism-align/frontend/app/views/viewer/viewer.actions.js
@@ -190,7 +190,7 @@ export const loadSections = () => dispatch => {
section.inlineParagraphCount = section.paragraphs.filter(p => !p.hidden).length
// console.log(i, section.inlineParagraphCount)
})
- console.log(sections)
+ // console.log(sections)
// console.log(footnoteList)
// console.log(fullscreenTimeline)
dispatch({ type: types.viewer.load_sections, sections, footnoteList })