diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2021-03-17 18:11:26 +0100 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2021-03-17 18:11:26 +0100 |
| commit | d165a0727e42349d935ab3ee287242f1e5029742 (patch) | |
| tree | b4fa68209127efdd4eb46c82eaef280535692611 /frontend/site | |
| parent | 92566ba17f5e921d5bff1f3fb4e4b0d92ca4fd39 (diff) | |
frontend. export/view button. interactivity sanity check
Diffstat (limited to 'frontend/site')
| -rw-r--r-- | frontend/site/audio/audio.player.js | 43 | ||||
| -rw-r--r-- | frontend/site/index.js | 2 | ||||
| -rw-r--r-- | frontend/site/site.css | 20 | ||||
| -rw-r--r-- | frontend/site/site/site.actions.js | 4 | ||||
| -rw-r--r-- | frontend/site/site/site.reducer.js | 7 | ||||
| -rw-r--r-- | frontend/site/store.js | 3 | ||||
| -rw-r--r-- | frontend/site/types.js | 4 | ||||
| -rw-r--r-- | frontend/site/viewer/viewer.container.js | 60 |
8 files changed, 131 insertions, 12 deletions
diff --git a/frontend/site/audio/audio.player.js b/frontend/site/audio/audio.player.js new file mode 100644 index 0000000..9a2d783 --- /dev/null +++ b/frontend/site/audio/audio.player.js @@ -0,0 +1,43 @@ +export default class AudioPlayer { + players = {} + + play({ item, restart, loop }) { + return new Promise((resolve, reject) => { + const { id, url } = item + if (id in players) { + if (restart) { + players[id].currentTime = 0 + players[id].play() + return resolve() + } + return reject() + } + const player = document.createElement('audio') + const handleEnded = () => { + unbind() + resolve() + } + const handleError = (error) => { + console.error(error) + unbind() + reject(error) + } + const bind = () => { + player.addEventListener('ended', handleEnded) + player.addEventListener('error', handleError) + this.players[id] = player + } + const unbind = () => { + player.removeEventListener('ended', handleEnded) + player.removeEventListener('error', handleError) + delete this.players[id] + } + const start = () => { + player.src = url + player.play() + } + bind() + start() + }) + } +} diff --git a/frontend/site/index.js b/frontend/site/index.js index 36eeae8..337d362 100644 --- a/frontend/site/index.js +++ b/frontend/site/index.js @@ -2,6 +2,8 @@ import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' +import './site.css' + import App from 'site/app' import { store, history } from 'site/store' diff --git a/frontend/site/site.css b/frontend/site/site.css new file mode 100644 index 0000000..0597514 --- /dev/null +++ b/frontend/site/site.css @@ -0,0 +1,20 @@ +.roadblock { + position: fixed; + top: 0; left: 0; + display: flex; + width: 100vw; + height: 100vh; + justify-content: center; + align-items: center; + cursor: pointer; +} +.roadblock div { + display: inline-block; + text-align: center; +} +.roadblock h2 { + font-style: italic; +} +.roadblock button { + padding: 0.5rem; +} diff --git a/frontend/site/site/site.actions.js b/frontend/site/site/site.actions.js index 3547ec0..07814d6 100644 --- a/frontend/site/site/site.actions.js +++ b/frontend/site/site/site.actions.js @@ -9,3 +9,7 @@ export const setSiteTitle = title => dispatch => { export const loadSite = (graph_name, path_name) => dispatch => ( api(dispatch, types.site, 'site', '/' + graph_name + '/index.json') ) + +export const interact = () => dispatch => { + dispatch({ type: types.site.interact }) +}
\ No newline at end of file diff --git a/frontend/site/site/site.reducer.js b/frontend/site/site/site.reducer.js index 53fa555..e0b53fb 100644 --- a/frontend/site/site/site.reducer.js +++ b/frontend/site/site/site.reducer.js @@ -2,6 +2,7 @@ import * as types from 'site/types' const initialState = { siteTitle: 'swimmer', + interactive: false, graph: { loading: true, } @@ -22,6 +23,12 @@ export default function siteReducer(state = initialState, action) { graph: action.data.graph, } + case types.site.interact: + return { + ...state, + interactive: true, + } + case '@@router/LOCATION_CHANGE': return { ...state, diff --git a/frontend/site/store.js b/frontend/site/store.js index 6511613..5cb1a1b 100644 --- a/frontend/site/store.js +++ b/frontend/site/store.js @@ -4,6 +4,7 @@ import { createBrowserHistory } from 'history' import thunk from 'redux-thunk' import siteReducer from 'site/site/site.reducer' +import AudioPlayer from 'site/audio/audio.player' const createRootReducer = history => ( combineReducers({ @@ -13,7 +14,7 @@ const createRootReducer = history => ( }) ) -const configureStore = (initialState = {}, history) => { +const configureStore = (initialState = { audio: audioPlayer }, history) => { const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose const store = createStore( diff --git a/frontend/site/types.js b/frontend/site/types.js index 23bed98..4ab897f 100644 --- a/frontend/site/types.js +++ b/frontend/site/types.js @@ -1,7 +1,7 @@ -import { with_type, crud_type } from 'app/api/crud.types' +import { with_type } from 'app/api/crud.types' export const site = with_type('site', [ - 'set_site_title', 'loading', 'loaded', 'error', + 'set_site_title', 'loading', 'loaded', 'error', 'interact' ]) export const system = with_type('system', [ diff --git a/frontend/site/viewer/viewer.container.js b/frontend/site/viewer/viewer.container.js index 1b3d564..3f1c9c5 100644 --- a/frontend/site/viewer/viewer.container.js +++ b/frontend/site/viewer/viewer.container.js @@ -12,12 +12,17 @@ import 'app/views/page/page.css' class ViewerContainer extends Component { state = { page: {}, + bounds: { width: window.innerWidth, height: window.innerHeight }, + roadblock: false, } constructor(props) { super(props) this.pageRef = React.createRef() this.handleMouseDown = this.handleMouseDown.bind(this) + this.handleResize = this.handleResize.bind(this) + this.removeRoadblock = this.removeRoadblock.bind(this) + window.addEventListener('resize', this.handleResize) } componentDidUpdate(prevProps) { @@ -27,20 +32,30 @@ class ViewerContainer extends Component { } } + componentWillUnmount() { + window.removeEventListener('resize', this.handleResize) + actions.site.interact() + } + + handleResize() { + this.setState({ + bounds: { + width: window.innerWidth, + height: window.innerHeight, + } + }) + } + load() { const { graph_name, page_name } = this.props.match.params const page_path = ["", graph_name, page_name].join('/') const { pages, home_page } = this.props.graph - const page = pages[page_path] - if (!page) { - // console.log('-> home page') - console.log(page_path) - const { home_page } = this.props.graph - this.setState({ page: pages[home_page] }) + const page = pages[page_path] || pages[home_page] + if (!this.props.interactive && hasAutoplayVideo(page)) { + this.setState({ page, roadblock: true }) } else { - // console.log(page) - console.log(page_path) - this.setState({ page }) + this.setState({ page, roadblock: false }) + actions.site.interact() } } @@ -50,6 +65,9 @@ class ViewerContainer extends Component { render() { const { page } = this.state + if (this.state.roadblock) { + return this.renderRoadblock() + } if (this.props.graph.loading || !page.id) { return ( <div> @@ -83,11 +101,35 @@ class ViewerContainer extends Component { </div> ) } + + removeRoadblock() { + actions.site.interact() + this.setState({ roadblock: false }) + } + + renderRoadblock() { + const { title } = this.props.graph + return ( + <div className='roadblock' onClick={this.removeRoadblock}> + <div> + <h2>{title}</h2> + <button>Enter</button> + </div> + </div> + ) + } +} + +const hasAutoplayVideo = page => { + return page.tiles.some(tile => { + return tile.type === 'video' && !tile.settings.muted + }) } const mapStateToProps = state => ({ site: state.site, graph: state.site.graph, + interactive: state.site.interactive, }) const mapDispatchToProps = dispatch => ({ |
