From 1db2fe219a9bcad013e98ed5d458a32299f4753c Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Wed, 13 Feb 2019 16:13:54 +0000 Subject: [PATCH] restructure overlay --- src/components/App.jsx | 6 +- src/components/{Dashboard.jsx => Layout.js} | 6 +- src/components/Overlay/Content.js | 61 +++++ src/components/Overlay/Controls.js | 36 +++ .../LoadingOverlay.js => Overlay/Loading.js} | 0 src/components/{Md.jsx => Overlay/Md.js} | 0 src/components/Overlay/Media.js | 77 +++++++ src/components/SourceOverlay.jsx | 216 ------------------ src/js/utilities.js | 15 ++ 9 files changed, 194 insertions(+), 223 deletions(-) rename src/components/{Dashboard.jsx => Layout.js} (97%) create mode 100644 src/components/Overlay/Content.js create mode 100644 src/components/Overlay/Controls.js rename src/components/{presentational/LoadingOverlay.js => Overlay/Loading.js} (100%) rename src/components/{Md.jsx => Overlay/Md.js} (100%) create mode 100644 src/components/Overlay/Media.js delete mode 100644 src/components/SourceOverlay.jsx diff --git a/src/components/App.jsx b/src/components/App.jsx index ac12e14..f876253 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -1,13 +1,11 @@ import '../scss/main.scss' import React from 'react' -import Dashboard from './Dashboard.jsx' +import Layout from './Layout' class App extends React.Component { render () { return ( -
- -
+ ) } } diff --git a/src/components/Dashboard.jsx b/src/components/Layout.js similarity index 97% rename from src/components/Dashboard.jsx rename to src/components/Layout.js index 133b744..8a26dd8 100644 --- a/src/components/Dashboard.jsx +++ b/src/components/Layout.js @@ -4,8 +4,8 @@ import { bindActionCreators } from 'redux' import { connect } from 'react-redux' import * as actions from '../actions' -import SourceOverlay from './SourceOverlay.jsx' -import LoadingOverlay from './presentational/LoadingOverlay' +import MediaOverlay from './Overlay/Media' +import LoadingOverlay from './Overlay/Loading' import Map from './Map.jsx' import Toolbar from './Toolbar.jsx' import CardStack from './CardStack.jsx' @@ -171,7 +171,7 @@ class Dashboard extends React.Component { onToggle={actions.markNotificationsRead} /> {app.source ? ( - { actions.updateSource(null) diff --git a/src/components/Overlay/Content.js b/src/components/Overlay/Content.js new file mode 100644 index 0000000..9c1db50 --- /dev/null +++ b/src/components/Overlay/Content.js @@ -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 ( +
+
} + unloader={} + /> + + ) + case 'Video': + return ( +
+ +
+ ) + case 'Text': + return ( +
+ } + unloader={() => this.renderError()} + /> +
+ ) + default: + return ( + + ) + } + } + + return ( +
+ {media.map((m) => renderMedia(m))} +
+ ) +} diff --git a/src/components/Overlay/Controls.js b/src/components/Overlay/Controls.js new file mode 100644 index 0000000..e547123 --- /dev/null +++ b/src/components/Overlay/Controls.js @@ -0,0 +1,36 @@ +import React from 'react' + +export default ({ viewIdx, paths, onShiftHandler }) => { + const backArrow = viewIdx !== 0 ? ( +
onShiftHandler(-1)} + > + + + +
+ ) : null + const forwardArrow = viewIdx < paths.length - 1 ? ( +
onShiftHandler(1)} + > + + + +
+ ) : null + + if (paths.length > 1) { + return ( +
+ {backArrow} + {forwardArrow} +
+ ) + } + return ( +
+ ) +} diff --git a/src/components/presentational/LoadingOverlay.js b/src/components/Overlay/Loading.js similarity index 100% rename from src/components/presentational/LoadingOverlay.js rename to src/components/Overlay/Loading.js diff --git a/src/components/Md.jsx b/src/components/Overlay/Md.js similarity index 100% rename from src/components/Md.jsx rename to src/components/Overlay/Md.js diff --git a/src/components/Overlay/Media.js b/src/components/Overlay/Media.js new file mode 100644 index 0000000..158f8ae --- /dev/null +++ b/src/components/Overlay/Media.js @@ -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 ( +
+
e.stopPropagation()}> +
+
+ +
+
{this.props.source.title.substring(0, 200)}
+
+
+ + +
+
+
+ {title ?

{title}

: null} +
{desc}
+
+ +
+
+ {type ?

Media type

: null} + {type ?

perm_media{type}

: null} +
+
+ {date ?

Date

: null} + {date ?

today{date}

: null} +
+
+ {url ?

Link

: null} + {url ? linkLink to original URL : null} +
+
+
+
+
+ ) + } +} + +export default SourceOverlay diff --git a/src/components/SourceOverlay.jsx b/src/components/SourceOverlay.jsx deleted file mode 100644 index 5b3a254..0000000 --- a/src/components/SourceOverlay.jsx +++ /dev/null @@ -1,216 +0,0 @@ -import React from 'react' -import Img from 'react-image' -import { Player } from 'video-react' -import Md from './Md.jsx' -import Spinner from './presentational/Spinner' -import NoSource from './presentational/NoSource' -// TODO: move render functions into presentational components - -class SourceOverlay extends React.Component { - constructor () { - super() - this.state = { idx: 0 } - } - - renderImage (path) { - return ( -
-
} - unloader={} - /> -
- ) - } - - renderVideo (path) { - return ( -
- -
- ) - } - - renderText (path) { - return ( -
- } - unloader={() => this.renderError()} - /> -
- ) - } - - renderNoSupport (ext) { - return ( - - ) - } - - toMedia (path) { - let type - switch (true) { - case /\.(png|jpg)$/.test(path): - type = 'Image'; break - case /\.(mp4)$/.test(path): - type = 'Video'; break - case /\.(md)$/.test(path): - type = 'Text'; break - default: - type = 'Unknown'; break - } - return { type, path } - } - - getTypeCounts (media) { - return media.reduce( - (acc, vl) => { - acc[vl.type] += 1 - return acc - }, - { Image: 0, Video: 0, Text: 0 } - ) - } - - _renderPath (media) { - const { path, type } = media - switch (type) { - case 'Image': - return this.renderImage(path) - case 'Video': - return this.renderVideo(path) - case 'Text': - return this.renderText(path) - default: - return this.renderNoSupport(path.split('.')[1]) - } - } - - _renderCounts (counts) { - const strFor = type => - counts[type] > 0 - ? `${counts[type]} ${type.toLowerCase()}${counts[type] > 1 ? 's' : ''}` - : '' - const img = strFor('Image') - const vid = strFor('Video') - const txt = strFor('Text') - - return ( -
- {img || ''} - {(img && vid) ? `, ${vid}` : (vid || '')} - {((img || vid) && txt) ? `, ${txt}` : (txt || '')} -
- ) - } - - _renderContent (media) { - const el = document.querySelector(`.source-media-gallery`) - const shiftW = el ? el.getBoundingClientRect().width : 0 - return ( -
- {media.map((m) => this._renderPath(m))} -
- ) - } - - 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 }) - } - - _renderControls () { - const backArrow = this.state.idx !== 0 ? ( -
this.onShiftGallery(-1)} - > - - - -
- ) : null - const forwardArrow = this.state.idx < this.props.source.paths.length - 1 ? ( -
this.onShiftGallery(1)} - > - - - -
- ) : null - - if (this.props.source.paths.length > 1) { - return ( -
- {backArrow} - {forwardArrow} -
- ) - } - return ( -
- ) - } - - render () { - if (typeof (this.props.source) !== 'object') { - return this.renderError() - } - const { url, title, paths, date, type, desc } = this.props.source - const media = paths.map(this.toMedia) - - return ( -
-
e.stopPropagation()}> -
-
- -
-
{this.props.source.title.substring(0, 200)}
-
-
- {this._renderContent(media)} - {this._renderControls()} -
-
-
- {/*

{`${this.state.idx+1} / ${paths.length}`}

*/} - {title ?

{title}

: null} -
{desc}
-
- -
-
- {type ?

Media type

: null} - {type ?

perm_media{type}

: null} -
-
- {date ?

Date

: null} - {date ?

today{date}

: null} -
-
- {url ?

Link

: null} - {url ? linkLink to original URL : null} -
-
-
-
-
- ) - } -} - -export default SourceOverlay diff --git a/src/js/utilities.js b/src/js/utilities.js index 8d04788..00d9987 100644 --- a/src/js/utilities.js +++ b/src/js/utilities.js @@ -136,3 +136,18 @@ export function toggleFlagAC (flag) { } }) } + +export function selectTypeFromPath (path) { + let type + switch (true) { + case /\.(png|jpg)$/.test(path): + type = 'Image'; break + case /\.(mp4)$/.test(path): + type = 'Video'; break + case /\.(md)$/.test(path): + type = 'Text'; break + default: + type = 'Unknown'; break + } + return { type, path } +}