forked from cybrespace/mastodon
Do not autoplay videos, display play button instead. Use expiring links when using S3. Do not keep originals
for avatars/headers, resize avatars down to 120x120 instead of 300x300. Set cache headers on S3 stuff, also make it private (aka only accessible via expiring links to prevent hotlinking)
This commit is contained in:
parent
290ffb63cd
commit
80c44ed9c1
|
@ -53,7 +53,8 @@ const VideoPlayer = React.createClass({
|
|||
propTypes: {
|
||||
media: ImmutablePropTypes.map.isRequired,
|
||||
width: React.PropTypes.number,
|
||||
height: React.PropTypes.number
|
||||
height: React.PropTypes.number,
|
||||
sensitive: React.PropTypes.bool
|
||||
},
|
||||
|
||||
getDefaultProps () {
|
||||
|
@ -102,6 +103,12 @@ const VideoPlayer = React.createClass({
|
|||
<span style={spoilerSubSpanStyle}><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
|
||||
</div>
|
||||
);
|
||||
} else if (!sensitive && !this.state.visible) {
|
||||
return (
|
||||
<div style={{ cursor: 'pointer', position: 'relative', marginTop: '8px', width: `${width}px`, height: `${height}px`, background: `url(${media.get('preview_url')}) no-repeat center`, backgroundSize: 'cover' }} onClick={this.handleOpen}>
|
||||
<div style={{ position: 'absolute', top: '50%', left: '50%', fontSize: '36px', transform: 'translate(-50%, -50%)', padding: '5px', borderRadius: '100px', color: 'rgba(255, 255, 255, 0.8)' }}><i className='fa fa-play' /></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -112,13 +112,11 @@ module AtomBuilderHelper
|
|||
end
|
||||
|
||||
def link_enclosure(xml, media)
|
||||
xml.link(rel: 'enclosure', href: full_asset_url(media.file.url), type: media.file_content_type, length: media.file_file_size)
|
||||
xml.link(rel: 'enclosure', href: full_asset_url(media.file.url(:original, false)), type: media.file_content_type, length: media.file_file_size)
|
||||
end
|
||||
|
||||
def link_avatar(xml, account)
|
||||
single_link_avatar(xml, account, :large, 300)
|
||||
# single_link_avatar(xml, account, :medium, 96)
|
||||
# single_link_avatar(xml, account, :small, 48)
|
||||
single_link_avatar(xml, account, :original, 120)
|
||||
end
|
||||
|
||||
def logo(xml, url)
|
||||
|
|
|
@ -6,7 +6,7 @@ module StreamEntriesHelper
|
|||
end
|
||||
|
||||
def avatar_for_status_url(status)
|
||||
status.reblog? ? status.reblog.account.avatar.url(:large) : status.account.avatar.url(:large)
|
||||
status.reblog? ? status.reblog.account.avatar.expiring_url(3600, :original) : status.account.avatar.expiring_url(3600, :original)
|
||||
end
|
||||
|
||||
def entry_classes(status, is_predecessor, is_successor, include_threads)
|
||||
|
|
|
@ -13,12 +13,12 @@ class Account < ApplicationRecord
|
|||
validates :username, presence: true, uniqueness: { scope: :domain, case_sensitive: true }, unless: 'local?'
|
||||
|
||||
# Avatar upload
|
||||
has_attached_file :avatar, styles: { large: '300x300#' }, convert_options: { all: '-strip' }
|
||||
has_attached_file :avatar, styles: { original: '120x120#' }, convert_options: { all: '-quality 80 -strip' }
|
||||
validates_attachment_content_type :avatar, content_type: IMAGE_MIME_TYPES
|
||||
validates_attachment_size :avatar, less_than: 2.megabytes
|
||||
|
||||
# Header upload
|
||||
has_attached_file :header, styles: { medium: '700x335#' }, convert_options: { all: '-strip' }
|
||||
has_attached_file :header, styles: { original: '700x335#' }, convert_options: { all: '-quality 80 -strip' }
|
||||
validates_attachment_content_type :header, content_type: IMAGE_MIME_TYPES
|
||||
validates_attachment_size :header, less_than: 2.megabytes
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ class MediaAttachment < ApplicationRecord
|
|||
has_attached_file :file,
|
||||
styles: -> (f) { file_styles f },
|
||||
processors: -> (f) { f.video? ? [:transcoder] : [:thumbnail] },
|
||||
convert_options: { all: '-strip' }
|
||||
convert_options: { all: '-quality 80 -strip' }
|
||||
validates_attachment_content_type :file, content_type: IMAGE_MIME_TYPES + VIDEO_MIME_TYPES
|
||||
validates_attachment_size :file, less_than: 4.megabytes
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.account-grid-card
|
||||
.account-grid-card__header
|
||||
.avatar= image_tag account.avatar.url(:medium)
|
||||
.avatar= image_tag account.avatar.expiring_url(3600, :original)
|
||||
.name
|
||||
= link_to TagManager.instance.url_for(account) do
|
||||
%span.display_name= display_name(account)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.card{ style: "background-image: url(#{@account.header.url(:medium)})" }
|
||||
.card{ style: "background-image: url(#{@account.header.expiring_url(3600, :original)})" }
|
||||
- if user_signed_in? && current_account.id != @account.id
|
||||
.controls
|
||||
- if current_account.following?(@account)
|
||||
|
@ -6,7 +6,7 @@
|
|||
- else
|
||||
= link_to t('accounts.follow'), follow_account_path(@account), data: { method: :post }, class: 'button'
|
||||
|
||||
.avatar= image_tag @account.avatar.url(:large)
|
||||
.avatar= image_tag @account.avatar.expiring_url(3600, :original)
|
||||
%h1.name
|
||||
= display_name(@account)
|
||||
%small= "@#{@account.username}"
|
||||
|
|
|
@ -6,7 +6,7 @@ Nokogiri::XML::Builder.new do |xml|
|
|||
title xml, @account.display_name
|
||||
subtitle xml, @account.note
|
||||
updated_at xml, stream_updated_at
|
||||
logo xml, full_asset_url(@account.avatar.url(:medium, false))
|
||||
logo xml, full_asset_url(@account.avatar.expiring_url(3600, :original))
|
||||
|
||||
author(xml) do
|
||||
include_author xml, @account
|
||||
|
|
|
@ -4,8 +4,8 @@ attributes :id, :username, :acct, :display_name
|
|||
|
||||
node(:note) { |account| Formatter.instance.simplified_format(account) }
|
||||
node(:url) { |account| TagManager.instance.url_for(account) }
|
||||
node(:avatar) { |account| full_asset_url(account.avatar.url(:large, false)) }
|
||||
node(:header) { |account| full_asset_url(account.header.url(:medium, false)) }
|
||||
node(:avatar) { |account| full_asset_url(account.avatar.expiring_url(3600, :original)) }
|
||||
node(:header) { |account| full_asset_url(account.header.expiring_url(3600, :original)) }
|
||||
node(:followers_count) { |account| defined?(@followers_counts_map) ? (@followers_counts_map[account.id] || 0) : (account.try(:followers_count) || account.followers.count) }
|
||||
node(:following_count) { |account| defined?(@following_counts_map) ? (@following_counts_map[account.id] || 0) : (account.try(:following_count) || account.following.count) }
|
||||
node(:statuses_count) { |account| defined?(@statuses_counts_map) ? (@statuses_counts_map[account.id] || 0) : (account.try(:statuses_count) || account.statuses.count) }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
object @media
|
||||
attribute :id, :type
|
||||
node(:url) { |media| full_asset_url(media.file.url) }
|
||||
node(:preview_url) { |media| full_asset_url(media.file.url(:small)) }
|
||||
node(:url) { |media| full_asset_url(media.file.expiring_url(3600, :original)) }
|
||||
node(:preview_url) { |media| full_asset_url(media.file.expiring_url(3600, :small)) }
|
||||
node(:text_url) { |media| medium_url(media) }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
attributes :id, :remote_url, :type
|
||||
|
||||
node(:url) { |media| full_asset_url(media.file.url) }
|
||||
node(:preview_url) { |media| full_asset_url(media.file.url(:small)) }
|
||||
node(:url) { |media| full_asset_url(media.file.expiring_url(3600, :original)) }
|
||||
node(:preview_url) { |media| full_asset_url(media.file.expiring_url(3600, :small)) }
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
- if (status.reblog? ? status.reblog : status).media_attachments.size > 0
|
||||
%ul.media-attachments
|
||||
- (status.reblog? ? status.reblog : status).media_attachments.each do |media|
|
||||
%li.transparent-background= link_to '', media.file.url, style: "background-image: url(#{media.file.url(:small)})", target: '_blank'
|
||||
%li.transparent-background= link_to '', media.file.expiring_url(3600, :original), style: "background-image: url(#{media.file.expiring_url(3600, :small)})", target: '_blank'
|
||||
|
||||
- if include_threads
|
||||
= render partial: 'status', collection: @descendants, as: :status, locals: { is_successor: true }
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
%meta{ name: 'og:title', content: "#{@account.username} on #{Rails.configuration.x.local_domain}" }/
|
||||
%meta{ name: 'og:article:author', content: @account.username }/
|
||||
%meta{ name: 'og:description', content: @stream_entry.activity.content }/
|
||||
%meta{ name: 'og:image', content: @stream_entry.activity.is_a?(Status) && @stream_entry.activity.media_attachments.size > 0 ? full_asset_url(@stream_entry.activity.media_attachments.first.file.url(:small)) : full_asset_url(@account.avatar.url(:large)) }/
|
||||
%meta{ name: 'og:image', content: @stream_entry.activity.is_a?(Status) && @stream_entry.activity.media_attachments.size > 0 ? full_asset_url(@stream_entry.activity.media_attachments.first.file.expiring_url(3600, :small)) : full_asset_url(@account.avatar.expiring_url(3600, :original)) }/
|
||||
|
||||
.activity-stream.activity-stream-headless
|
||||
= render partial: @type, locals: { @type.to_sym => @stream_entry.activity, include_threads: true }
|
||||
|
|
|
@ -6,6 +6,8 @@ if ENV['S3_ENABLED'] == 'true'
|
|||
Paperclip::Attachment.default_options[:url] = ':s3_domain_url'
|
||||
Paperclip::Attachment.default_options[:s3_host_name] = "s3-#{ENV.fetch('S3_REGION')}.amazonaws.com"
|
||||
Paperclip::Attachment.default_options[:path] = '/:class/:attachment/:id_partition/:style/:filename'
|
||||
Paperclip::Attachment.default_options[:s3_headers] = { 'Cache-Control' => 'max-age=315576000', 'Expires' => 10.years.from_now.httpdate }
|
||||
Paperclip::Attachment.default_options[:s3_permissions] = :private
|
||||
|
||||
unless ENV['S3_CLOUDFRONT_HOST'].blank?
|
||||
Paperclip::Attachment.default_options[:url] = ':s3_alias_url'
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 681 B |
|
@ -162,7 +162,7 @@ RSpec.describe AtomBuilderHelper, type: :helper do
|
|||
let(:account) { Fabricate(:account, username: 'alice') }
|
||||
|
||||
it 'creates a link' do
|
||||
expect(used_with_namespaces { |xml| helper.link_avatar(xml, account) }).to match '<link rel="avatar" type="" media:width="300" media:height="300" href="http://test.host/avatars/large/missing.png"/>'
|
||||
expect(used_with_namespaces { |xml| helper.link_avatar(xml, account) }).to match '<link rel="avatar" type="" media:width="120" media:height="120" href="http://test.host/avatars/original/missing.png"/>'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue