闭社主体 forked from https://github.com/tootsuite/mastodon
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.

162 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. width: '400px',
  38. paddingBottom: '120px'
  39. };
  40. const preloader = () => (
  41. <div className='modal-container--preloader' style={loadingStyle}>
  42. <LoadingIndicator />
  43. </div>
  44. );
  45. const leftNavStyle = {
  46. position: 'absolute',
  47. background: 'rgba(0, 0, 0, 0.5)',
  48. padding: '30px 15px',
  49. cursor: 'pointer',
  50. fontSize: '24px',
  51. top: '0',
  52. left: '-61px',
  53. boxSizing: 'border-box',
  54. height: '100%',
  55. display: 'flex',
  56. alignItems: 'center'
  57. };
  58. const rightNavStyle = {
  59. position: 'absolute',
  60. background: 'rgba(0, 0, 0, 0.5)',
  61. padding: '30px 15px',
  62. cursor: 'pointer',
  63. fontSize: '24px',
  64. top: '0',
  65. right: '-61px',
  66. boxSizing: 'border-box',
  67. height: '100%',
  68. display: 'flex',
  69. alignItems: 'center'
  70. };
  71. const Modal = React.createClass({
  72. propTypes: {
  73. media: ImmutablePropTypes.list,
  74. index: React.PropTypes.number.isRequired,
  75. isVisible: React.PropTypes.bool,
  76. onCloseClicked: React.PropTypes.func,
  77. onOverlayClicked: React.PropTypes.func,
  78. onNextClicked: React.PropTypes.func,
  79. onPrevClicked: React.PropTypes.func
  80. },
  81. mixins: [PureRenderMixin],
  82. handleNextClick () {
  83. this.props.onNextClicked();
  84. },
  85. handlePrevClick () {
  86. this.props.onPrevClicked();
  87. },
  88. componentDidMount () {
  89. this._listener = e => {
  90. if (!this.props.isVisible) {
  91. return;
  92. }
  93. switch(e.key) {
  94. case 'ArrowLeft':
  95. this.props.onPrevClicked();
  96. break;
  97. case 'ArrowRight':
  98. this.props.onNextClicked();
  99. break;
  100. }
  101. };
  102. window.addEventListener('keyup', this._listener);
  103. },
  104. componentWillUnmount () {
  105. window.removeEventListener('keyup', this._listener);
  106. },
  107. render () {
  108. const { media, index, ...other } = this.props;
  109. if (!media) {
  110. return null;
  111. }
  112. const url = media.get(index).get('url');
  113. let leftNav, rightNav;
  114. leftNav = rightNav = '';
  115. if (media.size > 1) {
  116. leftNav = <div style={leftNavStyle} className='modal-container--nav' onClick={this.handlePrevClick}><i className='fa fa-fw fa-chevron-left' /></div>;
  117. rightNav = <div style={rightNavStyle} className='modal-container--nav' onClick={this.handleNextClick}><i className='fa fa-fw fa-chevron-right' /></div>;
  118. }
  119. return (
  120. <Lightbox {...other}>
  121. {leftNav}
  122. <ImageLoader
  123. src={url}
  124. preloader={preloader}
  125. imgProps={{ style: imageStyle }}
  126. />
  127. {rightNav}
  128. </Lightbox>
  129. );
  130. }
  131. });
  132. export default connect(mapStateToProps, mapDispatchToProps)(Modal);