]> cat aescling's git repositories - mastodon.git/commitdiff
Do not autoplay videos, display play button instead. Use expiring links when using...
authorEugen Rochko <eugen@zeonfederated.com>
Sun, 4 Dec 2016 11:26:12 +0000 (12:26 +0100)
committerEugen Rochko <eugen@zeonfederated.com>
Sun, 4 Dec 2016 11:28:10 +0000 (12:28 +0100)
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)

18 files changed:
app/assets/javascripts/components/components/video_player.jsx
app/helpers/atom_builder_helper.rb
app/helpers/stream_entries_helper.rb
app/models/account.rb
app/models/media_attachment.rb
app/views/accounts/_grid_card.html.haml
app/views/accounts/_header.html.haml
app/views/accounts/show.atom.ruby
app/views/api/v1/accounts/show.rabl
app/views/api/v1/media/create.rabl
app/views/api/v1/statuses/_media.rabl
app/views/stream_entries/_status.html.haml
app/views/stream_entries/show.html.haml
config/initializers/paperclip.rb
public/avatars/medium/missing.png [deleted file]
public/avatars/original/missing.png [moved from public/avatars/large/missing.png with 100% similarity]
public/avatars/small/missing.png [deleted file]
spec/helpers/atom_builder_helper_spec.rb

index 61c1995a782706980697c9bb1290899572f67f84..8f64ad3cd32c4184c969a281c1fd737facb95798 100644 (file)
@@ -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 (
index 40bbe0491ca5fbaed79b5a5c69c7a01e77fc79f0..953ccd438842daa6c7d3094cbd5a34b2cdb84f32 100644 (file)
@@ -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)
index 1eb2ed05861e79db94077c20f2b23ab2d41768e7..4abb00b07d079766ef7a14e6544196ced80e0c15 100644 (file)
@@ -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)
index 105b77e044080c4d21897a3b9b9177e9cfd09888..b1cf34e9abeefa133af777501d4068c366eced53 100644 (file)
@@ -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
 
index f1b9b81121e6642a54eb45abc85b8b487b003e35..d37ef99a85b75678286192a5d3bc0bac6c6c4996 100644 (file)
@@ -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
 
index f65b78470c9f45926d49005c9855404810b4187e..d91c184760c81250b22a3bcc36e5741b158a3fd3 100644 (file)
@@ -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)
index 0063d9f1609d2aa58837c13a059583dc6a6f185f..4c7d53678a13c1a8fbab8a8762b569ed2f7bd76a 100644 (file)
@@ -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}"
index 558c777f011785b601350c77cbab28f5bc6d87aa..68b1c157dda7d9119df1fcde0c4839faa973d695 100644 (file)
@@ -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
index c01349ef23f5a29e72cd8ab18907b0d6d53e6bb1..a58db29b6a4f95fb176e7591abc940ab9f02f999 100644 (file)
@@ -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) }
index 803a9309443f74ae3f55f0f0c31fb41d32e22e4f..2a4db7aaee0debcaaf8f012876e00ecf02d8ab29 100644 (file)
@@ -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) }
index e4ceef7630116217af9ff701b3435971fa9e6b54..76256ed2c7736a1ffd48021a64f5e06c947620fc 100644 (file)
@@ -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)) }
index 2edc8bc3fce1adf06c7b4c62261ae1c48fc56317..42994abbdf0d7f9a5646affd267c51810d2d7a76 100644 (file)
@@ -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 }
index a0e2488731441caa8e27d664a63be15c6f77dbd7..76dfa6dacd4a44d6136a6c160ffa32089024ca59 100644 (file)
@@ -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 }
index 4c2053e2cc8d863f21dba91e1c00fa56b313425e..704f7fe73754061f6660e7115e6df86541a4f9df 100644 (file)
@@ -1,11 +1,13 @@
 if ENV['S3_ENABLED'] == 'true'
   Aws.eager_autoload!(services: %w(S3))
 
-  Paperclip::Attachment.default_options[:storage]      = :s3
-  Paperclip::Attachment.default_options[:s3_protocol]  = 'https'
-  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[:storage]        = :s3
+  Paperclip::Attachment.default_options[:s3_protocol]    = 'https'
+  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'
diff --git a/public/avatars/medium/missing.png b/public/avatars/medium/missing.png
deleted file mode 100644 (file)
index 98fffda..0000000
Binary files a/public/avatars/medium/missing.png and /dev/null differ
diff --git a/public/avatars/small/missing.png b/public/avatars/small/missing.png
deleted file mode 100644 (file)
index 43fe8b7..0000000
Binary files a/public/avatars/small/missing.png and /dev/null differ
index 8a161cab37631fb33a016e9315fa5df79f5aa8ec..3d3bd56a19c9a0be91949ba7398efaa1dde54f33 100644 (file)
@@ -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