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.

147 lines
3.6 KiB

  1. import ImmutablePropTypes from 'react-immutable-proptypes';
  2. import PureRenderMixin from 'react-addons-pure-render-mixin';
  3. import { FormattedMessage } from 'react-intl';
  4. const outerStyle = {
  5. marginTop: '8px',
  6. overflow: 'hidden',
  7. width: '100%',
  8. boxSizing: 'border-box'
  9. };
  10. const spoilerStyle = {
  11. background: '#000',
  12. color: '#fff',
  13. textAlign: 'center',
  14. height: '100%',
  15. cursor: 'pointer',
  16. display: 'flex',
  17. alignItems: 'center',
  18. justifyContent: 'center',
  19. flexDirection: 'column'
  20. };
  21. const spoilerSpanStyle = {
  22. display: 'block',
  23. fontSize: '14px',
  24. };
  25. const spoilerSubSpanStyle = {
  26. display: 'block',
  27. fontSize: '11px',
  28. fontWeight: '500'
  29. };
  30. const MediaGallery = React.createClass({
  31. getInitialState () {
  32. return {
  33. visible: false
  34. };
  35. },
  36. propTypes: {
  37. sensitive: React.PropTypes.bool,
  38. media: ImmutablePropTypes.list.isRequired,
  39. height: React.PropTypes.number.isRequired,
  40. onOpenMedia: React.PropTypes.func.isRequired
  41. },
  42. mixins: [PureRenderMixin],
  43. handleClick (url, e) {
  44. if (e.button === 0) {
  45. e.preventDefault();
  46. this.props.onOpenMedia(url);
  47. }
  48. e.stopPropagation();
  49. },
  50. handleOpen () {
  51. this.setState({ visible: true });
  52. },
  53. render () {
  54. const { media, sensitive } = this.props;
  55. let children;
  56. if (sensitive && !this.state.visible) {
  57. children = (
  58. <div style={spoilerStyle} onClick={this.handleOpen}>
  59. <span style={spoilerSpanStyle}><FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /></span>
  60. <span style={spoilerSubSpanStyle}><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
  61. </div>
  62. );
  63. } else {
  64. const size = media.take(4).size;
  65. children = media.take(4).map((attachment, i) => {
  66. let width = 50;
  67. let height = 100;
  68. let top = 'auto';
  69. let left = 'auto';
  70. let bottom = 'auto';
  71. let right = 'auto';
  72. if (size === 1) {
  73. width = 100;
  74. }
  75. if (size === 4 || (size === 3 && i > 0)) {
  76. height = 50;
  77. }
  78. if (size === 2) {
  79. if (i === 0) {
  80. right = '2px';
  81. } else {
  82. left = '2px';
  83. }
  84. } else if (size === 3) {
  85. if (i === 0) {
  86. right = '2px';
  87. } else if (i > 0) {
  88. left = '2px';
  89. }
  90. if (i === 1) {
  91. bottom = '2px';
  92. } else if (i > 1) {
  93. top = '2px';
  94. }
  95. } else if (size === 4) {
  96. if (i === 0 || i === 2) {
  97. right = '2px';
  98. }
  99. if (i === 1 || i === 3) {
  100. left = '2px';
  101. }
  102. if (i < 2) {
  103. bottom = '2px';
  104. } else {
  105. top = '2px';
  106. }
  107. }
  108. return (
  109. <div key={attachment.get('id')} style={{ boxSizing: 'border-box', position: 'relative', left: left, top: top, right: right, bottom: bottom, float: 'left', border: 'none', display: 'block', width: `${width}%`, height: `${height}%` }}>
  110. <a href={attachment.get('remote_url') ? attachment.get('remote_url') : attachment.get('url')} onClick={this.handleClick.bind(this, attachment.get('url'))} target='_blank' style={{ display: 'block', width: '100%', height: '100%', background: `url(${attachment.get('preview_url')}) no-repeat center`, textDecoration: 'none', backgroundSize: 'cover', cursor: 'zoom-in' }} />
  111. </div>
  112. );
  113. });
  114. }
  115. return (
  116. <div style={{ ...outerStyle, height: `${this.props.height}px` }}>
  117. {children}
  118. </div>
  119. );
  120. }
  121. });
  122. export default MediaGallery;