Changeset 5f3f9ec in Klonkt


Ignore:
Timestamp:
06/30/2026 11:06:00 PM (2 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
86fa2d2
Parents:
e091add
Message:

fix(cirkel): render a federated video cover as <video>, not a broken <img>

An animated cover that federates as an MP4 (Video attachment) put the video URL into cover_image_url
— circle.js's mediaImage fell back to media[0] even when it was the video — so the Cirkel feed
rendered <img src=...mp4> = a broken image. Now the video is extracted separately (never used as the
cover image) and post-tile/post-card render a muted looping <video> for a video-only cover.

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

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/routes/circle.js

    re091add r5f3f9ec  
    1919  try { return s ? JSON.parse(s) : []; } catch { return []; }
    2020}
    21 function mediaImage(media_json) {
     21// The cover image + (separately) a cover video from a remote note's media. NEVER use a video/audio
     22// item as the cover image — that produced a broken <img> for an animated cover that federated as an
     23// MP4 (the video becomes a <video> instead).
     24function coverMedia(media_json) {
    2225  const media = safeJson(media_json).map((m) => ({ ...m, url: safeUrl(m.url) })).filter((m) => m.url);
    23   return media.find((m) => /image/i.test(m.type || '')) || media[0] || null;
     26  const video = media.find((m) => /video/i.test(m.type || '')) || null;
     27  const image = media.find((m) => /image/i.test(m.type || ''))
     28    || (media[0] && !/(video|audio)/i.test(media[0].type || '') ? media[0] : null);
     29  return { image, video };
    2430}
    2531function htmlToText(html) {
     
    3743    const titleM = (r.content || '').match(/^\s*<p>\s*<strong>([\s\S]*?)<\/strong>/i);
    3844    const realTitle = titleM ? htmlToText(titleM[1]).trim() : '';
    39     const image = mediaImage(r.media_json);
     45    const cover = coverMedia(r.media_json);
    4046    const name = r.author_name || r.author_handle || 'Onbekend';
    4147    return {
     
    4652        : (text ? (text.length > 90 ? text.slice(0, 90) + '…' : text) : name),
    4753      excerpt: '',
    48       cover_image_url: image ? image.url : null,
     54      cover_image_url: cover.image ? cover.image.url : null,
     55      cover_video_url: cover.video ? cover.video.url : null,
    4956      published_at: r.published,
    5057      created_at: r.published,
  • src/views/partials/post-card.ejs

    re091add r5f3f9ec  
    1616const _ext       = !!_external;
    1717const _src       = post.source_name || '';
    18 const _hasCover  = !!post.cover_image_url;
     18const _hasCover  = !!post.cover_image_url || !!post.cover_video_url;
    1919const _typeLabel = (post.type && post.type !== 'overig' && post.type !== 'post') ? post.type : '';
    2020const _isPinned  = !!post.pinned;
     
    4949       <% if (_ext) { %>target="_blank" rel="noopener"<% } else { %>hx-get="<%= _href %>?partial=1" hx-target="#pcms-main" hx-swap="innerHTML" hx-push-url="<%= _href %>" hx-indicator="#pcms-loading"<% } %>
    5050       aria-label="<%= post.title || '(zonder titel)' %>" tabindex="-1">
    51       <img src="<%= thumb(post.cover_image_url, 480) %>"
     51      <% if (post.cover_image_url) { %><img src="<%= thumb(post.cover_image_url, 480) %>"
    5252           srcset="<%= thumb(post.cover_image_url, 320) %> 320w, <%= thumb(post.cover_image_url, 640) %> 640w, <%= thumb(post.cover_image_url, 1280) %> 1280w"
    5353           sizes="(min-width: 768px) 120px, 100vw"
    5454           alt="" loading="lazy" decoding="async"<% if (post.cover_video_url) { %> data-ios-mp4="<%= post.cover_video_url %>"<% } %>>
     55      <% } else if (post.cover_video_url) { %><video src="<%= post.cover_video_url %>" autoplay loop muted playsinline></video><% } %>
    5556      <% if (post.nsfw) { %><span class="nsfw-veil"><span class="nsfw-veil-label">🔞 <%= post.content_warning || t('post.nsfw_warning') %></span><span class="nsfw-veil-btn"><%= t('post.nsfw_show') %></span></span><% } %>
    5657    </a>
  • src/views/partials/post-tile.ejs

    re091add r5f3f9ec  
    66const _isPinned = !!post.pinned;
    77const _isBoost = !!post.isBoost;
    8 const _hasCover = !!post.cover_image_url;
     8const _hasCover = !!post.cover_image_url || !!post.cover_video_url;
    99const _typeLabel = (post.type && post.type !== 'post') ? post.type : '';
    1010const _src = post.source_name || '';   // bron-site (cirkel-feed: van welke site komt deze post)
     
    1919   <% if (_ext) { %>target="_blank" rel="noopener"<% } else { %>hx-get="<%= _href %>?partial=1" hx-target="#pcms-main" hx-swap="innerHTML" hx-push-url="<%= _href %>" hx-indicator="#pcms-loading"<% } %>>
    2020
    21   <% if (_hasCover) { %><img class="grid-tile-img" src="<%= thumb(post.cover_image_url, 480) %>" alt="" loading="lazy" decoding="async"<% if (post.cover_video_url) { %> data-ios-mp4="<%= post.cover_video_url %>"<% } %>><% } %>
     21  <% if (post.cover_image_url) { %><img class="grid-tile-img" src="<%= thumb(post.cover_image_url, 480) %>" alt="" loading="lazy" decoding="async"<% if (post.cover_video_url) { %> data-ios-mp4="<%= post.cover_video_url %>"<% } %>><% } else if (post.cover_video_url) { %><video class="grid-tile-img" src="<%= post.cover_video_url %>" autoplay loop muted playsinline></video><% } %>
    2222
    2323  <% if (_typeLabel) { %>
Note: See TracChangeset for help on using the changeset viewer.