restructure overlay

This commit is contained in:
Lachlan Kermode
2019-02-13 16:13:54 +00:00
parent b1e47ed2eb
commit 1db2fe219a
9 changed files with 194 additions and 223 deletions

View File

@@ -0,0 +1,61 @@
import React from 'react'
import { Player } from 'video-react'
import Img from 'react-image'
import Md from './Md'
import Spinner from '../presentational/Spinner'
import NoSource from '../presentational/NoSource'
export default ({ media, viewIdx }) => {
const el = document.querySelector(`.source-media-gallery`)
const shiftW = el ? el.getBoundingClientRect().width : 0
function renderMedia (media) {
const { path, type } = media
switch (type) {
case 'Image':
return (
<div className='source-image-container'>
<Img
className='source-image'
src={path}
loader={<div className='source-image-loader'><Spinner /></div>}
unloader={<NoSource failedUrls={[ path ]} />}
/>
</div>
)
case 'Video':
return (
<div className='media-player'>
<Player
className='source-video'
playsInline
src={path}
/>
</div>
)
case 'Text':
return (
<div className='source-text-container'>
<Md
path={path}
loader={<Spinner />}
unloader={() => this.renderError()}
/>
</div>
)
default:
return (
<NoSource failedUrls={[`Application does not support extension: ${path.split('.')[1]}`]} />
)
}
}
return (
<div
className='source-media-gallery'
style={{ transform: `translate(${viewIdx * -shiftW}px)` }}
>
{media.map((m) => renderMedia(m))}
</div>
)
}

View File

@@ -0,0 +1,36 @@
import React from 'react'
export default ({ viewIdx, paths, onShiftHandler }) => {
const backArrow = viewIdx !== 0 ? (
<div
className='back'
onClick={() => onShiftHandler(-1)}
>
<svg>
<path d='M0,-7.847549217020565L6.796176979388489,3.9237746085102825L-6.796176979388489,3.9237746085102825Z' />
</svg>
</div>
) : null
const forwardArrow = viewIdx < paths.length - 1 ? (
<div
className='next'
onClick={() => onShiftHandler(1)}
>
<svg>
<path d='M0,-7.847549217020565L6.796176979388489,3.9237746085102825L-6.796176979388489,3.9237746085102825Z' />
</svg>
</div>
) : null
if (paths.length > 1) {
return (
<div className='media-gallery-controls'>
{backArrow}
{forwardArrow}
</div>
)
}
return (
<div className='media-gallery-controls' />
)
}

View File

@@ -0,0 +1,21 @@
import React from 'react'
import copy from '../../js/data/copy.json'
const LoadingOverlay = ({ isLoading, language }) => {
let classes = 'loading-overlay'
classes += (!isLoading) ? ' hidden' : ''
return (
<div id='loading-overlay' className={classes}>
<div className='loading-wrapper'>
<span id='loading-text' className='text'>{copy[language].loading}</span>
<div className='spinner'>
<div className='double-bounce1' />
<div className='double-bounce2' />
</div>
</div>
</div>
)
}
export default LoadingOverlay

View File

@@ -0,0 +1,44 @@
/* global fetch */
import React from 'react'
import PropTypes from 'prop-types'
import marked from 'marked'
class Md extends React.Component {
constructor (props) {
super(props)
this.state = { md: null, error: null }
}
componentDidMount () {
fetch(this.props.path)
.then(resp => resp.text())
.then(text => {
if (text.length <= 0) { throw new Error() }
this.setState({ md: marked(text) })
})
.catch(() => {
this.setState({ error: true })
})
}
render () {
if (this.state.md && !this.state.error) {
return (
<div className='md-container' dangerouslySetInnerHTML={{ __html: this.state.md }} />
)
} else if (this.state.error) {
return this.props.unloader || <div>Error: couldn't load source</div>
} else {
return this.props.loader
}
}
}
Md.propTypes = {
loader: PropTypes.func,
unloader: PropTypes.func.isRequired,
path: PropTypes.string.isRequired
}
export default Md

View File

@@ -0,0 +1,77 @@
import React from 'react'
import Content from './Content'
import Controls from './Controls'
import { selectTypeFromPath } from '../../js/utilities'
class SourceOverlay extends React.Component {
constructor () {
super()
this.state = { idx: 0 }
this.onShiftGallery = this.onShiftGallery.bind(this)
}
getTypeCounts (media) {
return media.reduce(
(acc, vl) => {
acc[vl.type] += 1
return acc
},
{ Image: 0, Video: 0, Text: 0 }
)
}
onShiftGallery (shift) {
// no more left
if (this.state.idx === 0 && shift === -1) return
// no more right
if (this.state.idx === this.props.source.paths.length - 1 && shift === 1) return
this.setState({ idx: this.state.idx + shift })
}
render () {
if (typeof (this.props.source) !== 'object') {
return this.renderError()
}
const { url, title, paths, date, type, desc } = this.props.source
return (
<div className='mo-overlay' onClick={this.props.onCancel}>
<div className='mo-container' onClick={e => e.stopPropagation()}>
<div className='mo-header'>
<div className='mo-header-close' onClick={this.props.onCancel}>
<button className='side-menu-burg is-active'><span /></button>
</div>
<div className='mo-header-text'>{this.props.source.title.substring(0, 200)}</div>
</div>
<div className='mo-media-container'>
<Content media={paths.map(selectTypeFromPath)} viewIdx={this.state.idx} />
<Controls paths={paths} viewIdx={this.state.idx} onShiftHandler={this.onShiftGallery} />
</div>
<div className='mo-meta-container'>
<div className='mo-box-title'>
{title ? <p><b>{title}</b></p> : null}
<div>{desc}</div>
</div>
<div className='mo-box'>
<div>
{type ? <h4>Media type</h4> : null}
{type ? <p><i className='material-icons left'>perm_media</i>{type}</p> : null}
</div>
<div>
{date ? <h4>Date</h4> : null}
{date ? <p><i className='material-icons left'>today</i>{date}</p> : null}
</div>
<div>
{url ? <h4>Link</h4> : null}
{url ? <span><i className='material-icons left'>link</i><a href={url} target='_blank'>Link to original URL</a></span> : null}
</div>
</div>
</div>
</div>
</div>
)
}
}
export default SourceOverlay