Changeset 0448e34 in Klonkt


Ignore:
Timestamp:
08/06/2026 02:04:30 AM (5 weeks ago)
Author:
Claude (agent) <aiclaude@…>
Branches:
main
Children:
a78a0ef
Parents:
7875a80
git-author:
Robin <roboburr@…> (08/06/2026 02:04:29 AM)
git-committer:
Claude (agent) <aiclaude@…> (08/06/2026 02:04:30 AM)
Message:

Gesprekken verborg regels die geen draad werden

Robins melding: een draad die je zelf begonnen bent viel weg onder Gesprekken.
Oorzaak was een halve opruiming van mijn kant. De chips gingen van zes naar
vier, maar msg-item bleef 'sent' en 'msgs' als data-kind uitdelen aan regels die
om wat voor reden dan ook geen draad werden. Die twee chips bestaan niet meer,
dus zo'n regel matchte geen enkel filter en was alleen nog onder Alles te zien.

Geraakt werden: een verzonden bericht zonder post en zonder herkenbare
ontvanger, een mention zonder afzender, en een losse privé-reply. Alles wat een
gesprek is krijgt nu data-kind 'conv'; alleen Activiteit en Moderatie houden een
eigen emmer.

Daarnaast de oorzaak een stap eerder aangepakt: een direct bericht kan zonder
to_handle in ap_outbox staan, en dan vond threadKey geen tegenpartij. De eerste
uit to_actors telt nu ook, met to_handle als winnaar zodat dezelfde persoon niet
twee draden oplevert. Juist een gesprek dat JIJ begon heeft vaak niets anders om
aan te hangen, dus daar deed het ontbreken van die terugval het meeste pijn.

Getest tegen dev: de drie gevallen renderden aantoonbaar als data-kind sent/msgs
en doen dat nu als conv, terwijl like en report op act en mod blijven. Suite
410/410, met twee nieuwe tests op de to_actors-terugval.

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

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/services/ActivityPubService.js

    r7875a80 r0448e34  
    638638    for (const m of listOutbox(slug).slice(0, need)) {
    639639      items.push({
    640         type: 'sent', outboxId: m.id, to_handle: m.to_handle, in_reply_to: m.in_reply_to,
    641         post_slug: m.post_slug, content: m.content, editable: m.editable,
    642         language: m.language, created_at: m.created_at,
     640        type: 'sent', outboxId: m.id, to_handle: m.to_handle, to_actors: m.to_actors,
     641        in_reply_to: m.in_reply_to, post_slug: m.post_slug, content: m.content,
     642        editable: m.editable, language: m.language, created_at: m.created_at,
    643643      });
    644644    }
     
    701701  if (!it || !CONV_TYPES.has(it.type)) return null;
    702702  if (it.post_slug) return `post:${it.post_slug}`;
    703   const who = it.handle || it.to_handle || '';
    704   const norm = String(who).trim().toLowerCase().replace(/^@/, '');
     703  let who = it.handle || it.to_handle || '';
     704  // Een direct bericht kan zonder to_handle in de tabel staan (de handle van de
     705  // ontvanger was niet af te leiden). De eerste uit to_actors is dan alsnog de
     706  // tegenpartij, en zonder deze terugval kreeg een gesprek dat JIJ begon geen
     707  // draad -- precies het geval waarin het meest onlogisch is dat het los blijft.
     708  if (!who && it.to_actors) {
     709    try {
     710      const first = JSON.parse(it.to_actors)[0];
     711      if (first) who = deriveHandle(first);
     712    } catch { /* geen bruikbare lijst → geen sleutel, het blijft een losse regel */ }
     713  }
     714  const norm = String(who || '').trim().toLowerCase().replace(/^@/, '');
    705715  return norm ? `actor:${norm}` : null;
    706716}
     
    30103020  // gaat staan (zie threadKey). Zonder die kolom viel een uitwisseling uit
    30113021  // elkaar in "Verzonden" en "Gesprekken".
    3012   return db.prepare('SELECT id, content, to_handle, to_actor, post_slug, in_reply_to, language, created_at FROM ap_outbox WHERE site_slug = ? ORDER BY created_at DESC')
     3022  return db.prepare('SELECT id, content, to_handle, to_actor, to_actors, post_slug, in_reply_to, language, created_at FROM ap_outbox WHERE site_slug = ? ORDER BY created_at DESC')
    30133023    .all(siteSlug).map((r) => { const c = stripLeadingMentions(r.content); return { ...r, content: c, editable: outboxEditableText(c) }; });
    30143024}
  • src/views/partials/msg-item.ejs

    r7875a80 r0448e34  
    3737           var _who = n.name || n.handle || '';
    3838           var _priv0 = (n.visibility === 'followers' || n.visibility === 'direct');
    39            // Buckets (klonkt-demo-3jf): Messages = @mentions + private (DM) replies;
    40            // Activity = likes/boosts/follows; Moderation = reports; Sent = your
    41            // replies; Conversations = every other (public) reply.
    42            var _kind = _t === 'sent' ? 'sent'
    43              : (_t === 'like' || _t === 'boost' || _t === 'follow' || _t === 'poll_done') ? 'act'
     39           // Emmers: Activiteit = likes/boosts/follows/polls, Moderatie =
     40           // reports, en al het overige is gesprek. De oude emmers 'msgs' en
     41           // 'sent' bestaan niet meer sinds Berichten, Gesprekken en Verzonden
     42           // samenvielen -- en dat is geen cosmetische hernoeming: een
     43           // gespreksregel die om wat voor reden dan ook geen draad werd (geen
     44           // post, geen herkenbare tegenpartij) hield anders een data-kind
     45           // waarvoor geen chip meer bestond, en was daarmee onder ELKE chip
     46           // behalve Alles onzichtbaar.
     47           var _kind = (_t === 'like' || _t === 'boost' || _t === 'follow' || _t === 'poll_done') ? 'act'
    4448             : _t === 'report' ? 'mod'
    45              : (_t === 'mention' || _priv0) ? 'msgs'
    4649             : 'conv';
    4750           // Binnen een draad is dit geen zelfstandige regel: de chip filtert op
  • test/messages-conversations.test.js

    r7875a80 r0448e34  
    112112  assert.equal(out[0].type, 'sent');
    113113});
     114
     115test('een direct bericht zonder to_handle valt terug op to_actors', () => {
     116  // Precies het geval waarin het het onlogischst is dat er geen draad ontstaat:
     117  // een gesprek dat JIJ begon. Zonder deze terugval bleef het een losse regel.
     118  const key = threadKey({
     119    type: 'sent',
     120    to_actors: JSON.stringify(['https://a.test/users/anna', 'https://b.test/users/bo']),
     121    created_at: ts(1),
     122  });
     123  assert.equal(key, 'actor:anna@a.test');
     124  // Rommel in de kolom mag niets omgooien.
     125  assert.equal(threadKey({ type: 'sent', to_actors: 'geen json' }), null);
     126  assert.equal(threadKey({ type: 'sent', to_actors: '[]' }), null);
     127});
     128
     129test('to_handle wint van to_actors, zodat een draad niet splitst', () => {
     130  const a = threadKey({ type: 'sent', to_handle: '@anna@a.test' });
     131  const b = threadKey({ type: 'sent', to_handle: '@anna@a.test', to_actors: JSON.stringify(['https://b.test/users/bo']) });
     132  assert.equal(a, b, 'dezelfde tegenpartij hoort dezelfde sleutel te geven');
     133});
Note: See TracChangeset for help on using the changeset viewer.