Many improvements to images in collapsed toots

- Now works on detailed and static pages
- Fixed bug with nested CW / Sensitive Media
- Now apparent which toots contain media
This commit is contained in:
kibigo! 2017-06-29 23:31:22 -07:00
parent 54c1f56c9a
commit 6839ee390f
8 changed files with 75 additions and 54 deletions

View File

@ -152,6 +152,7 @@ export default class Status extends ImmutablePureComponent {
render () { render () {
let media = null; let media = null;
let mediaIcon = null;
let statusAvatar; let statusAvatar;
// Exclude intersectionObserverWrapper from `other` variable // Exclude intersectionObserverWrapper from `other` variable
@ -198,8 +199,10 @@ export default class Status extends ImmutablePureComponent {
} else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
media = <VideoPlayer media={status.getIn(['media_attachments', 0])} sensitive={status.get('sensitive')} onOpenVideo={this.props.onOpenVideo} />; media = <VideoPlayer media={status.getIn(['media_attachments', 0])} sensitive={status.get('sensitive')} onOpenVideo={this.props.onOpenVideo} />;
mediaIcon = 'video-camera';
} else { } else {
media = <MediaGallery media={status.get('media_attachments')} sensitive={status.get('sensitive')} height={110} onOpenMedia={this.props.onOpenMedia} autoPlayGif={this.props.autoPlayGif} />; media = <MediaGallery media={status.get('media_attachments')} sensitive={status.get('sensitive')} height={110} onOpenMedia={this.props.onOpenMedia} autoPlayGif={this.props.autoPlayGif} />;
mediaIcon = 'picture-o';
} }
} }
@ -223,7 +226,7 @@ export default class Status extends ImmutablePureComponent {
</a> </a>
</div> </div>
<StatusContent status={status} onClick={this.handleClick} expanded={isExpanded} onExpandedToggle={this.handleExpandedToggle} onHeightUpdate={this.saveHeight}> <StatusContent status={status} mediaIcon={mediaIcon} onClick={this.handleClick} expanded={isExpanded} onExpandedToggle={this.handleExpandedToggle} onHeightUpdate={this.saveHeight}>
{media} {media}

View File

@ -19,6 +19,7 @@ export default class StatusContent extends React.PureComponent {
onExpandedToggle: PropTypes.func, onExpandedToggle: PropTypes.func,
onHeightUpdate: PropTypes.func, onHeightUpdate: PropTypes.func,
onClick: PropTypes.func, onClick: PropTypes.func,
mediaIcon: PropTypes.string,
children: PropTypes.element, children: PropTypes.element,
}; };
@ -108,7 +109,7 @@ export default class StatusContent extends React.PureComponent {
} }
render () { render () {
const { status, children } = this.props; const { status, children, mediaIcon } = this.props;
const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden; const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden;
@ -129,15 +130,19 @@ export default class StatusContent extends React.PureComponent {
</Permalink> </Permalink>
)).reduce((aggregate, item) => [...aggregate, item, ' '], []); )).reduce((aggregate, item) => [...aggregate, item, ' '], []);
const toggleText = hidden ? <FormattedMessage id='status.show_more' defaultMessage='Show more' /> : <FormattedMessage id='status.show_less' defaultMessage='Show less' />; const toggleText = hidden ? [<FormattedMessage id='status.show_more' defaultMessage='Show more' key='0' />, mediaIcon ? <i className={`fa fa-fw fa-${mediaIcon} status__content__spoiler-icon`} aria-hidden='true' key='1' /> : null] : [<FormattedMessage id='status.show_less' defaultMessage='Show less' key='0' />];
if (hidden) { if (hidden) {
mentionsPlaceholder = <div>{mentionLinks}</div>; mentionsPlaceholder = <div>{mentionLinks}</div>;
} }
return ( return (
<div className='status__content status__content--with-action' ref={this.setRef} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}> <div className='status__content status__content--with-action' ref={this.setRef}>
<p style={{ marginBottom: hidden && status.get('mentions').isEmpty() ? '0px' : null }}> <p
style={{ marginBottom: hidden && status.get('mentions').isEmpty() ? '0px' : null }}
onMouseDown={this.handleMouseDown}
onMouseUp={this.handleMouseUp}
>
<span dangerouslySetInnerHTML={spoilerContent} /> <span dangerouslySetInnerHTML={spoilerContent} />
{' '} {' '}
<button tabIndex='0' className='status__content__spoiler-link' onClick={this.handleSpoilerClick}>{toggleText}</button> <button tabIndex='0' className='status__content__spoiler-link' onClick={this.handleSpoilerClick}>{toggleText}</button>
@ -146,11 +151,13 @@ export default class StatusContent extends React.PureComponent {
{mentionsPlaceholder} {mentionsPlaceholder}
<div className={`status__content__spoiler ${!hidden ? 'status__content__spoiler--visible' : ''}`}> <div className={`status__content__spoiler ${!hidden ? 'status__content__spoiler--visible' : ''}`}>
<div
<div style={directionStyle} dangerouslySetInnerHTML={content} /> style={directionStyle}
onMouseDown={this.handleMouseDown}
onMouseUp={this.handleMouseUp}
dangerouslySetInnerHTML={content}
/>
{children} {children}
</div> </div>
</div> </div>
); );
@ -160,10 +167,12 @@ export default class StatusContent extends React.PureComponent {
ref={this.setRef} ref={this.setRef}
className='status__content status__content--with-action' className='status__content status__content--with-action'
style={directionStyle} style={directionStyle}
onMouseDown={this.handleMouseDown}
onMouseUp={this.handleMouseUp}
> >
<div dangerouslySetInnerHTML={content} /> <div
onMouseDown={this.handleMouseDown}
onMouseUp={this.handleMouseUp}
dangerouslySetInnerHTML={content}
/>
{children} {children}
</div> </div>
); );
@ -173,7 +182,6 @@ export default class StatusContent extends React.PureComponent {
ref={this.setRef} ref={this.setRef}
className='status__content' className='status__content'
style={directionStyle} style={directionStyle}
dangerouslySetInnerHTML={content}
> >
<div dangerouslySetInnerHTML={content} /> <div dangerouslySetInnerHTML={content} />
{children} {children}

View File

@ -38,6 +38,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
const status = this.props.status.get('reblog') ? this.props.status.get('reblog') : this.props.status; const status = this.props.status.get('reblog') ? this.props.status.get('reblog') : this.props.status;
let media = ''; let media = '';
let mediaIcon = null;
let applicationLink = ''; let applicationLink = '';
if (status.get('media_attachments').size > 0) { if (status.get('media_attachments').size > 0) {
@ -45,12 +46,12 @@ export default class DetailedStatus extends ImmutablePureComponent {
media = <AttachmentList media={status.get('media_attachments')} />; media = <AttachmentList media={status.get('media_attachments')} />;
} else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
media = <VideoPlayer sensitive={status.get('sensitive')} media={status.getIn(['media_attachments', 0])} width={300} height={150} onOpenVideo={this.props.onOpenVideo} autoplay />; media = <VideoPlayer sensitive={status.get('sensitive')} media={status.getIn(['media_attachments', 0])} width={300} height={150} onOpenVideo={this.props.onOpenVideo} autoplay />;
mediaIcon = 'video-camera';
} 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 sensitive={status.get('sensitive')} media={status.get('media_attachments')} height={300} onOpenMedia={this.props.onOpenMedia} autoPlayGif={this.props.autoPlayGif} />;
mediaIcon = 'picture-o';
} }
} else if (status.get('spoiler_text').length === 0) { } else media = <CardContainer statusId={status.get('id')} />;
media = <CardContainer statusId={status.get('id')} />;
}
if (status.get('application')) { if (status.get('application')) {
applicationLink = <span> · <a className='detailed-status__application' href={status.getIn(['application', 'website'])} target='_blank' rel='noopener'>{status.getIn(['application', 'name'])}</a></span>; applicationLink = <span> · <a className='detailed-status__application' href={status.getIn(['application', 'website'])} target='_blank' rel='noopener'>{status.getIn(['application', 'name'])}</a></span>;
@ -63,9 +64,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
<DisplayName account={status.get('account')} /> <DisplayName account={status.get('account')} />
</a> </a>
<StatusContent status={status} /> <StatusContent status={status} mediaIcon={mediaIcon}>{media}</StatusContent>
{media}
<div className='detailed-status__meta'> <div className='detailed-status__meta'>
<a className='detailed-status__datetime' href={status.get('url')} target='_blank' rel='noopener'> <a className='detailed-status__datetime' href={status.get('url')} target='_blank' rel='noopener'>

View File

@ -493,10 +493,19 @@
cursor: pointer; cursor: pointer;
vertical-align: bottom; vertical-align: bottom;
&:hover { &:hover {
background: lighten($ui-base-color, 33%); background: lighten($ui-base-color, 33%);
text-decoration: none; text-decoration: none;
} }
.status__content__spoiler-icon {
display: inline-block;
margin: 0 0 0 5px;
border-left: 1px solid currentColor;
padding: 0 0 0 4px;
font-size: 16px;
vertical-align: -2px;
}
} }
.status__prepend-icon-wrapper { .status__prepend-icon-wrapper {

View File

@ -1,3 +1,3 @@
.media-spoiler .media-spoiler><
%span= t('stream_entries.sensitive_content') %span= t('stream_entries.sensitive_content')
%span= t('stream_entries.click_to_show') %span= t('stream_entries.click_to_show')

View File

@ -12,21 +12,22 @@
%p{ style: 'margin-bottom: 0' }< %p{ style: 'margin-bottom: 0' }<
%span.p-summary> #{status.spoiler_text}&nbsp; %span.p-summary> #{status.spoiler_text}&nbsp;
%a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more')
.e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status) .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }<
= Formatter.instance.format(status)
- unless status.media_attachments.empty? - unless status.media_attachments.empty?
- if status.media_attachments.first.video? - if status.media_attachments.first.video?
.video-player .video-player><
- if status.sensitive? - if status.sensitive?
= render partial: 'stream_entries/content_spoiler' = render partial: 'stream_entries/content_spoiler'
%video.u-video{ src: status.media_attachments.first.file.url(:original), loop: true } %video.u-video{ src: status.media_attachments.first.file.url(:original), loop: true }
- else - else
.detailed-status__attachments .detailed-status__attachments><
- if status.sensitive? - if status.sensitive?
= render partial: 'stream_entries/content_spoiler' = render partial: 'stream_entries/content_spoiler'
.status__attachments__inner .status__attachments__inner<
- status.media_attachments.each do |media| - status.media_attachments.each do |media|
= render partial: 'stream_entries/media', locals: { media: media } = render partial: 'stream_entries/media', locals: { media: media }
.detailed-status__meta .detailed-status__meta
%data.dt-published{ value: status.created_at.to_time.iso8601 } %data.dt-published{ value: status.created_at.to_time.iso8601 }

