Skip to content

Instantly share code, notes, and snippets.

@selbekk
Created April 11, 2017 11:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save selbekk/64d519b320d316ac0006cf6bdd398836 to your computer and use it in GitHub Desktop.
Save selbekk/64d519b320d316ac0006cf6bdd398836 to your computer and use it in GitHub Desktop.
Reecap showcase
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import classNames from 'classnames';
import EventImage from '~/components/EventImage';
import Logo from '~/components/Logo';
import Spinner from '~/components/Spinner';
import * as dispatchers from '~/dispatchers';
import '~/scss/components/ShowcaseList.scss';
const randomize = () => (Math.random() * 2) - 1;
class ShowcasePage extends Component {
constructor() {
super();
const aspectRatio = window.innerWidth / window.innerHeight;
const numberOfImages = aspectRatio < 1.5 ? 12 : 8;
this.state = {
indexes: Array.from({ length: numberOfImages }, (v, k) => k).sort(randomize),
queue: [],
selection: [],
showOverlay: false,
};
this.updateImages = this.updateImages.bind(this);
this.showOverlay = this.showOverlay.bind(this);
}
componentDidMount() {
const { match, event, fetchEvent } = this.props;
if (!event.populated) {
fetchEvent(match.params.pin);
}
this._interval = setInterval(this.updateImages, 2000);
this._overlayInterval = setInterval(this.showOverlay, 60 * 1000);
this.updateImages();
this.showOverlay();
}
componentWillUpdate(nextProps) {
const { event } = this.props;
const { queue, indexes } = this.state;
const nextImages = nextProps.event.images;
const diff = nextImages.length - event.images.length;
if (diff > 0) {
this.setState({
queue: [...nextImages.slice(0, diff), ...queue],
});
}
if (!event.images.length && nextImages.length) {
const selection = [];
while (selection.length < indexes.length) {
selection.push(
nextImages[Math.floor(Math.random() * nextImages.length)],
);
}
this.setState({ selection });
}
}
componentWillUnmount() {
clearInterval(this._interval);
clearInterval(this._overlayInterval);
}
showOverlay() {
this.setState({ showOverlay: true });
setTimeout(() => this.setState({ showOverlay: false }), 5000);
}
updateImages() {
const { event } = this.props;
const { selection, queue, indexes } = this.state;
if (!event.images.length) {
return; // Initial load, nothing to shuffle
}
const updatedSelection = [...selection];
const [indexToChange, ...remainingIndexes] = indexes;
const [nextImage, ...remainingQueue] = queue;
updatedSelection[indexToChange] = nextImage;
this.setState({
indexes: [...remainingIndexes, indexToChange],
queue: [...remainingQueue, nextImage],
selection: updatedSelection,
});
}
render() {
const { event, match } = this.props;
const { selection, showOverlay } = this.state;
if (!event) {
return (
<div className="page showcase-view">
<Spinner />
</div>
);
}
return (
<div className="page showcase-view">
<ul className="showcase-list">
{selection.map((image, i) =>
<EventImage
key={`${image.key}-${i}`}
id={image.key}
pin={event.pin}
url={image.url}
/>,
)}
</ul>
<div className="showcase-view-details">
<div className="showcase-view-details__pin">
reecap.it/<strong>{match.params.pin}</strong>
</div>
<div className="showcase-view-details__logo">
<Logo color="#ffffff" blur={false} />
</div>
</div>
<div
className={classNames(
'showcase-overlay',
{ 'showcase-overlay--visible': showOverlay },
)}
>
<div className="showcase-overlay__inner">
<Logo color="#ffffff" blur={false} />
<p className="lead">
{'Join the fun @ '}
<strong>reecap.it/{match.params.pin}</strong>
</p>
</div>
</div>
</div>
);
}
}
ShowcasePage.propTypes = {
event: PropTypes.shape({}),
fetchEvent: PropTypes.func,
match: PropTypes.shape({
params: PropTypes.shape({
pin: PropTypes.string,
}),
}),
};
const mapStateToProps = state => ({
event: state.currentEvent,
});
export default connect(mapStateToProps, dispatchers)(ShowcasePage);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment