summaryrefslogtreecommitdiff
path: root/frontend/site/audio
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/site/audio')
-rw-r--r--frontend/site/audio/audio.player.js141
-rw-r--r--frontend/site/audio/audio.reducer.js18
2 files changed, 159 insertions, 0 deletions
diff --git a/frontend/site/audio/audio.player.js b/frontend/site/audio/audio.player.js
new file mode 100644
index 0000000..17edeee
--- /dev/null
+++ b/frontend/site/audio/audio.player.js
@@ -0,0 +1,141 @@
+import { history } from 'site/store'
+
+export default class AudioPlayer {
+ files = {}
+ players = {}
+ current_background_id = 0
+
+ constructor() {
+ this.done = this.done.bind(this)
+ }
+
+ load(graph) {
+ this.files = graph.uploads
+ .filter(upload => upload.tag === 'audio')
+ .reduce((accumulator, item) => {
+ accumulator[item.id] = item
+ return accumulator
+ }, {})
+ }
+
+ has(id) {
+ return (
+ (id > 0) &&
+ (id in this.files)
+ )
+ }
+
+ done(id) {
+ // console.log('remove', id)
+ delete this.players[id]
+ }
+
+ playPage(page) {
+ const { background_audio_id, restart_audio } = page.settings
+ // console.log('playPage', page)
+ if (
+ this.current_background_id
+ && this.current_background_id !== background_audio_id
+ && this.current_background_id in this.players
+ ) {
+ this.players[this.current_background_id].stop()
+ }
+ if (this.has(background_audio_id)) {
+ this.current_background_id = background_audio_id
+ this.playFile({
+ id: background_audio_id,
+ type: 'background',
+ restart: !!restart_audio,
+ })
+ }
+ }
+
+ playTile({ tile, type }) {
+ let id = type === 'click'
+ ? tile.settings.audio_on_click_id
+ : type === 'hover'
+ ? tile.settings.audio_on_hover_id
+ : null
+ if (this.has(id)) {
+ this.playFile({ id, tile, type })
+ }
+ }
+
+ playFile({ id, tile, type, restart, loop }) {
+ const item = this.files[id]
+ if (id in this.players) {
+ if (restart) {
+ this.players[id].restart()
+ }
+ if (tile && !this.players[id].tile) {
+ this.players[id].tile = tile
+ this.players[id].type = type
+ }
+ return this.players[id]
+ } else {
+ this.players[id] = new Player({
+ item,
+ tile,
+ type,
+ done: this.done
+ })
+ this.players[id].play()
+ return this.players[id]
+ }
+ }
+}
+
+class Player {
+ constructor({ item, tile, type, done }) {
+ this.item = item
+ this.tile = tile
+ this.type = type
+ this.done = done
+ this.audio = document.createElement('audio')
+ this.handleEnded = this.handleEnded.bind(this)
+ this.handleError = this.handleError.bind(this)
+ this.release = this.release.bind(this)
+ this.audio.addEventListener('ended', this.handleEnded)
+ this.audio.addEventListener('error', this.handleError)
+ this.audio.src = item.url
+ }
+
+ release() {
+ if (this.type === 'click' && this.tile && this.tile.settings.navigate_when_audio_finishes) {
+ history.push(this.tile.href)
+ }
+ this.audio.removeEventListener('ended', this.handleEnded)
+ this.audio.removeEventListener('error', this.handleError)
+ this.done(this.item.id)
+ this.item = null
+ this.done = null
+ this.audio = null
+ }
+
+ handleError(error) {
+ console.error(error)
+ this.release()
+ }
+
+ handleEnded() {
+ if (this.type === 'background') {
+ this.restart()
+ } else {
+ this.release()
+ }
+ }
+
+ play() {
+ this.audio.play()
+ }
+
+ restart() {
+ this.audio.currentTime = 0
+ this.audio.play()
+ }
+
+ stop() {
+ this.audio.pause()
+ this.release()
+ }
+}
diff --git a/frontend/site/audio/audio.reducer.js b/frontend/site/audio/audio.reducer.js
new file mode 100644
index 0000000..f0bf0e9
--- /dev/null
+++ b/frontend/site/audio/audio.reducer.js
@@ -0,0 +1,18 @@
+import AudioPlayer from 'site/audio/audio.player'
+import * as types from 'site/types'
+
+const initialState = {
+ player: new AudioPlayer(),
+}
+
+export default function audioReducer(state = initialState, action) {
+ // console.log(action.type, action)
+ switch (action.type) {
+ case types.site.loaded:
+ state.player.load(action.data.graph)
+ return state
+
+ default:
+ return state
+ }
+}