mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-10-08 15:50:08 +09:00
Merge pull request #330: bound attachment preview work
Reviewed and merged by GPT on behalf of DHH. Keep both boost-cache and preview-loading regressions.
This commit is contained in:
@@ -17,11 +17,16 @@ class Messages::AttachmentPresentation
|
||||
attr_reader :message, :context
|
||||
delegate :tag, :link_to, :broadcast_image_tag, :rails_blob_path, :url_for, to: :context
|
||||
|
||||
# Previews are made when the message is posted, within limits. One that wasn't, because the file was too large or
|
||||
# the preview failed, isn't attempted again from here: its URL would make it on every view.
|
||||
def render_preview
|
||||
if message.attachment.video?
|
||||
case
|
||||
when message.attachment.video?
|
||||
video_preview_tag
|
||||
else
|
||||
when message.attachment.representation(:thumb).processed?
|
||||
lightboxed_image_preview_tag
|
||||
else
|
||||
render_link
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,11 +35,17 @@ class Messages::AttachmentPresentation
|
||||
|
||||
inline_media_dimension_constraints(width, height) do
|
||||
tag.video \
|
||||
src: rails_blob_path(message.attachment), poster: url_for(message.attachment.preview(format: :webp, resize_to_limit: [ Message::THUMBNAIL_MAX_WIDTH, Message::THUMBNAIL_MAX_HEIGHT ])),
|
||||
src: rails_blob_path(message.attachment), poster: video_poster_url,
|
||||
controls: true, preload: :none, width: "100%", height: "100%", class: "message__attachment"
|
||||
end
|
||||
end
|
||||
|
||||
# A preview is processed once the frame is drawn, but the poster is a variant of that frame, which can fail on its own.
|
||||
def video_poster_url
|
||||
poster = message.attachment.preview(:poster)
|
||||
url_for(poster) if poster.processed? && poster.image.variant(poster.variation).processed?
|
||||
end
|
||||
|
||||
def lightboxed_image_preview_tag
|
||||
width, height = preview_dimensions
|
||||
|
||||
|
||||
@@ -4,9 +4,14 @@ module Message::Attachment
|
||||
THUMBNAIL_MAX_WIDTH = 1200
|
||||
THUMBNAIL_MAX_HEIGHT = 800
|
||||
|
||||
# Decoding a picture, or a video's frame, costs in proportion to its pixels, however small the file. The largest
|
||||
# phone photos have 200 million.
|
||||
THUMBNAIL_MAX_PIXELS = 250_000_000
|
||||
|
||||
included do
|
||||
has_one_attached :attachment do |attachable|
|
||||
attachable.variant :thumb, resize_to_limit: [ THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT ]
|
||||
attachable.variant :poster, format: :webp, resize_to_limit: [ THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT ]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,13 +37,23 @@ module Message::Attachment
|
||||
|
||||
# A file that ffmpeg or libvips can't decode is still the message: post it without a preview.
|
||||
def process_attachment_thumbnail
|
||||
return if too_many_pixels_to_preview?
|
||||
|
||||
case
|
||||
when attachment.video?
|
||||
attachment.preview(format: :webp).processed
|
||||
attachment.preview(:poster).processed
|
||||
when attachment.representable?
|
||||
attachment.representation(:thumb).processed
|
||||
end
|
||||
rescue ActiveStorage::PreviewError, Vips::Error => error
|
||||
Rails.logger.warn "Posted #{attachment.filename} without a preview: #{error.class}: #{error.message.lines.first&.chomp}"
|
||||
end
|
||||
|
||||
# Without a size, the analyzer couldn't read the file's header, and the previewer wouldn't either.
|
||||
def too_many_pixels_to_preview?
|
||||
if attachment.image? || attachment.video?
|
||||
width, height = attachment.metadata.values_at(:width, :height)
|
||||
width.nil? || height.nil? || width * height > THUMBNAIL_MAX_PIXELS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<%# Be sure to check/update messages/_template.html.erb when changing this file %>
|
||||
|
||||
<%# Bump this version when the message presentation filters change what they emit. Editing this line changes the template digest, which busts BOTH this fragment cache and the collection cache that keys on this partial's digest (helper Ruby changes alone don't). %>
|
||||
<% cache [ message, "presentation-v3" ] do %>
|
||||
<% cache [ message, "presentation-v4" ] do %>
|
||||
<%= message_tag message do %>
|
||||
<h2 class="message__day-separator"><%= local_datetime_tag message.created_at, style: :date %></h2>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user