Changeset feced2c in Klonkt for src/views/partials/fedi-node.ejs


Ignore:
Timestamp:
07/19/2026 05:25:26 PM (7 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
5190152
Parents:
33e1dbd
git-author:
Robin <roboburr@…> (07/19/2026 05:24:58 PM)
git-committer:
Robin <roboburr@…> (07/19/2026 05:25:26 PM)
Message:

Feature: media in replies — rich replies phase 2 (klonkt-demo-c7f)

Drop, paste or pick images/audio/video in the reply editor; they upload, show
as removable chips, travel as AS2 attachments on the federated Note, and render
in the thread.

  • POST /posts/upload-reply-media (requireSiteManager): image/audio/video by extension AND mimetype, stored as-is under /media/reply-media/ (no transcode; a reply attachment is not a track), 32MB cap, returns {url, mediaType, name}.
  • Editor: paperclip button + hidden file input (the mobile path), paste-files and drag/drop handlers, busy/error chips, image thumbnails, max 4, hidden attachments JSON field. Media-only submit allowed (text no longer required when something is attached).
  • deliverReply({attachments}): re-validates server-side — own /media/ paths only (the upload route is the sole producer, remote URLs rejected), image|audio|video mimetypes, capped at 4; stored as JSON on ap_outbox (additive column). Dedup guard now includes attachments so two media-only replies to the same parent are distinct from each other but double-submits still dedup.
  • buildNote reply branch: attachment array with Image/Audio/Video types and absolute URLs. getInteractions passes media through; fedi-node renders it (img/audio/video) for visitors too, loading the stylesheet when the owner-only editor is not on the page.

3 new tests (foreign-URL and type rejection, typed absolute Note attachments,
media-only allowed, only-invalid rejected); 91 green. Browser-verified end to
end: real upload via the endpoint, paste-event -> chip with thumbnail ->
submit -> ap_outbox row with content+language+attachments -> media rendered in
the thread -> /ap/notes/<id> serves the typed absolute attachment.

Co-Authored-By: Claude Opus 4.8 <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/views/partials/fedi-node.ejs

    r33e1dbd rfeced2c  
    1212  </div>
    1313  <div class="comment-content"><%- n.content %></div>
     14  <%# Rich replies: media on our own sent replies (attachments on the Note).
     15      Visitors see these too, and the reply editor (owner-only) may not render,
     16      so make sure the stylesheet is on the page either way. %>
     17  <% if (n.media && n.media.length) { %>
     18    <% if (!locals.__reAssets) { locals.__reAssets = 1; %><link rel="stylesheet" href="/assets/css/reply-editor.css"><% } %>
     19    <div class="re-reply-media">
     20      <% n.media.forEach(function (m) { %>
     21        <% if ((m.mediaType || '').indexOf('image/') === 0) { %>
     22          <a href="<%= m.url %>" target="_blank" rel="noopener"><img src="<%= m.url %>" alt="<%= m.name || '' %>" loading="lazy"></a>
     23        <% } else if ((m.mediaType || '').indexOf('audio/') === 0) { %>
     24          <audio controls preload="none" src="<%= m.url %>"></audio>
     25        <% } else { %>
     26          <video controls preload="metadata" src="<%= m.url %>"></video>
     27        <% } %>
     28      <% }); %>
     29    </div>
     30  <% } %>
    1431  <div class="comment-actions">
    1532    <% if (n.mine && typeof canManageSite !== 'undefined' && canManageSite && n.outboxId) { %>
Note: See TracChangeset for help on using the changeset viewer.