1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
/**
* Subtitles for Charles Stankievech
*/
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { SUBTITLES } from '../subtitles.js'
import './subtitles.css'
const TITLE_SHOW_DELAY = 1000
const TITLE_HIDE_DELAY = 6000
const FIRST_SUBTITLE_DELAY = 3000
const SUBTITLE_DELAY = 3500
const LAST_SUBTITLE_DELAY = 5000
class SubtitlesOverlay extends Component {
state = {
content: null,
}
constructor(props) {
super(props)
this.titleRef = React.createRef()
this.subtitleRef = React.createRef()
this.showTitle = this.showTitle.bind(this)
this.nextSubtitle = this.nextSubtitle.bind(this)
}
componentDidMount() {
if (this.props.interactive) {
this.load()
}
}
componentDidUpdate(prevProps) {
if (
(this.props.interactive && this.props.interactive !== prevProps.interactive)
|| this.props.location.pathname !== prevProps.location.pathname
) {
this.load()
}
if (
this.props.popups !== prevProps.popups
&& this.state.content
&& this.state.content.popup
&& this.props.popups[this.state.content.popup]
) {
this.startSubtitles()
}
}
load() {
const { page_name } = this.props.match.params
clearTimeout(this.titleTimeout)
clearTimeout(this.subtitleTimeout)
this.props.audio.player.stop("text-overlay")
if (SUBTITLES[page_name]) {
this.setState({
content: SUBTITLES[page_name],
open: false,
})
setTimeout(this.showTitle, 0)
} else {
this.setState({
content: null,
open: false,
})
}
}
showTitle() {
if (!this.titleRef.current) return
this.titleRef.current.style.color = this.state.content.color || "rgba(255, 121, 13, 1.0)"
this.titleRef.current.style.opacity = 0
this.titleTimeout = setTimeout(() => {
this.titleRef.current.style.opacity = 1
this.titleTimeout = setTimeout(() => {
this.titleRef.current.style.opacity = 0
}, TITLE_HIDE_DELAY)
}, TITLE_SHOW_DELAY)
}
startSubtitles() {
if (this.state.content.audio_url) {
this.props.audio.player.stop("text-overlay")
this.props.audio.player.playURL({
id: "text-overlay",
url: this.state.content.audio_url,
})
}
clearTimeout(this.subtitleTimeout)
this.index = -1
this.subtitleTimeout = setTimeout(this.nextSubtitle, FIRST_SUBTITLE_DELAY)
}
nextSubtitle() {
if (!this.subtitleRef.current) return
this.index += 1
const subtitle = this.state.content.subtitles[this.index] || ""
this.subtitleRef.current.style.color = this.state.content.color || "rgba(255, 121, 13, 1.0)"
this.subtitleRef.current.innerHTML = subtitle
if (this.index === (this.state.content.subtitles.length - 1)) {
this.subtitleTimeout = setTimeout(this.nextSubtitle, LAST_SUBTITLE_DELAY)
}
else if (subtitle.length) {
this.subtitleTimeout = setTimeout(this.nextSubtitle, SUBTITLE_DELAY)
}
}
render() {
const { content } = this.state
const { popups, interactive } = this.props
if (!interactive || !content) return null
return (
<div>
<div
ref={this.titleRef}
className="chapter-title"
dangerouslySetInnerHTML={{ __html: content.title }}
/>
{content.popup && popups[content.popup] && (
<div
ref={this.subtitleRef}
className="subtitles"
/>
)}
</div>
)
}
}
const mapStateToProps = state => ({
audio: state.audio,
popups: state.site.popups,
interactive: state.site.interactive,
})
export default connect(mapStateToProps)(SubtitlesOverlay)
|