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
|
import React, { Component } from 'react'
import { connect } from 'react-redux'
import actions from 'app/actions'
import { ROMAN_NUMERALS, SECTION_LIMITED_MESSAGE } from 'app/constants'
import { timestamp } from 'app/utils'
import { thumbnailURL, sectionProgressPercentage } from 'app/utils/annotation.utils'
import { SpeakerIcon } from '../nav/viewer.icons'
const SECTION_WIDTH = 13 * 16
class ViewerSectionsList extends Component {
state = {
selectedSectionIndex: -1,
}
constructor(props) {
super(props)
this.scrollRef = React.createRef()
this.handleWheel = this.handleWheel.bind(this)
}
shouldComponentUpdate(nextProps) {
if (this.props.currentSection !== nextProps.currentSection) {
this.scrollToSection(nextProps.currentSection)
}
if (nextProps.nav !== this.props.nav) return true
return nextProps.nav
}
scrollToSection(section) {
const dx = section.index * SECTION_WIDTH
clearTimeout(this.timeout)
this.timeout = setTimeout(() => {
this.scrollRef.current.scrollTo(dx, 0)
}, 500)
}
handleWheel(e) {
let delta = Math.abs(e.deltaY) > Math.abs(e.deltaX) ? e.deltaY : e.deltaX
this.scrollRef.current.scrollLeft += delta
}
handleSectionClick(e, section) {
if (this.props.onlyEnableFirstSection && section.index !== 0) {
this.setState({ selectedSectionIndex: section.index })
clearTimeout(this.warningFadeTimeout)
this.warningFadeTimeout = setTimeout(() => {
this.setState({ selectedSectionIndex: -1 })
}, 10000)
} else {
actions.viewer.seekToSection(section)
}
}
render() {
const { play_ts, sections, media, currentSection, onlyEnableFirstSection } = this.props
const { selectedSectionIndex } = this.state
return (
<div
ref={this.scrollRef}
className="viewer-sections-scroll"
onWheel={e => this.handleWheel(e)}
>
{sections.map(section => {
// console.log(section)
let mediaItem
if (section.cover_id) {
mediaItem = media.lookup[section.cover_id]
} else {
mediaItem = section.media.length ? section.media[0].media : null
}
const { no_audio, section_nav_color } = section
const progress = sectionProgressPercentage(section, play_ts)
return (
<div
className={(!currentSection || section.index === currentSection.index) ? "viewer-section current-section" : "viewer-section"}
key={section.index}
onClick={e => this.handleSectionClick(e, section)}
>
<div className="section-content">
<div className="section-thumbnail" style={{
backgroundImage: mediaItem && 'url(' + thumbnailURL(mediaItem) + ')',
}}>
{!no_audio &&
<div className={"section-duration-" + section_nav_color}>
<div className="section-duration">
{timestamp(section.duration)}
</div>
<div className="section-has-audio">
{SpeakerIcon}
</div>
<div className="section-progress-bar">
<div className="section-progress"
style={{ width: progress }}
/>
</div>
</div>
}
</div>
<div className="section-title">
{ROMAN_NUMERALS[section.index]}<br />
{section.title}
</div>
<div className="section-media">
{section.mediaLabels}
</div>
</div>
{!!(onlyEnableFirstSection && section.index) && (
<div className={section.index === selectedSectionIndex ? 'section-limited visible' : 'section-limited'}>
{SECTION_LIMITED_MESSAGE}
</div>
)}
</div>
)
})}
</div>
)
}
}
const mapStateToProps = state => ({
media: state.media.index,
nav: state.viewer.nav,
onlyEnableFirstSection: state.viewer.onlyEnableFirstSection,
play_ts: state.audio.play_ts,
sections: state.viewer.sections,
currentSection: state.viewer.currentSection,
})
export default connect(mapStateToProps)(ViewerSectionsList)
|