before. In the API, attachments now can be either image, video or gifv. Gifv is to be treated like images in terms of behaviour, but are videos by file type.
		
			
				
	
	
		
			171 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { connect } from 'react-redux';
 | |
| import {
 | |
|   closeModal,
 | |
|   decreaseIndexInModal,
 | |
|   increaseIndexInModal
 | |
| } from '../../../actions/modal';
 | |
| import Lightbox from '../../../components/lightbox';
 | |
| import ImageLoader from 'react-imageloader';
 | |
| import LoadingIndicator from '../../../components/loading_indicator';
 | |
| import PureRenderMixin from 'react-addons-pure-render-mixin';
 | |
| import ImmutablePropTypes from 'react-immutable-proptypes';
 | |
| import ExtendedVideoPlayer from '../../../components/extended_video_player';
 | |
| 
 | |
| const mapStateToProps = state => ({
 | |
|   media: state.getIn(['modal', 'media']),
 | |
|   index: state.getIn(['modal', 'index']),
 | |
|   isVisible: state.getIn(['modal', 'open'])
 | |
| });
 | |
| 
 | |
| const mapDispatchToProps = dispatch => ({
 | |
|   onCloseClicked () {
 | |
|     dispatch(closeModal());
 | |
|   },
 | |
| 
 | |
|   onOverlayClicked () {
 | |
|     dispatch(closeModal());
 | |
|   },
 | |
| 
 | |
|   onNextClicked () {
 | |
|     dispatch(increaseIndexInModal());
 | |
|   },
 | |
| 
 | |
|   onPrevClicked () {
 | |
|     dispatch(decreaseIndexInModal());
 | |
|   }
 | |
| });
 | |
| 
 | |
| const imageStyle = {
 | |
|   display: 'block',
 | |
|   maxWidth: '80vw',
 | |
|   maxHeight: '80vh'
 | |
| };
 | |
| 
 | |
| const loadingStyle = {
 | |
|   width: '400px',
 | |
|   paddingBottom: '120px'
 | |
| };
 | |
| 
 | |
| const preloader = () => (
 | |
|   <div className='modal-container--preloader' style={loadingStyle}>
 | |
|     <LoadingIndicator />
 | |
|   </div>
 | |
| );
 | |
| 
 | |
| const leftNavStyle = {
 | |
|   position: 'absolute',
 | |
|   background: 'rgba(0, 0, 0, 0.5)',
 | |
|   padding: '30px 15px',
 | |
|   cursor: 'pointer',
 | |
|   fontSize: '24px',
 | |
|   top: '0',
 | |
|   left: '-61px',
 | |
|   boxSizing: 'border-box',
 | |
|   height: '100%',
 | |
|   display: 'flex',
 | |
|   alignItems: 'center'
 | |
| };
 | |
| 
 | |
| const rightNavStyle = {
 | |
|   position: 'absolute',
 | |
|   background: 'rgba(0, 0, 0, 0.5)',
 | |
|   padding: '30px 15px',
 | |
|   cursor: 'pointer',
 | |
|   fontSize: '24px',
 | |
|   top: '0',
 | |
|   right: '-61px',
 | |
|   boxSizing: 'border-box',
 | |
|   height: '100%',
 | |
|   display: 'flex',
 | |
|   alignItems: 'center'
 | |
| };
 | |
| 
 | |
| const Modal = React.createClass({
 | |
| 
 | |
|   propTypes: {
 | |
|     media: ImmutablePropTypes.list,
 | |
|     index: React.PropTypes.number.isRequired,
 | |
|     isVisible: React.PropTypes.bool,
 | |
|     onCloseClicked: React.PropTypes.func,
 | |
|     onOverlayClicked: React.PropTypes.func,
 | |
|     onNextClicked: React.PropTypes.func,
 | |
|     onPrevClicked: React.PropTypes.func
 | |
|   },
 | |
| 
 | |
|   mixins: [PureRenderMixin],
 | |
| 
 | |
|   handleNextClick () {
 | |
|     this.props.onNextClicked();
 | |
|   },
 | |
| 
 | |
|   handlePrevClick () {
 | |
|     this.props.onPrevClicked();
 | |
|   },
 | |
| 
 | |
|   componentDidMount () {
 | |
|     this._listener = e => {
 | |
|       if (!this.props.isVisible) {
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|       switch(e.key) {
 | |
|       case 'ArrowLeft':
 | |
|         this.props.onPrevClicked();
 | |
|         break;
 | |
|       case 'ArrowRight':
 | |
|         this.props.onNextClicked();
 | |
|         break;
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     window.addEventListener('keyup', this._listener);
 | |
|   },
 | |
| 
 | |
|   componentWillUnmount () {
 | |
|     window.removeEventListener('keyup', this._listener);
 | |
|   },
 | |
| 
 | |
|   render () {
 | |
|     const { media, index, ...other } = this.props;
 | |
| 
 | |
|     if (!media) {
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     const attachment = media.get(index);
 | |
|     const url = attachment.get('url');
 | |
| 
 | |
|     let leftNav, rightNav, content;
 | |
| 
 | |
|     leftNav = rightNav = content = '';
 | |
| 
 | |
|     if (media.size > 1) {
 | |
|       leftNav  = <div style={leftNavStyle} className='modal-container--nav' onClick={this.handlePrevClick}><i className='fa fa-fw fa-chevron-left' /></div>;
 | |
|       rightNav = <div style={rightNavStyle} className='modal-container--nav' onClick={this.handleNextClick}><i className='fa fa-fw fa-chevron-right' /></div>;
 | |
|     }
 | |
| 
 | |
|     if (attachment.get('type') === 'image') {
 | |
|       content = (
 | |
|         <ImageLoader
 | |
|           src={url}
 | |
|           preloader={preloader}
 | |
|           imgProps={{ style: imageStyle }}
 | |
|         />
 | |
|       );
 | |
|     } else if (attachment.get('type') === 'gifv') {
 | |
|       content = <ExtendedVideoPlayer src={url} />;
 | |
|     }
 | |
| 
 | |
|     return (
 | |
|       <Lightbox {...other}>
 | |
|         {leftNav}
 | |
|         {content}
 | |
|         {rightNav}
 | |
|       </Lightbox>
 | |
|     );
 | |
|   }
 | |
| 
 | |
| });
 | |
| 
 | |
| export default connect(mapStateToProps, mapDispatchToProps)(Modal);
 |