logo

mastofe

My custom branche(s) on git.pleroma.social/pleroma/mastofe
commit: bfbc2ca0d8dcef47f8581585b42f13b6b4c933d9
parent: 5ce8a1811abbb304a6cf92616a9db4fb3cac89ee
Author: Eugen <eugen@zeonfederated.com>
Date:   Wed, 19 Apr 2017 15:37:18 +0200

Attachment list for uncached attachments (#2110)

* For undownloaded attachments, set type :unknown, display them as a list in the web UI

* Fix case when attachment type is set explicitly

Diffstat:

Aapp/assets/javascripts/components/components/attachment_list.jsx34++++++++++++++++++++++++++++++++++
Mapp/assets/javascripts/components/components/status.jsx5++++-
Mapp/assets/javascripts/components/features/status/components/detailed_status.jsx5++++-
Mapp/assets/stylesheets/components.scss50++++++++++++++++++++++++++++++++++++++++++++++++++
Mapp/models/media_attachment.rb11+++++++----
5 files changed, 99 insertions(+), 6 deletions(-)

diff --git a/app/assets/javascripts/components/components/attachment_list.jsx b/app/assets/javascripts/components/components/attachment_list.jsx @@ -0,0 +1,34 @@ +import ImmutablePropTypes from 'react-immutable-proptypes'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; + +const filename = url => url.split('/').pop().split('#')[0].split('?')[0]; + +const AttachmentList = React.createClass({ + propTypes: { + media: ImmutablePropTypes.list.isRequired + }, + + mixins: [PureRenderMixin], + + render () { + const { media } = this.props; + + return ( + <div className='attachment-list'> + <div className='attachment-list__icon'> + <i className='fa fa-link' /> + </div> + + <ul className='attachment-list__list'> + {media.map(attachment => + <li key={attachment.get('id')}> + <a href={attachment.get('remote_url')} target='_blank' rel='noopener'>{filename(attachment.get('remote_url'))}</a> + </li> + )} + </ul> + </div> + ); + } +}); + +export default AttachmentList; diff --git a/app/assets/javascripts/components/components/status.jsx b/app/assets/javascripts/components/components/status.jsx @@ -5,6 +5,7 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; import DisplayName from './display_name'; import MediaGallery from './media_gallery'; import VideoPlayer from './video_player'; +import AttachmentList from './attachment_list'; import StatusContent from './status_content'; import StatusActionBar from './status_action_bar'; import { FormattedMessage } from 'react-intl'; @@ -77,7 +78,9 @@ const Status = React.createClass({ } if (status.get('media_attachments').size > 0 && !this.props.muted) { - if (status.getIn(['media_attachments', 0, 'type']) === 'video') { + if (status.get('media_attachments').some(item => item.get('type') === 'unknown')) { + + } 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} />; } else { media = <MediaGallery media={status.get('media_attachments')} sensitive={status.get('sensitive')} height={110} onOpenMedia={this.props.onOpenMedia} autoPlayGif={this.props.autoPlayGif} />; diff --git a/app/assets/javascripts/components/features/status/components/detailed_status.jsx b/app/assets/javascripts/components/features/status/components/detailed_status.jsx @@ -5,6 +5,7 @@ import DisplayName from '../../../components/display_name'; import StatusContent from '../../../components/status_content'; import MediaGallery from '../../../components/media_gallery'; import VideoPlayer from '../../../components/video_player'; +import AttachmentList from '../../../components/attachment_list'; import { Link } from 'react-router'; import { FormattedDate, FormattedNumber } from 'react-intl'; import CardContainer from '../containers/card_container'; @@ -40,7 +41,9 @@ const DetailedStatus = React.createClass({ let applicationLink = ''; if (status.get('media_attachments').size > 0) { - if (status.getIn(['media_attachments', 0, 'type']) === 'video') { + if (status.get('media_attachments').some(item => item.get('type') === 'unknown')) { + media = <AttachmentList media={status.get('media_attachments')} />; + } 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 />; } else { media = <MediaGallery sensitive={status.get('sensitive')} media={status.get('media_attachments')} height={300} onOpenMedia={this.props.onOpenMedia} autoPlayGif={this.props.autoPlayGif} />; diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss @@ -2346,3 +2346,53 @@ button.icon-button.active i.fa-retweet { } } } + +.attachment-list { + display: flex; + font-size: 14px; + border: 1px solid lighten($color1, 8%); + border-radius: 4px; + margin-top: 14px; + overflow: hidden; +} + +.attachment-list__icon { + flex: 0 0 auto; + color: lighten($color1, 26%); + padding: 8px 18px; + cursor: default; + border-right: 1px solid lighten($color1, 8%); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: 26px; + + .fa { + display: block; + } +} + +.attachment-list__list { + list-style: none; + padding: 4px 0; + padding-left: 8px; + display: flex; + flex-direction: column; + justify-content: center; + + li { + display: block; + padding: 4px 0; + } + + a { + text-decoration: none; + color: lighten($color1, 26%); + font-weight: 500; + + &:hover { + text-decoration: underline; + } + } +} diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb @@ -3,7 +3,7 @@ class MediaAttachment < ApplicationRecord self.inheritance_column = nil - enum type: [:image, :gifv, :video] + enum type: [:image, :gifv, :video, :unknown] IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze VIDEO_MIME_TYPES = ['video/webm', 'video/mp4'].freeze @@ -95,6 +95,8 @@ class MediaAttachment < ApplicationRecord private def set_shortcode + self.type = :unknown if file.blank? && type.blank? + return unless local? loop do @@ -104,9 +106,10 @@ class MediaAttachment < ApplicationRecord end def set_type_and_extension - self.type = VIDEO_MIME_TYPES.include?(file_content_type) ? :video : :image - - unless file.blank? + if file.blank? + self.type = :unknown + else + self.type = VIDEO_MIME_TYPES.include?(file_content_type) ? :video : :image extension = Paperclip::Interpolations.content_type_extension(file, :original) basename = Paperclip::Interpolations.basename(file, :original) file.instance_write :file_name, [basename, extension].delete_if(&:empty?).join('.')