Skip to content
Snippets Groups Projects
Commit 2f079573 authored by Eugen Rochko's avatar Eugen Rochko Committed by GitHub
Browse files

In detail status view, display attachment uncropped if there's only one (#5054)

* In detail status view, display attachment uncropped if there's only one

* Make media spoiler the size of the media it hides, enable on static
parent b2820c39
No related branches found
No related tags found
No related merge requests found
...@@ -4,6 +4,8 @@ import PropTypes from 'prop-types'; ...@@ -4,6 +4,8 @@ import PropTypes from 'prop-types';
import IconButton from './icon_button'; import IconButton from './icon_button';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { isIOS } from '../is_mobile'; import { isIOS } from '../is_mobile';
import classNames from 'classnames';
import sizeMe from 'react-sizeme';
const messages = defineMessages({ const messages = defineMessages({
toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' }, toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' },
...@@ -17,6 +19,7 @@ class Item extends React.PureComponent { ...@@ -17,6 +19,7 @@ class Item extends React.PureComponent {
static propTypes = { static propTypes = {
attachment: ImmutablePropTypes.map.isRequired, attachment: ImmutablePropTypes.map.isRequired,
standalone: PropTypes.bool,
index: PropTypes.number.isRequired, index: PropTypes.number.isRequired,
size: PropTypes.number.isRequired, size: PropTypes.number.isRequired,
onClick: PropTypes.func.isRequired, onClick: PropTypes.func.isRequired,
...@@ -25,6 +28,9 @@ class Item extends React.PureComponent { ...@@ -25,6 +28,9 @@ class Item extends React.PureComponent {
static defaultProps = { static defaultProps = {
autoPlayGif: false, autoPlayGif: false,
standalone: false,
index: 0,
size: 1,
}; };
handleMouseEnter = (e) => { handleMouseEnter = (e) => {
...@@ -57,7 +63,7 @@ class Item extends React.PureComponent { ...@@ -57,7 +63,7 @@ class Item extends React.PureComponent {
} }
render () { render () {
const { attachment, index, size } = this.props; const { attachment, index, size, standalone } = this.props;
let width = 50; let width = 50;
let height = 100; let height = 100;
...@@ -136,7 +142,7 @@ class Item extends React.PureComponent { ...@@ -136,7 +142,7 @@ class Item extends React.PureComponent {
const autoPlay = !isIOS() && this.props.autoPlayGif; const autoPlay = !isIOS() && this.props.autoPlayGif;
thumbnail = ( thumbnail = (
<div className={`media-gallery__gifv ${autoPlay ? 'autoplay' : ''}`}> <div className={classNames('media-gallery__gifv', { autoplay: autoPlay })}>
<video <video
className='media-gallery__item-gifv-thumbnail' className='media-gallery__item-gifv-thumbnail'
role='application' role='application'
...@@ -154,8 +160,10 @@ class Item extends React.PureComponent { ...@@ -154,8 +160,10 @@ class Item extends React.PureComponent {
); );
} }
const style = standalone ? {} : { left, top, right, bottom, width: `${width}%`, height: `${height}%` };
return ( return (
<div className='media-gallery__item' key={attachment.get('id')} style={{ left: left, top: top, right: right, bottom: bottom, width: `${width}%`, height: `${height}%` }}> <div className={classNames('media-gallery__item', { standalone })} key={attachment.get('id')} style={style}>
{thumbnail} {thumbnail}
</div> </div>
); );
...@@ -164,11 +172,14 @@ class Item extends React.PureComponent { ...@@ -164,11 +172,14 @@ class Item extends React.PureComponent {
} }
@injectIntl @injectIntl
@sizeMe({})
export default class MediaGallery extends React.PureComponent { export default class MediaGallery extends React.PureComponent {
static propTypes = { static propTypes = {
sensitive: PropTypes.bool, sensitive: PropTypes.bool,
standalone: PropTypes.bool,
media: ImmutablePropTypes.list.isRequired, media: ImmutablePropTypes.list.isRequired,
size: PropTypes.object,
height: PropTypes.number.isRequired, height: PropTypes.number.isRequired,
onOpenMedia: PropTypes.func.isRequired, onOpenMedia: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
...@@ -177,6 +188,7 @@ export default class MediaGallery extends React.PureComponent { ...@@ -177,6 +188,7 @@ export default class MediaGallery extends React.PureComponent {
static defaultProps = { static defaultProps = {
autoPlayGif: false, autoPlayGif: false,
standalone: false,
}; };
state = { state = {
...@@ -198,10 +210,19 @@ export default class MediaGallery extends React.PureComponent { ...@@ -198,10 +210,19 @@ export default class MediaGallery extends React.PureComponent {
} }
render () { render () {
const { media, intl, sensitive } = this.props; const { media, intl, sensitive, height, standalone, size } = this.props;
let children; let children;
const standaloneEligible = standalone && size.width && media.size === 1 && media.getIn([0, 'meta', 'small', 'aspect']);
const style = {};
if (standaloneEligible) {
style.height = size.width / media.getIn([0, 'meta', 'small', 'aspect']);
} else {
style.height = height;
}
if (!this.state.visible) { if (!this.state.visible) {
let warning; let warning;
...@@ -212,19 +233,24 @@ export default class MediaGallery extends React.PureComponent { ...@@ -212,19 +233,24 @@ export default class MediaGallery extends React.PureComponent {
} }
children = ( children = (
<button className='media-spoiler' onClick={this.handleOpen}> <button className='media-spoiler' onClick={this.handleOpen} style={style}>
<span className='media-spoiler__warning'>{warning}</span> <span className='media-spoiler__warning'>{warning}</span>
<span className='media-spoiler__trigger'><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span> <span className='media-spoiler__trigger'><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
</button> </button>
); );
} else { } else {
const size = media.take(4).size; const size = media.take(4).size;
children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} autoPlayGif={this.props.autoPlayGif} index={i} size={size} />);
if (standaloneEligible) {
children = <Item standalone onClick={this.handleClick} attachment={media.get(0)} autoPlayGif={this.props.autoPlayGif} />;
} else {
children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} autoPlayGif={this.props.autoPlayGif} index={i} size={size} />);
}
} }
return ( return (
<div className='media-gallery' style={{ height: `${this.props.height}px` }}> <div className='media-gallery' style={style}>
<div className={`spoiler-button ${this.state.visible ? 'spoiler-button--visible' : ''}`}> <div className={classNames('spoiler-button', { 'spoiler-button--visible': this.state.visible })}>
<IconButton title={intl.formatMessage(messages.toggle_visible)} icon={this.state.visible ? 'eye' : 'eye-slash'} overlay onClick={this.handleOpen} /> <IconButton title={intl.formatMessage(messages.toggle_visible)} icon={this.state.visible ? 'eye' : 'eye-slash'} overlay onClick={this.handleOpen} />
</div> </div>
......
...@@ -61,7 +61,16 @@ export default class DetailedStatus extends ImmutablePureComponent { ...@@ -61,7 +61,16 @@ export default class DetailedStatus extends ImmutablePureComponent {
/> />
); );
} else { } else {
media = <MediaGallery sensitive={status.get('sensitive')} media={status.get('media_attachments')} height={300} onOpenMedia={this.props.onOpenMedia} autoPlayGif={this.props.autoPlayGif} />; media = (
<MediaGallery
standalone
sensitive={status.get('sensitive')}
media={status.get('media_attachments')}
height={300}
onOpenMedia={this.props.onOpenMedia}
autoPlayGif={this.props.autoPlayGif}
/>
);
} }
} else if (status.get('spoiler_text').length === 0) { } else if (status.get('spoiler_text').length === 0) {
media = <CardContainer statusId={status.get('id')} />; media = <CardContainer statusId={status.get('id')} />;
......
...@@ -3645,6 +3645,12 @@ button.icon-button.active i.fa-retweet { ...@@ -3645,6 +3645,12 @@ button.icon-button.active i.fa-retweet {
display: block; display: block;
float: left; float: left;
position: relative; position: relative;
&.standalone {
.media-gallery__item-gifv-thumbnail {
transform: none;
}
}
} }
.media-gallery__item-thumbnail { .media-gallery__item-thumbnail {
...@@ -3652,6 +3658,7 @@ button.icon-button.active i.fa-retweet { ...@@ -3652,6 +3658,7 @@ button.icon-button.active i.fa-retweet {
display: block; display: block;
text-decoration: none; text-decoration: none;
height: 100%; height: 100%;
line-height: 0;
&, &,
img { img {
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
- video = status.media_attachments.first - video = status.media_attachments.first
%div{ data: { component: 'Video', props: Oj.dump(src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive?, width: 670, height: 380) }} %div{ data: { component: 'Video', props: Oj.dump(src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive?, width: 670, height: 380) }}
- else - else
%div{ data: { component: 'MediaGallery', props: Oj.dump(height: 380, sensitive: status.sensitive?, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }) }} %div{ data: { component: 'MediaGallery', props: Oj.dump(height: 380, sensitive: status.sensitive?, standalone: true, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }) }}
- elsif status.preview_cards.first - elsif status.preview_cards.first
%div{ data: { component: 'Card', props: Oj.dump('maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_cards.first, serializer: REST::PreviewCardSerializer).as_json) }} %div{ data: { component: 'Card', props: Oj.dump('maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_cards.first, serializer: REST::PreviewCardSerializer).as_json) }}
......
...@@ -982,6 +982,10 @@ base64-js@^1.0.2: ...@@ -982,6 +982,10 @@ base64-js@^1.0.2:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886"
batch-processor@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/batch-processor/-/batch-processor-1.0.0.tgz#75c95c32b748e0850d10c2b168f6bdbe9891ace8"
batch@0.6.1: batch@0.6.1:
version "0.6.1" version "0.6.1"
resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
...@@ -2053,6 +2057,12 @@ electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.14: ...@@ -2053,6 +2057,12 @@ electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.14:
version "1.3.15" version "1.3.15"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.15.tgz#08397934891cbcfaebbd18b82a95b5a481138369" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.15.tgz#08397934891cbcfaebbd18b82a95b5a481138369"
element-resize-detector@^1.1.12:
version "1.1.12"
resolved "https://registry.yarnpkg.com/element-resize-detector/-/element-resize-detector-1.1.12.tgz#8b3fd6eedda17f9c00b360a0ea2df9927ae80ba2"
dependencies:
batch-processor "^1.0.0"
elliptic@^6.0.0: elliptic@^6.0.0:
version "6.4.0" version "6.4.0"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df"
...@@ -5413,6 +5423,14 @@ react-simple-dropdown@^3.0.0: ...@@ -5413,6 +5423,14 @@ react-simple-dropdown@^3.0.0:
classnames "^2.1.2" classnames "^2.1.2"
prop-types "^15.5.8" prop-types "^15.5.8"
react-sizeme@^2.3.5:
version "2.3.5"
resolved "https://registry.yarnpkg.com/react-sizeme/-/react-sizeme-2.3.5.tgz#f14c0a15f9b24d7b8b6f196871b0af19aa01a422"
dependencies:
element-resize-detector "^1.1.12"
invariant "^2.2.2"
lodash "^4.17.4"
react-swipeable-views-core@^0.11.1: react-swipeable-views-core@^0.11.1:
version "0.11.1" version "0.11.1"
resolved "https://registry.yarnpkg.com/react-swipeable-views-core/-/react-swipeable-views-core-0.11.1.tgz#61d046799f90725bbf91a0eb3abcab805c774cac" resolved "https://registry.yarnpkg.com/react-swipeable-views-core/-/react-swipeable-views-core-0.11.1.tgz#61d046799f90725bbf91a0eb3abcab805c774cac"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment