You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
3.8 KiB

  1. import { connect } from 'react-redux';
  2. import {
  3. closeModal,
  4. decreaseIndexInModal,
  5. increaseIndexInModal
  6. } from '../../../actions/modal';
  7. import Lightbox from '../../../components/lightbox';
  8. import ImageLoader from 'react-imageloader';
  9. import LoadingIndicator from '../../../components/loading_indicator';
  10. import PureRenderMixin from 'react-addons-pure-render-mixin';
  11. import ImmutablePropTypes from 'react-immutable-proptypes';
  12. import ExtendedVideoPlayer from '../../../components/extended_video_player';
  13. const mapStateToProps = state => ({
  14. media: state.getIn(['modal', 'media']),
  15. index: state.getIn(['modal', 'index']),
  16. isVisible: state.getIn(['modal', 'open'])
  17. });
  18. const mapDispatchToProps = dispatch => ({
  19. onCloseClicked () {
  20. dispatch(closeModal());
  21. },
  22. onOverlayClicked () {
  23. dispatch(closeModal());
  24. },
  25. onNextClicked () {
  26. dispatch(increaseIndexInModal());
  27. },
  28. onPrevClicked () {
  29. dispatch(decreaseIndexInModal());
  30. }
  31. });
  32. const imageStyle = {
  33. display: 'block',
  34. maxWidth: '80vw',
  35. maxHeight: '80vh'
  36. };
  37. const loadingStyle = {
  38. width: '400px',
  39. paddingBottom: '120px'
  40. };
  41. const preloader = () => (
  42. <div className='modal-container--preloader' style={loadingStyle}>
  43. <LoadingIndicator />
  44. </div>
  45. );
  46. const leftNavStyle = {
  47. position: 'absolute',
  48. background: 'rgba(0, 0, 0, 0.5)',
  49. padding: '30px 15px',
  50. cursor: 'pointer',
  51. fontSize: '24px',
  52. top: '0',
  53. left: '-61px',
  54. boxSizing: 'border-box',
  55. height: '100%',
  56. display: 'flex',
  57. alignItems: 'center'
  58. };
  59. const rightNavStyle = {
  60. position: 'absolute',
  61. background: 'rgba(0, 0, 0, 0.5)',
  62. padding: '30px 15px',
  63. cursor: 'pointer',
  64. fontSize: '24px',
  65. top: '0',
  66. right: '-61px',
  67. boxSizing: 'border-box',
  68. height: '100%',
  69. display: 'flex',
  70. alignItems: 'center'
  71. };
  72. const Modal = React.createClass({
  73. propTypes: {
  74. media: ImmutablePropTypes.list,
  75. index: React.PropTypes.number.isRequired,
  76. isVisible: React.PropTypes.bool,
  77. onCloseClicked: React.PropTypes.func,
  78. onOverlayClicked: React.PropTypes.func,
  79. onNextClicked: React.PropTypes.func,
  80. onPrevClicked: React.PropTypes.func
  81. },
  82. mixins: [PureRenderMixin],
  83. handleNextClick () {
  84. this.props.onNextClicked();
  85. },
  86. handlePrevClick () {
  87. this.props.onPrevClicked();
  88. },
  89. componentDidMount () {
  90. this._listener = e => {
  91. if (!this.props.isVisible) {
  92. return;
  93. }
  94. switch(e.key) {
  95. case 'ArrowLeft':
  96. this.props.onPrevClicked();
  97. break;
  98. case 'ArrowRight':
  99. this.props.onNextClicked();
  100. break;
  101. }
  102. };
  103. window.addEventListener('keyup', this._listener);
  104. },
  105. componentWillUnmount () {
  106. window.removeEventListener('keyup', this._listener);
  107. },
  108. render () {
  109. const { media, index, ...other } = this.props;
  110. if (!media) {
  111. return null;
  112. }
  113. const attachment = media.get(index);
  114. const url = attachment.get('url');
  115. let leftNav, rightNav, content;
  116. leftNav = rightNav = content = '';
  117. if (media.size > 1) {
  118. leftNav = <div style={leftNavStyle} className='modal-container--nav' onClick={this.handlePrevClick}><i className='fa fa-fw fa-chevron-left' /></div>;
  119. rightNav = <div style={rightNavStyle} className='modal-container--nav' onClick={this.handleNextClick}><i className='fa fa-fw fa-chevron-right' /></div>;
  120. }
  121. if (attachment.get('type') === 'image') {
  122. content = (
  123. <ImageLoader
  124. src={url}
  125. preloader={preloader}
  126. imgProps={{ style: imageStyle }}
  127. />
  128. );
  129. } else if (attachment.get('type') === 'gifv') {
  130. content = <ExtendedVideoPlayer src={url} />;
  131. }
  132. return (
  133. <Lightbox {...other}>
  134. {leftNav}
  135. {content}
  136. {rightNav}
  137. </Lightbox>
  138. );
  139. }
  140. });
  141. export default connect(mapStateToProps, mapDispatchToProps)(Modal);