summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--animism-align/frontend/app/types.js1
-rw-r--r--animism-align/frontend/app/utils/annotation.utils.js10
-rw-r--r--animism-align/frontend/app/views/viewer/nav/eflux.chrome.js7
-rw-r--r--animism-align/frontend/app/views/viewer/nav/eflux.css15
-rw-r--r--animism-align/frontend/app/views/viewer/nav/nav.css34
-rw-r--r--animism-align/frontend/app/views/viewer/nav/nav.parent.js12
-rw-r--r--animism-align/frontend/app/views/viewer/player/player.transcript.js11
-rw-r--r--animism-align/frontend/app/views/viewer/sections/viewer.sections.js10
-rw-r--r--animism-align/frontend/app/views/viewer/viewer.actions.js7
-rw-r--r--animism-align/frontend/app/views/viewer/viewer.reducer.js21
10 files changed, 105 insertions, 23 deletions
diff --git a/animism-align/frontend/app/types.js b/animism-align/frontend/app/types.js
index eca6cf3..855385c 100644
--- a/animism-align/frontend/app/types.js
+++ b/animism-align/frontend/app/types.js
@@ -29,6 +29,7 @@ export const viewer = with_type('viewer', [
'set_current_section', 'reached_end_of_section',
'set_nav_style',
'open_vitrine_modal', 'close_vitrine_modal', 'set_vitrine_index',
+ 'open_growl', 'close_growl',
])
export const site = with_type('site', [
diff --git a/animism-align/frontend/app/utils/annotation.utils.js b/animism-align/frontend/app/utils/annotation.utils.js
index 89e6aea..8640fa9 100644
--- a/animism-align/frontend/app/utils/annotation.utils.js
+++ b/animism-align/frontend/app/utils/annotation.utils.js
@@ -1,4 +1,4 @@
-import { timestampToSeconds } from 'app/utils'
+import { clamp, timestampToSeconds } from 'app/utils'
export const annotationFadeTimings = annotation => {
const fadeInDuration = timestampToSeconds(annotation.settings.fade_in_duration || '0') || 0.1
@@ -39,3 +39,11 @@ export const thumbnailURL = media => {
return null
}
}
+
+export const sectionProgress = (section, play_ts) => {
+ return (clamp(play_ts, section.start_ts, section.end_ts) - section.start_ts) / section.duration
+}
+
+export const sectionProgressPercentage = (section, play_ts) => {
+ return (Math.round(sectionProgress(section, play_ts) * 2000) / 20) + '%'
+} \ No newline at end of file
diff --git a/animism-align/frontend/app/views/viewer/nav/eflux.chrome.js b/animism-align/frontend/app/views/viewer/nav/eflux.chrome.js
index 40c8365..f8c2892 100644
--- a/animism-align/frontend/app/views/viewer/nav/eflux.chrome.js
+++ b/animism-align/frontend/app/views/viewer/nav/eflux.chrome.js
@@ -7,13 +7,16 @@ import {
import { PlayButton } from './viewer.icons'
import actions from 'app/actions'
-const EfluxChrome = React.memo(({ navStyle, playing, transcriptOpen }) => (
+const EfluxChrome = React.memo(({ navStyle, playing, transcriptOpen, started, growlOpen, growlMessage }) => (
<div className={"eflux-header " + navStyle + (transcriptOpen ? ' transcript-open' : '')}>
<div className="eflux-logo">
<a href="/">
{EfluxLogo}
</a>
</div>
+ <div className={growlOpen ? "growl-message open" : "growl-message"}>
+ {growlMessage}
+ </div>
<div className="eflux-nav">
<PlayButton playing={playing} />
<div className="transcript-icon" onClick={() => actions.viewer.toggleComponent('transcript')}>
@@ -27,6 +30,8 @@ const mapStateToProps = state => ({
navStyle: state.viewer.navStyle,
playing: state.audio.playing,
transcriptOpen: state.viewer.transcript,
+ growlOpen: state.viewer.growlOpen,
+ growlMessage: state.viewer.growlMessage,
})
export default connect(mapStateToProps)(EfluxChrome)
diff --git a/animism-align/frontend/app/views/viewer/nav/eflux.css b/animism-align/frontend/app/views/viewer/nav/eflux.css
index 487c04e..fe57779 100644
--- a/animism-align/frontend/app/views/viewer/nav/eflux.css
+++ b/animism-align/frontend/app/views/viewer/nav/eflux.css
@@ -75,3 +75,18 @@
.eflux-logo.black svg line {
stroke: #fff;
}
+
+.growl-message {
+ position: absolute;
+ top: 0; left: 50%;
+ transition: transform 0.2s;
+ transform: translateZ(0) translateY(-5rem) translateX(-50%);
+ background: black;
+ color: white;
+ border: 1px solid;
+ padding: 0.75rem;
+ margin-top: 1rem;
+}
+.growl-message.open {
+ transform: translateZ(0) translateY(0) translateX(-50%);
+} \ No newline at end of file
diff --git a/animism-align/frontend/app/views/viewer/nav/nav.css b/animism-align/frontend/app/views/viewer/nav/nav.css
index 922bd01..a6b9a3b 100644
--- a/animism-align/frontend/app/views/viewer/nav/nav.css
+++ b/animism-align/frontend/app/views/viewer/nav/nav.css
@@ -14,7 +14,7 @@
transform: translateZ(0) translateY(0);
border-top: 1px solid transparent;
}
-.main-nav.hovering-nav {
+.viewer-nav.hovering-nav .main-nav {
background: black;
color: white;
}
@@ -110,6 +110,24 @@
transform: translateZ(0) translateY(-9rem);
}
+/* Inverse progress bar */
+
+.nav-progress-percentage {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ height: calc(3rem - 1px);
+ pointer-events: none;
+ backdrop-filter: invert(0%);
+ transition: opacity 0.2s, backdrop-filter 0.2s, width 0.25s linear;
+ opacity: 0;
+}
+.nav-open .nav-progress-percentage,
+.viewer-nav.hovering-nav .nav-progress-percentage {
+ backdrop-filter: invert(100%);
+ opacity: 1;
+}
+
/* Arrows */
.arrow svg {
@@ -139,8 +157,8 @@
}
.viewer-nav.black .arrow path,
.viewer-nav.black .arrow polygon,
-.viewer-nav .main-nav.hovering-nav .arrow path,
-.viewer-nav .main-nav.hovering-nav .arrow polygon,
+.viewer-nav.hovering-nav .main-nav .arrow path,
+.viewer-nav.hovering-nav .main-nav .arrow polygon,
.nav-open .viewer-nav .arrow path,
.nav-open .viewer-nav .arrow polygon,
.checklist-open .viewer-nav .arrow path,
@@ -157,7 +175,7 @@
.nav-player.playing {
opacity: 0.0;
}
-.main-nav.hovering-nav .nav-player.playing,
+.viewer-nav.hovering-nav .nav-player.playing,
.nav-open .nav-player.playing {
opacity: 1.0;
}
@@ -177,11 +195,11 @@
stroke: #000;
stroke-width: 0.5;
}
-.main-nav.hovering-nav .volume path,
+.viewer-nav.hovering-nav .volume path,
.nav-open .volume path {
fill: #fff;
}
-.main-nav.hovering-nav .volume.muted path,
+.viewer-nav.hovering-nav .volume.muted path,
.nav-open .volume.muted path {
fill: #000;
stroke: #fff;
@@ -198,8 +216,8 @@
.playToggle polygon {
fill: #000;
}
-.main-nav.hovering-nav .playToggle path,
-.main-nav.hovering-nav .playToggle polygon,
+.viewer-nav.hovering-nav .playToggle path,
+.viewer-nav.hovering-nav .playToggle polygon,
.nav-open .playToggle path,
.nav-open .playToggle polygon {
fill: #fff;
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 8ad0cd1..ca1c148 100644
--- a/animism-align/frontend/app/views/viewer/nav/nav.parent.js
+++ b/animism-align/frontend/app/views/viewer/nav/nav.parent.js
@@ -5,7 +5,7 @@ import actions from 'app/actions'
import { ROMAN_NUMERALS } from 'app/constants'
import { Arrow } from './viewer.icons'
import NavPlayer from './nav.player'
-import { thumbnailURL } from 'app/utils/annotation.utils'
+import { thumbnailURL, sectionProgressPercentage } from 'app/utils/annotation.utils'
class NavParent extends Component {
state = {
@@ -38,11 +38,11 @@ class NavParent extends Component {
}, 50)
}
render() {
- const { viewer } = this.props
+ const { viewer, play_ts } = this.props
let containerClassName = "viewer-nav " + viewer.navStyle
let navClassName = 'nav-row main-nav'
- if (this.state.hoveringNav) navClassName += ' hovering-nav'
- if (this.state.hoveringNext || viewer.atEndOfSection) containerClassName += ' hovering-next'
+ if (this.state.hoveringNav) containerClassName += ' hovering-nav'
+ if ((this.state.hoveringNext || viewer.atEndOfSection) && !viewer.nav) containerClassName += ' hovering-next'
return (
<div className={containerClassName} onMouseLeave={this.handleMouseLeave}>
<div className={navClassName}>
@@ -73,6 +73,9 @@ class NavParent extends Component {
</span>
}
</div>
+ <div className="nav-progress-percentage" style={{
+ width: viewer.currentSection ? sectionProgressPercentage(viewer.currentSection, play_ts) : 0
+ }} />
</div>
{viewer.nextSection &&
<div className="next-section-thumbnail"
@@ -91,6 +94,7 @@ class NavParent extends Component {
const mapStateToProps = state => ({
viewer: state.viewer,
+ play_ts: state.audio.play_ts,
})
export default connect(mapStateToProps)(NavParent)
diff --git a/animism-align/frontend/app/views/viewer/player/player.transcript.js b/animism-align/frontend/app/views/viewer/player/player.transcript.js
index 17218d5..cee70a8 100644
--- a/animism-align/frontend/app/views/viewer/player/player.transcript.js
+++ b/animism-align/frontend/app/views/viewer/player/player.transcript.js
@@ -14,6 +14,7 @@ class PlayerTranscript extends Component {
this.handleClose = this.handleClose.bind(this)
this.handleAnnotationClick = this.handleAnnotationClick.bind(this)
this.handleParagraphDoubleClick = this.handleParagraphDoubleClick.bind(this)
+ this.handleScroll = this.handleScroll.bind(this)
this.containerRef = React.createRef()
}
@@ -37,10 +38,16 @@ class PlayerTranscript extends Component {
handleClose() {
}
+ handleScroll(e) {
+ if (this.props.viewer.growlOpen) {
+ actions.viewer.closeGrowl()
+ }
+ }
+
render() {
const { paragraphs } = this.props.section
return (
- <div className="player-transcript" ref={this.containerRef}>
+ <div className="player-transcript" ref={this.containerRef} onScroll={this.handleScroll}>
<div className='content'>
<ParagraphList
paragraphs={paragraphs}
@@ -55,7 +62,7 @@ class PlayerTranscript extends Component {
}
const mapStateToProps = state => ({
- // viewer: state.viewer,
+ viewer: state.viewer,
})
const mapDispatchToProps = dispatch => ({
diff --git a/animism-align/frontend/app/views/viewer/sections/viewer.sections.js b/animism-align/frontend/app/views/viewer/sections/viewer.sections.js
index 05eef9c..e0ec212 100644
--- a/animism-align/frontend/app/views/viewer/sections/viewer.sections.js
+++ b/animism-align/frontend/app/views/viewer/sections/viewer.sections.js
@@ -6,7 +6,7 @@ import actions from 'app/actions'
import ViewerSectionsNav from './viewer.sections.nav'
import { ROMAN_NUMERALS, CURTAIN_COLOR_LOOKUP } from 'app/constants'
import { clamp, timestamp, floatInRange, floatLT } from 'app/utils'
-import { thumbnailURL } from 'app/utils/annotation.utils'
+import { thumbnailURL, sectionProgressPercentage } from 'app/utils/annotation.utils'
import { SpeakerIcon } from '../nav/viewer.icons'
class ViewerSections extends Component {
@@ -23,7 +23,7 @@ class ViewerSections extends Component {
// console.log(section)
const media = section.media.length ? section.media[0].media : null
const { no_audio, section_nav_color } = section
- const progress = Math.round(sectionProgress(section, play_ts) * 100)
+ const progress = sectionProgressPercentage(section, play_ts)
return (
<div
className={(!currentSection || section.index === currentSection.index) ? "viewer-section current-section" : "viewer-section"}
@@ -44,7 +44,7 @@ class ViewerSections extends Component {
</div>
<div className="section-progress-bar">
<div className="section-progress"
- style={{ width: progress + '%' }}
+ style={{ width: progress }}
/>
</div>
</div>
@@ -68,10 +68,6 @@ class ViewerSections extends Component {
}
}
-const sectionProgress = (section, play_ts) => {
- return (clamp(play_ts, section.start_ts, section.end_ts) - section.start_ts) / section.duration
-}
-
const mapStateToProps = state => ({
nav: state.viewer.nav,
play_ts: state.audio.play_ts,
diff --git a/animism-align/frontend/app/views/viewer/viewer.actions.js b/animism-align/frontend/app/views/viewer/viewer.actions.js
index f5f0630..e8aaf0d 100644
--- a/animism-align/frontend/app/views/viewer/viewer.actions.js
+++ b/animism-align/frontend/app/views/viewer/viewer.actions.js
@@ -218,3 +218,10 @@ export const closeVitrineModal = (media, id) => dispatch => {
export const setVitrineIndex = (index) => dispatch => {
dispatch({ type: types.viewer.set_vitrine_index, index })
}
+
+export const openGrowl = message => dispatch => {
+ dispatch({ type: types.viewer.open_growl, message })
+}
+export const closeGrowl = () => dispatch => {
+ dispatch({ type: types.viewer.close_growl })
+}
diff --git a/animism-align/frontend/app/views/viewer/viewer.reducer.js b/animism-align/frontend/app/views/viewer/viewer.reducer.js
index 2ab5f57..4c25d64 100644
--- a/animism-align/frontend/app/views/viewer/viewer.reducer.js
+++ b/animism-align/frontend/app/views/viewer/viewer.reducer.js
@@ -11,6 +11,8 @@ const initialState = {
navStyle: 'white',
autoAdvance: false,
atEndOfSection: false,
+ growlOpen: true,
+ growlMessage: "Start the episode by clicking play or scroll to browse on your own.",
vitrineModal: {
open: false,
media: null,
@@ -29,6 +31,25 @@ export default function viewerReducer(state = initialState, action) {
[action.key]: action.value,
}
+ case types.audio.play:
+ return {
+ ...state,
+ growlOpen: false,
+ }
+
+ case types.viewer.open_growl:
+ return {
+ ...state,
+ growlMessage: action.message,
+ growlOpen: true,
+ }
+
+ case types.viewer.close_growl:
+ return {
+ ...state,
+ growlOpen: false,
+ }
+
case types.viewer.load_sections:
return {
...state,