summaryrefslogtreecommitdiff
path: root/frontend/site/projects/museum/views/_subtitles.overlay.js
blob: ad41e9e4595f8af69e82c2850701be6a5873ccdc (plain)
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)