diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2016-11-23 11:23:32 +0100 |
---|---|---|
committer | Eugen Rochko <eugen@zeonfederated.com> | 2016-11-23 11:23:32 +0100 |
commit | 5434ad3002b95f194a013fc327f1fdcabacf649a (patch) | |
tree | 16470f4fa7b7e4a7325b777ba4e03eb11c3a3eb9 | |
parent | 0603971894a967f632020277c32a8e50ea165519 (diff) |
Add content spoilers for media in sensitive-content statuses
3 files changed, 141 insertions, 58 deletions
diff --git a/app/assets/javascripts/components/components/media_gallery.jsx b/app/assets/javascripts/components/components/media_gallery.jsx index bdb456a08..e46933f7b 100644 --- a/app/assets/javascripts/components/components/media_gallery.jsx +++ b/app/assets/javascripts/components/components/media_gallery.jsx @@ -1,9 +1,43 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; -import PureRenderMixin from 'react-addons-pure-render-mixin'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import { FormattedMessage } from 'react-intl'; + +const outerStyle = { + marginTop: '8px', + overflow: 'hidden', + width: '100%', + boxSizing: 'border-box' +}; + +const spoilerStyle = { + background: '#000', + color: '#fff', + textAlign: 'center', + height: '100%', + cursor: 'pointer' +}; + +const spoilerSpanStyle = { + display: 'block', + fontSize: '14px', + paddingTop: '45%' +}; + +const spoilerSubSpanStyle = { + fontSize: '11px', + fontWeight: '500' +}; const MediaGallery = React.createClass({ + getInitialState () { + return { + visible: false + }; + }, + propTypes: { + sensitive: React.PropTypes.bool, media: ImmutablePropTypes.list.isRequired, height: React.PropTypes.number.isRequired, onOpenMedia: React.PropTypes.func.isRequired @@ -20,69 +54,85 @@ const MediaGallery = React.createClass({ e.stopPropagation(); }, + handleOpen () { + this.setState({ visible: true }); + }, + render () { - var children = this.props.media.take(4); - var size = children.size; - - children = children.map((attachment, i) => { - let width = 50; - let height = 100; - let top = 'auto'; - let left = 'auto'; - let bottom = 'auto'; - let right = 'auto'; - - if (size === 1) { - width = 100; - } - - if (size === 4 || (size === 3 && i > 0)) { - height = 50; - } - - if (size === 2) { - if (i === 0) { - right = '2px'; - } else { - left = '2px'; - } - } else if (size === 3) { - if (i === 0) { - right = '2px'; - } else if (i > 0) { - left = '2px'; - } + const { media, sensitive } = this.props; - if (i === 1) { - bottom = '2px'; - } else if (i > 1) { - top = '2px'; - } - } else if (size === 4) { - if (i === 0 || i === 2) { - right = '2px'; + let children; + + if (sensitive && !this.state.visible) { + children = ( + <div style={spoilerStyle} onClick={this.handleOpen}> + <span style={spoilerSpanStyle}><FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /></span> + <span style={spoilerSubSpanStyle}><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span> + </div> + ); + } else { + const size = media.take(4).size; + + children = media.take(4).map((attachment, i) => { + let width = 50; + let height = 100; + let top = 'auto'; + let left = 'auto'; + let bottom = 'auto'; + let right = 'auto'; + + if (size === 1) { + width = 100; } - if (i === 1 || i === 3) { - left = '2px'; + if (size === 4 || (size === 3 && i > 0)) { + height = 50; } - if (i < 2) { - bottom = '2px'; - } else { - top = '2px'; + if (size === 2) { + if (i === 0) { + right = '2px'; + } else { + left = '2px'; + } + } else if (size === 3) { + if (i === 0) { + right = '2px'; + } else if (i > 0) { + left = '2px'; + } + + if (i === 1) { + bottom = '2px'; + } else if (i > 1) { + top = '2px'; + } + } else if (size === 4) { + if (i === 0 || i === 2) { + right = '2px'; + } + + if (i === 1 || i === 3) { + left = '2px'; + } + + if (i < 2) { + bottom = '2px'; + } else { + top = '2px'; + } } - } - return ( - <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}%` }}> - <a href={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' }} /> - </div> - ); - }); + return ( + <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}%` }}> + <a href={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' }} /> + </div> + ); + }); + } return ( - <div style={{ marginTop: '8px', overflow: 'hidden', width: '100%', height: `${this.props.height}px`, boxSizing: 'border-box' }}> + <div style={{ ...outerStyle, height: `${this.props.height}px` }}> {children} </div> ); diff --git a/app/assets/javascripts/components/components/status.jsx b/app/assets/javascripts/components/components/status.jsx index 84cd07527..bf851e5bf 100644 --- a/app/assets/javascripts/components/components/status.jsx +++ b/app/assets/javascripts/components/components/status.jsx @@ -83,9 +83,9 @@ const Status = React.createClass({ if (status.get('media_attachments').size > 0) { if (status.getIn(['media_attachments', 0, 'type']) === 'video') { - media = <VideoPlayer media={status.getIn(['media_attachments', 0])} />; + media = <VideoPlayer media={status.getIn(['media_attachments', 0])} sensitive={status.get('sensitive')} />; } else { - media = <MediaGallery media={status.get('media_attachments')} height={110} onOpenMedia={this.props.onOpenMedia} />; + media = <MediaGallery media={status.get('media_attachments')} sensitive={status.get('sensitive')} height={110} onOpenMedia={this.props.onOpenMedia} />; } } diff --git a/app/assets/javascripts/components/components/video_player.jsx b/app/assets/javascripts/components/components/video_player.jsx index 9b9b0a2e4..a789f65e4 100644 --- a/app/assets/javascripts/components/components/video_player.jsx +++ b/app/assets/javascripts/components/components/video_player.jsx @@ -1,7 +1,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PureRenderMixin from 'react-addons-pure-render-mixin'; import IconButton from './icon_button'; -import { defineMessages, injectIntl } from 'react-intl'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; const messages = defineMessages({ toggle_sound: { id: 'video_player.toggle_sound', defaultMessage: 'Toggle sound' } @@ -25,6 +25,25 @@ const muteStyle = { zIndex: '5' }; +const spoilerStyle = { + background: '#000', + color: '#fff', + textAlign: 'center', + height: '100%', + cursor: 'pointer' +}; + +const spoilerSpanStyle = { + display: 'block', + fontSize: '14px', + paddingTop: '45%' +}; + +const spoilerSubSpanStyle = { + fontSize: '11px', + fontWeight: '500' +}; + const VideoPlayer = React.createClass({ propTypes: { media: ImmutablePropTypes.map.isRequired, @@ -41,6 +60,7 @@ const VideoPlayer = React.createClass({ getInitialState () { return { + visible: false, muted: true }; }, @@ -63,8 +83,21 @@ const VideoPlayer = React.createClass({ } }, + handleOpen () { + this.setState({ visible: true }); + }, + render () { - const { media, intl, width, height } = this.props; + const { media, intl, width, height, sensitive } = this.props; + + if (sensitive && !this.state.visible) { + return ( + <div style={spoilerStyle} onClick={this.handleOpen}> + <span style={spoilerSpanStyle}><FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /></span> + <span style={spoilerSubSpanStyle}><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span> + </div> + ); + } return ( <div style={{ cursor: 'default', marginTop: '8px', overflow: 'hidden', width: `${width}px`, height: `${height}px`, boxSizing: 'border-box', background: '#000', position: 'relative' }}> |