Changeset e62eee4 in Klonkt


Ignore:
Timestamp:
08/09/2026 08:50:48 AM (4 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
709dc6f
Parents:
6259305
Message:

Elke chip in het lijf krijgt zijn eigen URL (shaer-38y)

Een lezer kreeg een vetgedrukte opsomming van titels met een enkele "listen
on"-link naar de post als geheel. Vijf namen waar je niets mee kon. Elke track
heeft op de postpagina al een anker -- #track-<id>, of hij nu direct is
ingesloten, in een album zit of in een playlist -- dus elke naam kan naar
precies het nummer wijzen waar hij bij hoort.

De opsomming loopt nu in EEN scan over alle drie de vormen, in de volgorde van
de post. Dat repareert er meteen iets bij: een playlist-insluiting leverde
helemaal geen namen op, want alleen track en album werden gelezen. Een
albumnaam zonder tracks blijft gewone tekst -- geen link naar een anker dat er
niet is.

De listen-link naar de pagina als geheel blijft staan; die nodigt uit naar de
speler, en dat is iets anders dan naar een nummer springen.

DIT LOST ZICHZELF NIET OP VIA DE SELF-HEAL. Die heelt ap_timeline -- de cache
van notes die wij ONTVANGEN -- en niet wat wij versturen. Onze eigen Notes
worden bij elk verzoek vers uit posts.content gebouwd, dus wie hem nu ophaalt
krijgt meteen de nieuwe vorm. Alleen kopieen die elders al gecachet zijn blijven
oud tot er een Update langskomt, en daar reikt geen self-heal bij.

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

Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/ActivityPubService.js

    r6259305 re62eee4  
    595595  // a click-through to the protected player (discovery without leaking the file).
    596596  const esc = (s) => String(s == null ? '' : s).replace(/[<>&]/g, (c) => ({ '<': '&lt;', '>': '&gt;', '&': '&amp;' }[c]));
     597  // Elke titel met zijn track-id erbij, zodat hij hieronder een EIGEN link
     598  // krijgt naar #track-<id> op de postpagina (shaer-38y). Zonder id was dit een
     599  // vetgedrukte opsomming waar je niets mee kon: vijf namen en een enkele
     600  // "listen on"-link naar de post als geheel. Elke track heeft daar al een
     601  // anker -- direct ingesloten, in een album of in een playlist -- dus dit
     602  // wijst naar precies het nummer waar de naam bij hoort.
    597603  const audioLabels = [];
    598604  try {
    599     for (const m of body.matchAll(/\[\[track:([A-Za-z0-9_-]+)\]\]/g)) { const r = db.prepare('SELECT title FROM audio_tracks WHERE id = ?').get(m[1]); if (r && r.title) audioLabels.push(r.title); }
    600     for (const m of body.matchAll(/\[\[album:([^\]]+)\]\]/g)) audioLabels.push(m[1].trim());
     605    const zien = new Set();
     606    const voegToe = (id, titel) => {
     607      const t = String(titel || '').trim();
     608      if (!t) return;
     609      const sleutel = id || ('naam:' + t);
     610      if (zien.has(sleutel)) return;
     611      zien.add(sleutel);
     612      audioLabels.push({ id: id || null, titel: t });
     613    };
     614    // In de volgorde van de POST: een enkele scan over alle drie de vormen,
     615    // zodat de opsomming leest zoals de post is neergezet.
     616    for (const m of body.matchAll(/\[\[(track|album|playlist):([^\]]+)\]\]/gi)) {
     617      const soort = m[1].toLowerCase(), waarde = m[2].trim();
     618      if (soort === 'track') {
     619        const r = db.prepare('SELECT id, title FROM audio_tracks WHERE id = ?').get(waarde);
     620        if (r) voegToe(r.id, r.title);
     621      } else if (soort === 'album') {
     622        const rs = db.prepare('SELECT id, title FROM audio_tracks WHERE site_id = ? AND album = ? ORDER BY rowid').all(site.id, waarde);
     623        if (rs.length) for (const r of rs) voegToe(r.id, r.title);
     624        else voegToe(null, waarde);            // album zonder tracks: dan maar de naam
     625      } else {
     626        for (const r of db.prepare('SELECT t.id, t.title FROM playlist_tracks pt JOIN audio_tracks t ON t.id = pt.track_id WHERE pt.playlist_id = ? ORDER BY pt.position').all(waarde)) voegToe(r.id, r.title);
     627      }
     628    }
    601629  } catch { /* non-fatal */ }
    602630  // fedi_open tracks → real AS2 Audio attachments (the actual file URL, served ungated) so
     
    633661  });
    634662  if (hadAudio) {
    635     const lbl = audioLabels.length ? esc(audioLabels.slice(0, 4).join(', ')) : '';
     663    // Elke titel als eigen link naar zijn anker; een titel zonder id (een
     664    // albumnaam zonder tracks) blijft gewone tekst.
     665    const lbl = audioLabels.slice(0, 4)
     666      .map((a) => (a.id ? `<a href="${human}#track-${esc(a.id)}">${esc(a.titel)}</a>` : esc(a.titel)))
     667      .join(', ');
    636668    if (trackEmbedLinks.length) {
    637669      // Link-only track(s): emit the external link(s). Mastodon cards the first (Spotify → its
Note: See TracChangeset for help on using the changeset viewer.