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