Changeset 28267519 in Klonkt for src/assets/js/guardian2.js


Ignore:
Timestamp:
07/25/2026 07:43:37 AM (7 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
5c373b8
Parents:
05665bc
Message:

Guardian 2: meekijken met je wards (interop-hoofdroute, FEP-633c §5)

Een guardian volgt z'n wards, dus hun posts (ook followers-only) worden bezorgd
in de inbox -> timeline. Volgen is het mechanisme, geen nieuwe fetch, werkt
cross-instance en respecteert zichtbaarheid. Bij eerste contact backfillen we de
recente PUBLIEKE posts als cold start zodat de hoek niet leeg is. Read-only: een
guardian kijkt, publiceert niet.

Klonkt accepteert vandaag elke Follow automatisch, dus een gecommitte guardian
komt er direct in; de expliciete 5.3-gating (auto-accept alleen voor guardians)
is de volgende fase. Authorized-fetch komt als Klonkt-onderlinge verfijning erna.

Changed files:
src/routes/guardian2.js

  • ensureWardConnections(): volg + backfill per ward, alleen eerste keer
  • GET /api/feed: getTimeline gefilterd op je wards, read-only shape

src/views/pages/guardian2.ejs

  • wards-corner sectie bovenaan

src/assets/js/guardian2.js

  • renderFeed/loadFeed; CW ingeklapt; server-gesanitizede HTML

src/assets/css/guardian2.css

  • feed-kaart-styling

src/services/i18n.js

  • guardian2 feed_title/feed_sub (nl/en/de)

remarks: npm test 164/164; feed-api auth-gated. v1 /guardian onaangeraakt.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/assets/js/guardian2.js

    r05665bc r28267519  
    133133  function renderAll() { renderHelp(); renderPending(); renderWards(); }
    134134
     135  // ── 0. Wards' corner: read-only feed of your wards' posts ───────────────
     136  function renderFeed(items) {
     137    var list = document.getElementById('feed-list');
     138    list.textContent = '';
     139    (items || []).forEach(function (p) {
     140      var card = el('div', 'g-card feed');
     141      var head = el('div', 'row');
     142      head.appendChild(el('span', 'who grow', p.author));
     143      if (p.published) head.appendChild(el('span', 'g-when', when(p.published)));
     144      card.appendChild(head);
     145      var body = el('div', 'feed-body');
     146      if (p.cw) {
     147        var d = document.createElement('details');
     148        var sum = document.createElement('summary'); sum.textContent = p.cw; d.appendChild(sum);
     149        var inner = el('div'); inner.innerHTML = p.content || ''; d.appendChild(inner);
     150        body.appendChild(d);
     151      } else {
     152        body.innerHTML = p.content || '';   // server-sanitized HTML (same as Berichten)
     153      }
     154      card.appendChild(body);
     155      list.appendChild(card);
     156    });
     157    show('feed-section', (items || []).length > 0);
     158  }
     159
     160  function loadFeed() {
     161    return fetch('/guardian2/api/feed?site=' + encodeURIComponent(S.site))
     162      .then(function (r) { return r.json(); })
     163      .then(function (f) { if (f && !f.error) renderFeed(f.items); })
     164      .catch(function () { /* corner just stays hidden */ });
     165  }
     166
    135167  function refresh() {
    136168    return fetch('/guardian2/api/state?site=' + encodeURIComponent(S.site))
    137169      .then(function (r) { return r.json(); })
    138       .then(function (s) { if (s && !s.error) { S = s; T = s.strings || T; renderAll(); } });
     170      .then(function (s) { if (s && !s.error) { S = s; T = s.strings || T; renderAll(); } })
     171      .then(loadFeed);
    139172  }
    140173
     
    230263  });
    231264
    232   renderAll(); pushState();
     265  renderAll(); pushState(); loadFeed();
    233266  setInterval(refresh, 45000);   // live-ish while open
    234267  } catch (e) {
Note: See TracChangeset for help on using the changeset viewer.