Add support for standard GIFs (under 200 KB)

master
multiple creatures 2019-04-12 13:58:30 -05:00
parent cd042a4ee3
commit 2cc2089534
3 changed files with 89 additions and 25 deletions

View File

@ -58,6 +58,9 @@ class Item extends React.PureComponent {
handleMouseEnter = (e) => {
if (this.hoverToPlay()) {
e.target.play();
} else if (this.hoverToPlayClassicGif()) {
const { attachment } = this.props;
e.target.src = attachment.get('url');
}
}
@ -65,6 +68,9 @@ class Item extends React.PureComponent {
if (this.hoverToPlay()) {
e.target.pause();
e.target.currentTime = 0;
} else if (this.hoverToPlayClassicGif()) {
const { attachment } = this.props;
e.target.src = attachment.get('preview_url');
}
}
@ -73,6 +79,14 @@ class Item extends React.PureComponent {
return !autoPlayGif && attachment.get('type') === 'gifv';
}
hoverToPlayClassicGif () {
const { attachment } = this.props;
return !autoPlayGif && (
attachment.get('type') === 'image' &&
attachment.get('url').split('.').pop().startsWith('gif')
);
}
handleClick = (e) => {
const { index, onClick } = this.props;
@ -80,6 +94,9 @@ class Item extends React.PureComponent {
if (this.hoverToPlay()) {
e.target.pause();
e.target.currentTime = 0;
} else if (this.hoverToPlayClassicGif()) {
const { attachment } = this.props;
e.target.src = attachment.get('preview_url');
}
e.preventDefault();
onClick(index);
@ -199,25 +216,54 @@ class Item extends React.PureComponent {
const x = ((focusX / 2) + .5) * 100;
const y = ((focusY / -2) + .5) * 100;
thumbnail = (
<a
className='media-gallery__item-thumbnail'
href={attachment.get('remote_url') || originalUrl}
onClick={this.handleClick}
target='_blank'
>
<img
className={letterbox ? 'letterbox' : null}
src={previewUrl}
srcSet={srcSet}
sizes={sizes}
alt={attachment.get('description')}
title={attachment.get('description')}
style={{ objectPosition: letterbox ? null : `${x}% ${y}%` }}
onLoad={this.handleImageLoad}
/>
</a>
);
const isGif = originalUrl.split('.').pop().startsWith('gif');
const autoPlay = !isIOS() && autoPlayGif;
if (isGif && !autoPlay) {
thumbnail = (
<a
className='media-gallery__item-thumbnail'
href={attachment.get('remote_url') || originalUrl}
onClick={this.handleClick}
target='_blank'
>
<img
className={letterbox ? 'letterbox' : null}
src={previewUrl}
sizes={sizes}
alt={attachment.get('description')}
title={attachment.get('description')}
style={{ objectPosition: letterbox ? null : `${x}% ${y}%` }}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
onMouseDown={this.handleMouseDown}
onLoad={this.handleImageLoad}
/>
<span className='media-gallery__gifv__label'>GIF</span>
</a>
);
} else {
thumbnail = (
<a
className='media-gallery__item-thumbnail'
href={attachment.get('remote_url') || originalUrl}
onClick={this.handleClick}
target='_blank'
>
<img
className={letterbox ? 'letterbox' : null}
src={previewUrl}
srcSet={srcSet}
sizes={sizes}
alt={attachment.get('description')}
title={attachment.get('description')}
style={{ objectPosition: letterbox ? null : `${x}% ${y}%` }}
onLoad={this.handleImageLoad}
/>
</a>
);
}
} else if (attachment.get('type') === 'gifv') {
const autoPlay = !isIOS() && autoPlayGif;

View File

@ -54,6 +54,12 @@ class MediaAttachment < ApplicationRecord
},
}.freeze
GIF_THUMB_FORMAT = {
format: 'png',
pixels: 160_000, # 400x400px
file_geometry_parser: FastGeometryParser,
}.freeze
AUDIO_STYLES = {
small: {
format: 'png',
@ -121,6 +127,7 @@ class MediaAttachment < ApplicationRecord
IMAGE_LIMIT = 8.megabytes
VIDEO_LIMIT = 40.megabytes
GIF_LIMIT = ENV.fetch('MAX_GIF_SIZE', 200).to_i.kilobytes
belongs_to :account, inverse_of: :media_attachments, optional: true
belongs_to :status, inverse_of: :media_attachments, optional: true
@ -193,10 +200,17 @@ class MediaAttachment < ApplicationRecord
def file_styles(f)
if f.instance.file_content_type == 'image/gif'
{
small: IMAGE_STYLES[:small],
original: VIDEO_FORMAT,
}
if f.instance.file_file_size > GIF_LIMIT
{
small: IMAGE_STYLES[:small],
original: VIDEO_FORMAT,
}
else
{
small: GIF_THUMB_FORMAT,
original: IMAGE_STYLES[:original],
}
end
elsif IMAGE_MIME_TYPES.include? f.instance.file_content_type
IMAGE_STYLES
elsif AUDIO_CONVERTIBLE_MIME_TYPES.include?(f.instance.file_content_type)
@ -218,7 +232,11 @@ class MediaAttachment < ApplicationRecord
def file_processors(f)
if f.file_content_type == 'image/gif'
[:gif_transcoder, :blurhash_transcoder]
if f.file_file_size > GIF_LIMIT
[:gif_transcoder, :blurhash_transcoder]
else
[:lazy_thumbnail, :blurhash_transcoder]
end
elsif VIDEO_MIME_TYPES.include? f.file_content_type
[:video_transcoder, :blurhash_transcoder]
elsif AUDIO_MIME_TYPES.include? f.file_content_type

View File

@ -20,7 +20,7 @@ module Paperclip
private
def needs_convert?
needs_different_geometry? || needs_different_format? || needs_metadata_stripping?
options[:force_convert] == true || needs_different_geometry? || needs_different_format? || needs_metadata_stripping?
end
def needs_different_geometry?