Changeset d56d471 in Klonkt for src/assets


Ignore:
Timestamp:
07/29/2026 12:36:50 PM (6 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
7a93fcf
Parents:
6100ce9
Message:

Een voorstel krijgt een antwoord, een status en een zichtbare kring

Robin meldde drie dingen na de voorstelronde: er lijkt niets te gebeuren, de
status van een voorstel is nergens te volgen, en in /guardian zie je niet wie
de mede-guardians van een kind zijn. Onderzoek op beta wees de kern aan: de
ronde is aangekomen en geteld, maar elk voorstel was shaer:externalEmbeds, en
die stond al aan. Afspelen is nooit voorgesteld, en dat KON ook niet: de knop
"Afspelen voorstellen" verscheen alleen bij embeds === true, en voor een ward
op een andere server is die waarde onbekend, dus null, dus geen knop. Onbekend
is niet uit.

Drie reparaties, een per klacht.

Een: de lus sluit. De server van het kind beantwoordt de Offer die de
beslissing opende, terug naar de voorsteller: Accept als hij settelde op het
voorgestelde, Reject bij het tegendeel. Alleen de stem van het kind-account
telt als uitkomst; een vreemde die onze boeken wil sluiten wordt genegeerd.
Zonder dit kon het scherm van de voorsteller alleen maar eeuwig "wacht"
zeggen, wat er ook gebeurd was: de telling is het prive-grootboek van de
server van het kind.

Twee: de voorsteller houdt een eigen boek bij (ap_gated_sent) en het paneel
toont per ward de stand: wacht, aangenomen, afgewezen, of eerlijk verlopen als
het venster leegliep. Stilte na het venster is geen "loopt nog".

Drie: voor een ward op een andere server toont het paneel nu wel wie de
guardians zijn. Het lidmaatschap is publiek op het actordocument
(shaer:guardians, 2.1); de beschikbaarheid is en blijft het prive-grootboek
van hun server (3.6.1) en wordt alleen benoemd, niet getoond.

Changed files:
src/config/database.js

  • tabel ap_gated_sent (het boek van de voorsteller)
  • kolom proposer op ap_gated_offers, voor het antwoord naar huis

src/services/guardianship/gated.js

  • recordSent/recallSent/settleSent/listSent en sentStatus (puur, getest)
  • rememberGatedOffer onthoudt de voorsteller

src/services/guardianship/handshake.js

  • answerGatedProposer: het settle-antwoord naar de voorsteller
  • de inbox herkent dat antwoord en settelt het eigen boek; alleen het kind-account mag dat

src/routes/guardian.js

  • proposeGated schrijft het boek; dashboardState serveert per ward de voorstellen met status
  • GET /wards/guardians: lokaal met beschikbaarheid, remote de publieke lijst van hun actordocument

src/assets/js/guardian.js

  • de afspeel-knop verschijnt ook bij onbekende embeds-stand (de bug)
  • statusregels onder de instellingen-knoppen
  • remote guardians opgehaald bij het openen van het paneel

src/assets/css/guardian.css

  • g-prop-kleuren: de staat spreekt voor de woorden uit

src/services/i18n.js

  • prop_*- en panel_guards_far-strings, NL/EN/DE

test/gated-settings.test.js

  • de lus sluit: de voorsteller krijgt het antwoord, van alleen het kind
  • het boek: open, aangenomen, afgewezen, verlopen

remarks: 334 tests groen, server start op een schone database. De guardian-kant
(sound-fabrics) en de ward-kant (beta) hebben allebei deze commit nodig: de
knop en de status leven bij de guardian, het antwoord bij het kind.

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

Location:
src/assets
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/assets/css/guardian.css

    r6100ce9 rd56d471  
    156156.g-avlabel { color: var(--sub); font-size: .8rem; white-space: nowrap; }
    157157.row.g-guard { gap: 8px; margin-top: 6px; }
     158/* The status of a proposal this guardian sent (5.6): one quiet line per
     159   feature. The colour says the state before the words do. */
     160.g-prop { margin: 6px 0 0; color: var(--sub); }
     161.g-prop-accepted { color: var(--ok); }
     162.g-prop-rejected, .g-prop-expired { color: var(--danger); }
    158163.g-away-row { display: flex; gap: 8px; }
    159164.g-card.lapse { border-left: 3px solid #8a93a3; }
  • src/assets/js/guardian.js

    r6100ce9 rd56d471  
    361361    setRow.appendChild(gateButton(w, 'shaer:externalEmbeds', w.embeds, T.embeds_propose, T.embeds_on, T.embeds_off));
    362362    // The heavier sibling (5.6): seeing that a video exists is one decision,
    363     // letting a third party's player run inside the app is another. Only
    364     // offered once previews are on: you cannot play what you may not see.
    365     if (w.embeds === true) {
     363    // letting a third party's player run inside the app is another. Hidden
     364    // only when previews are known-OFF: for a ward on another server the
     365    // value is unknown, and unknown is not off. Hiding it there meant a
     366    // guardian elsewhere could never even propose playback, which is how a
     367    // whole proposal round went into the wrong gate. The ward's server
     368    // enforces play-needs-previews at serve time regardless.
     369    if (w.embeds !== false) {
    366370      setRow.appendChild(gateButton(w, 'shaer:externalPlayback', w.playback, T.play_propose, T.play_on, T.play_off));
    367371    }
    368372    set.appendChild(setRow);
     373    // What this guardian proposed and how it stands (5.6). This used to be a
     374    // button caption that vanished on refresh, so a running decision was
     375    // invisible: you could not tell "waiting", "done" and "expired" apart.
     376    (w.proposals || []).forEach(function (p) {
     377      var what = p.feature === 'shaer:externalPlayback' ? (T.prop_play || 'playback') : (T.prop_embeds || 'link previews');
     378      var line = (T.prop_line || 'Proposal {what} {value}: {status}')
     379        .replace('{what}', what)
     380        .replace('{value}', p.value ? (T.prop_on || 'on') : (T.prop_off || 'off'))
     381        .replace('{status}', T['prop_st_' + p.status] || p.status);
     382      set.appendChild(el('p', 'small g-prop g-prop-' + p.status, line));
     383    });
    369384    panel.appendChild(set);
    370385
     
    377392      w.guardians.forEach(function (g) { gsec.appendChild(availRow(g, uri)); });
    378393    } else {
    379       gsec.appendChild(el('p', 'g-empty small', T.panel_guards_remote || ''));
     394      // A ward on another server: WHO guards it is public on its actor
     395      // (shaer:guardians, 2.1), so list the seats; availability is the ward
     396      // server's private ledger (3.6.1) and is not shown, only named.
     397      var placeholder = el('p', 'g-empty small', '…');
     398      gsec.appendChild(placeholder);
     399      fetch('/guardian/wards/guardians?site=' + encodeURIComponent(S.site) + '&uri=' + encodeURIComponent(uri))
     400        .then(function (r) { return r.json(); })
     401        .then(function (j) {
     402          if (!j || !j.guardians || !j.guardians.length) {
     403            placeholder.textContent = T.panel_guards_remote || '';
     404            return;
     405          }
     406          placeholder.remove();
     407          j.guardians.forEach(function (g) {
     408            var row = el('div', 'row g-guard');
     409            row.appendChild(el('span', 'who grow', handleOf(g.uri, g.handle)));
     410            gsec.appendChild(row);
     411          });
     412          gsec.appendChild(el('p', 'g-empty small', T.panel_guards_far || ''));
     413        })
     414        .catch(function () { placeholder.textContent = T.panel_guards_remote || ''; });
    380415    }
    381416    panel.appendChild(gsec);
Note: See TracChangeset for help on using the changeset viewer.