source: Klonkt/src/views/partials/post-tile.ejs@ 457e87b

main
Last change on this file since 457e87b was 1f640ff, checked in by Robin <roboburr@…>, 6 weeks ago

Audio-tegel: golfvorm en titel elk hun eigen band, en balkjes ipv de rauwe golf

De titel stond dwars door de golfvorm heen (Robins schermafdruk): de
golfvorm hing absoluut gecentreerd en de flex-tegel centreerde de titel
er bovenop. Nu heeft elk zijn eigen band: golfvorm in de bovenhelft
(8-54 procent), titel op 60 procent, bronregel op 76. De maten staan
expliciet: een absoluut gepositioneerde img valt bij width/height auto
terug op zijn intrinsieke maat en de band klapte dicht.

En de golfvorm zelf is mooier (Robins tweede vraag): geen harige rauwe
golf meer maar balkjes in SoundCloud-stijl. Peak en average worden op 57
kolommen gesampled (zachte piek-top over heldere kern), nearest-neighbor
opgeblazen tot balkjes van 14px, en drawgrid wist er transparante
spleetjes van 5px tussen (c=black@0 met replace=1 schrijft echte
transparantie).

Changed files:
src/routes/activitypub.js

  • het showwavespic-recept vervangen door de gelaagde balkjes-graph

src/views/partials/post-tile.ejs

  • grid-tile-audio-klasse op de anchor als er een golfvorm is

src/assets/css/style.css

  • grid-tile-wave: expliciete band (top 8, hoogte 46, breedte 84)
  • grid-tile-audio: titel op 60 procent, bronregel op 76

remarks: geometrie numeriek geverifieerd in een browser-preview (golf
17.6-44.4 procent, titel 60-65.2, 58px ruimte, gradient intact) en het
balkjes-recept visueel beoordeeld op een tegel-gradient-compositie. De
bestaande audiopost houdt zijn oude dunne golfvorm-png; een verse upload
krijgt de balkjes. 345 tests groen.

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

  • Property mode set to 100644
File size: 5.1 KB
Line 
1<%
2// Square Instagram-style tile for the .feed-grid view (v9 pattern).
3// - With cover → background-image, dark gradient overlay reveals title on hover/touch
4// - No cover → .grid-tile-gradient with the title centered (random hue per tile)
5const _tileHue = ((post.id || post.slug || '0').charCodeAt(0) * 7) % 360;
6const _isPinned = !!post.pinned;
7const _isBoost = !!post.isBoost;
8const _hasCover = !!post.cover_image_url || !!post.cover_video_url;
9// A C2S post carries its media IN the content (a cover next to it showed the
10// video twice on the post page). The tile derives its picture from the
11// content instead, like the Cirkel card: first <video> (with its poster) or
12// first <img>.
13let _cVideo = null, _cPoster = null, _cImg = null, _cAudio = false, _cWave = null;
14if (!_hasCover && post.content) {
15 const vm = String(post.content).match(/<video[^>]*\ssrc="([^"]+)"[^>]*>/i);
16 if (vm) { _cVideo = vm[1]; const pm = vm[0].match(/poster="([^"]+)"/i); if (pm) _cPoster = pm[1]; }
17 else {
18 const im = String(post.content).match(/<img[^>]*\ssrc="([^"]+)"/i);
19 if (im) _cImg = im[1];
20 else {
21 // An audio post (Robins vraag, 30-7): the waveform the upload leg drew
22 // (data-poster) goes OVER the gradient, so the tile keeps its own hue.
23 const am = String(post.content).match(/<audio[^>]*>/i);
24 if (am) { _cAudio = true; const wm = am[0].match(/data-poster="([^"]+)"/i); if (wm) _cWave = wm[1]; }
25 }
26 }
27}
28const _showCover = _hasCover || !!_cVideo || !!_cImg; // the wave keeps the gradient
29// A C2S post has no title: fall back to the post's own words, and for a
30// media-only post to a friendly type label instead of "(untitled)". A tile
31// that already shows its picture needs no forced label at all.
32let _title = post.title || '';
33if (!_title && post.content) {
34 const _txt = String(post.content).replace(/<[^>]*>/g, ' ').replace(/&[a-zA-Z#0-9]+;/g, ' ').replace(/\s+/g, ' ').trim();
35 if (_txt) _title = _txt.length > 64 ? _txt.slice(0, 63).replace(/\s+\S*$/, '') + '…' : _txt;
36}
37if (!_title) _title = _cAudio ? '♪ audio' : (_cVideo || _cImg) ? '' : '(untitled)';
38const _typeLabel = (post.type && post.type !== 'post') ? post.type : '';
39const _src = post.source_name || ''; // bron-site (cirkel-feed: van welke site komt deze post)
40const _base = (typeof siteUrlBase !== 'undefined' && siteUrlBase) ? siteUrlBase : '';
41const _external = post.external_url || null;
42const _href = _external || (_base + '/' + post.slug);
43const _ext = !!_external;
44%>
45<a class="grid-tile<%= _showCover ? '' : ' grid-tile-gradient' %><%= _cWave ? ' grid-tile-audio' : '' %><%= (_isPinned || _isBoost) ? ' is-pinned' : '' %><%= post.nsfw ? ' nsfw-media' : '' %>"
46 href="<%= _href %>"
47 style="--tile-hue: <%= _tileHue %>;"
48 <% 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"<% } %>>
49
50 <% 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 %>" poster="<%= thumb(post.cover_video_url, 480) %>" autoplay loop muted playsinline></video><% } else if (_cVideo) { %><video class="grid-tile-img" src="<%= _cVideo %>"<% if (_cPoster) { %> poster="<%= _cPoster %>"<% } %> autoplay loop muted playsinline preload="metadata"></video><% } else if (_cImg) { %><img class="grid-tile-img" src="<%= _cImg %>" alt="" loading="lazy" decoding="async"><% } else if (_cWave) { %><img class="grid-tile-img grid-tile-wave" src="<%= _cWave %>" alt="" loading="lazy" decoding="async"><% } %>
51
52 <% if (_typeLabel) { %>
53 <span class="grid-tile-type"><%= _typeLabel %></span>
54 <% } %>
55 <% if (_isBoost) { %>
56 <span class="grid-tile-pin grid-tile-boost"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m17 2 4 4-4 4"/><path d="M3 11v-1a4 4 0 0 1 4-4h14"/><path d="m7 22-4-4 4-4"/><path d="M21 13v1a4 4 0 0 1-4 4H3"/></svg>Boost</span>
57 <% } else if (_isPinned) { %>
58 <span class="grid-tile-pin"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 17v5"/><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z"/></svg>Pinned</span>
59 <% } %>
60
61 <% if (_hasCover) { %>
62 <div class="grid-tile-overlay">
63 <strong><%= _title %></strong>
64 <% if (_src) { %><span class="grid-tile-overlay-src">van <%= _src %></span><% } %>
65 </div>
66 <% } else { %>
67 <span class="grid-tile-title"><%= _title %></span>
68 <% if (_src) { %><span class="grid-tile-gradient-src">van <%= _src %></span><% } %>
69 <% } %>
70 <% if (post.nsfw) { %><div class="nsfw-veil"><%- include('nsfw-veil', { cw: post.content_warning }) %></div><% } %>
71</a>
Note: See TracBrowser for help on using the repository browser.