Files
once-campfire/app/views/messages/_message.html.erb
T
Marcello Costagliola 9912e63d69 Bound the work of previewing an attachment
A video's preview and a picture's thumbnail are made inside the request that posts the message, and
nothing bounded how long either could take.

- The video preview filter also selects any frame from 5 seconds on. Rails' filter takes the second
  frame it selects, which a video with a single keyframe and no scene change only gives at its end, so
  ffmpeg decoded all of it.
- TimeLimitedVideoPreviewer gives ffmpeg 10 seconds of wall-clock time, kills it past that, and reports
  a failed preview, so the message is posted without one.
- Pictures and videos above 250 megapixels, or whose size couldn't be read, get no preview: decoding
  costs in proportion to the pixels, however small the file.
- The view shows a preview only if it was made when the message was posted. Its URL used to make it on
  view, so a preview that failed or was skipped would be attempted again on every view. The cached
  presentation's version goes up, so cached messages pick this up.
- A video's poster is made, when the message is posted, at the size the view shows it. The full-size WebP
  made until now wasn't shown anywhere, and encoding it costs in proportion to the frame's pixels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bj8KnxpTf9sj2Ysa8aLAVa
2026-10-06 15:20:57 +02:00

35 lines
1.8 KiB
Plaintext

<%# 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-v4" ] do %>
<%= message_tag message do %>
<h2 class="message__day-separator"><%= local_datetime_tag message.created_at, style: :date %></h2>
<figure class="avatar message__avatar">
<%= avatar_tag message.creator %>
</figure>
<turbo-frame id="<%= dom_id(message, :edit) %>">
<div class="message__body">
<div class="message__body-content">
<div class="message__meta">
<h3 class="message__heading">
<span class="message__author" title="<%= message.creator.title %>">
<strong data-reply-target="author"><%= message.creator.name %></strong>
</span>
<%= link_to message_timestamp(message, class: "message__timestamp"), room_at_message_path(message.room, message), target: "_top",
class: "message__permalink" %>
<span class="message__room">
<%= link_to room_display_name(message.room, for_user: nil), room_at_message_path(message.room, message), target: "_top", data: { reply_target: "link" } %>
</span>
</h3>
<%= render "messages/actions", message: message, url: room_at_message_url(message.room, message) %>
</div>
<%= render "messages/presentation", message: message %>
<%= render "messages/boosts/boosts", message: message %>
</div>
</div>
</turbo-frame>
<% end %>
<% end %>