View File

@ -1,4 +1,4 @@
.media-item .media-item><
= link_to media.remote_url.blank? ? media.file.url(:original) : media.remote_url, style: media.image? ? "background-image: url(#{media.file.url(:original)})" : '', target: '_blank', rel: 'noopener', class: "u-#{media.video? || media.gifv? ? 'video' : 'photo'}" do = link_to media.remote_url.blank? ? media.file.url(:original) : media.remote_url, style: media.image? ? "background-image: url(#{media.file.url(:original)})" : '', target: '_blank', rel: 'noopener', class: "u-#{media.video? || media.gifv? ? 'video' : 'photo'}" do
- unless media.image? - unless media.image?
%video{ src: media.file.url(:original), autoplay: true, loop: true }/ %video{ src: media.file.url(:original), autoplay: true, loop: true }/

View File

@ -18,19 +18,20 @@
%p{ style: 'margin-bottom: 0' }< %p{ style: 'margin-bottom: 0' }<
%span.p-summary> #{status.spoiler_text}&nbsp; %span.p-summary> #{status.spoiler_text}&nbsp;
%a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more')
.e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status) .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }<
= Formatter.instance.format(status)
- unless status.media_attachments.empty? - unless status.media_attachments.empty?
.status__attachments .status__attachments><
- if status.sensitive? - if status.sensitive?
= render partial: 'stream_entries/content_spoiler' = render partial: 'stream_entries/content_spoiler'
- if status.media_attachments.first.video? - if status.media_attachments.first.video?
.status__attachments__inner .status__attachments__inner<
.video-item .video-item<
= link_to (status.media_attachments.first.remote_url.blank? ? status.media_attachments.first.file.url(:original) : status.media_attachments.first.remote_url), style: "background-image: url(#{status.media_attachments.first.file.url(:small)})", target: '_blank', rel: 'noopener', class: 'u-video' do = link_to (status.media_attachments.first.remote_url.blank? ? status.media_attachments.first.file.url(:original) : status.media_attachments.first.remote_url), style: "background-image: url(#{status.media_attachments.first.file.url(:small)})", target: '_blank', rel: 'noopener', class: 'u-video' do
.video-item__play .video-item__play
= fa_icon('play') = fa_icon('play')
- else - else
.status__attachments__inner .status__attachments__inner<
- status.media_attachments.each do |media| - status.media_attachments.each do |media|
= render partial: 'stream_entries/media', locals: { media: media } = render partial: 'stream_entries/media', locals: { media: media }