Changeset 952baf3 in Klonkt for src/views/pages/messages.ejs


Ignore:
Timestamp:
08/07/2026 05:15:52 PM (5 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
ba76bf5
Parents:
f85b2c3 (diff), 0d5bd2c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge GitHub-main (1.7.0) met de VPS-lijn

De twee mains waren een dag gedivergeerd en bevatten elk echt werk. GitHub had 66
commits die nooit langs prutfolio.git zijn gekomen, omdat een parallelle sessie
rechtstreeks naar GitHub pushte vanaf een kloon in /tmp op de VPS. De VPS had twee
commits die GitHub niet had. Geen van beide bevatte de ander, en stable had geen van
de twee.

Bewust een merge en geen rebase: dan blijft beide historie intact en wordt er niets
herschreven waar iemand anders al op voortbouwt.

Drie bestanden raakten beide kanten. Alle drie zijn nagekeken, want dat een merge
automatisch slaagt zegt niets over of hij inhoudelijk klopt:

src/services/ActivityPubService.js

  • de sleutelbinding staat nu boven de nieuwe asSlug-aanroep van 1.7.0, dus de controle komt nog steeds voor de handtekeningcontrole

scripts/klonkt-refresh-updater.sh

  • alleen de opzij-aanpak overleefde; systemctl mask staat nergens meer als code

deploy/MULTI-INSTANCE.md

  • spreekt zichzelf niet tegen: beschrijft opzij zetten, met de reden waarom mask weigert

remarks: het gat dat in de review naar boven kwam staat hiermee ook op de 1.7.0-lijn.
De andere bevindingen uit die review staan nog open en zijn niet in deze merge
opgelost; die horen als beads. Ook nog te doen: dezelfde sleutelbinding op stable
als 1.6.1, want daar is het gat nog open bij self-hosters.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/views/pages/messages.ejs

    rf85b2c3 r952baf3  
    22  <%- include('../partials/fedi-tabs', { active: 'berichten' }) %>
    33  <h1 class="msg-title"><%= t('msg.title') %></h1>
    4   <% if (typeof success !== 'undefined' && success) { %><div class="alert alert-success"><%= success === 'guardian_accepted' ? t('msg.guard_accepted') : (success === 'guardian_rejected' ? t('msg.guard_rejected') : (success === 'wave_sent' ? t('msg.wave_sent') : success)) %></div><% } %>
    5   <% if (typeof error !== 'undefined' && error) { %><div class="alert alert-error"><%= error === 'guardianship' ? t('msg.guard_failed') : error %></div><% } %>
     4  <% if (typeof success !== 'undefined' && success) { %><div class="alert alert-success"><%= success === 'guardian_accepted' ? t('msg.guard_accepted') : (success === 'guardian_rejected' ? t('msg.guard_rejected') : (success === 'wave_sent' ? t('msg.wave_sent') : (success === 'reply_sent' ? t('msg.reply_sent') : success))) %></div><% } %>
     5  <% if (typeof error !== 'undefined' && error) { %><div class="alert alert-error"><%= error === 'guardianship' ? t('msg.guard_failed') : (error === 'reply_empty' ? t('msg.reply_empty') : ((error === 'reply_failed' || error === 'reply_target') ? t('msg.reply_failed') : error)) %></div><% } %>
    66
    77  <%# FEP-633c: a pending guardianship offer is a special message: the kid
     
    2525
    2626  <div class="msg-filters" role="tablist" aria-label="<%= t('msg.title') %>">
     27    <%# Vier chips, geen zes: Berichten, Gesprekken en Verzonden gingen op in
     28        een enkele Gesprekken-view, waarin verzonden en ontvangen in dezelfde
     29        draad staan. Activiteit en Moderatie blijven wat ze waren. %>
    2730    <button type="button" class="msg-chip is-on" data-show="all"><%= t('msg.filter_all') %></button>
    28     <button type="button" class="msg-chip" data-show="msgs"><%= t('msg.filter_msgs') %></button>
    2931    <button type="button" class="msg-chip" data-show="conv"><%= t('msg.filter_conv') %></button>
    3032    <button type="button" class="msg-chip" data-show="act"><%= t('msg.filter_act') %></button>
    3133    <button type="button" class="msg-chip" data-show="mod"><%= t('msg.filter_mod') %></button>
    32     <button type="button" class="msg-chip" data-show="sent"><%= t('msg.filter_sent') %></button>
    3334  </div>
    3435  <div class="msg-search">
     
    5960</div>
    6061
    61 <script>
    62 (function () {
    63   if (window.__msgWired) return; window.__msgWired = true;
    64 
    65   // Filtering: kind chip AND free-text search, combined in JS (search over the
    66   // sender and the rendered message text). Empty search + "all" = show all.
    67   var list = document.querySelector('.msg-list');
    68   var noMatch = document.querySelector('.msg-nomatch');
    69   var q = document.getElementById('msg-q');
    70   var kind = 'all';
    71   var items = [];
    72   function indexItem(li) {
    73     // Index once: sender + message body + linked post title + poll text.
    74     var body = li.querySelector('.msg-content');
    75     var post = li.querySelector('.msg-post');
    76     var poll = li.querySelector('.msg-poll');
    77     li._search = ((li.getAttribute('data-who') || '') + ' ' +
    78       (body ? body.textContent : '') + ' ' + (post ? post.textContent : '') + ' ' +
    79       (poll ? poll.textContent : '')).toLowerCase();
    80   }
    81   // Re-collect + index; called on load and after each "Load more" append so new
    82   // items join the filter/search (and inherit the active chip via apply()).
    83   function reindex() {
    84     items = list ? Array.prototype.slice.call(list.querySelectorAll('.msg-item')) : [];
    85     items.forEach(function (li) { if (!li._search) indexItem(li); });
    86   }
    87   reindex();
    88   function apply() {
    89     if (!list) return;
    90     var term = (q && q.value || '').trim().toLowerCase();
    91     var shown = 0;
    92     items.forEach(function (li) {
    93       var ok = (kind === 'all' || li.getAttribute('data-kind') === kind) &&
    94         (!term || li._search.indexOf(term) !== -1);
    95       li.style.display = ok ? '' : 'none';
    96       if (ok) shown++;
    97     });
    98     if (noMatch) noMatch.hidden = shown !== 0;
    99   }
    100   document.addEventListener('click', function (e) {
    101     var chip = e.target.closest('.msg-chip'); if (!chip) return;
    102     kind = chip.getAttribute('data-show');
    103     document.querySelectorAll('.msg-chip').forEach(function (c) { c.classList.toggle('is-on', c === chip); });
    104     apply();
    105   });
    106   if (q) q.addEventListener('input', apply);
    107   // After a "Load more" append (htmx), index the new rows and re-apply the filter.
    108   document.body.addEventListener('htmx:afterSettle', function (e) {
    109     if (e.target && e.target.id === 'msg-list') { reindex(); apply(); }
    110   });
    111 
    112   var a = document.getElementById('fedi-bm-btn');
    113   if (a) {
    114     a.setAttribute('href', "javascript:void(window.open('" + location.origin + "/authorize_interaction?uri='+encodeURIComponent(window.location.href)))");
    115     a.addEventListener('click', function (e) { e.preventDefault(); a.classList.add('nudge'); setTimeout(function(){ a.classList.remove('nudge'); }, 600); });
    116   }
    117 })();
    118 </script>
     62<%# Filteren, zoeken en het in-/uitklappen zitten in assets/js/mod/messages.js.
     63    Inline script hier wordt door de CSP geweigerd zodra je deze pagina via een
     64    link BINNEN de site opent -- zie shaer-0i6. De shell laadt de module op
     65    body[data-js]; deze pagina vraagt erom met pageJs (routes/posts.js). %>
    11966
    12067<style>
     
    13885
    13986  .msg-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: .55rem; }
     87
    14088
    14189  .msg-item { display: flex; gap: .8rem; padding: .85rem .95rem; border-radius: 14px; align-items: flex-start;
     
    14896    background: color-mix(in srgb, var(--accent, #06c) 4%, transparent); }
    14997  .msg-sent { border-left: 3px solid color-mix(in srgb, var(--accent, #06c) 55%, transparent); }
     98
     99  /* ── Gesprekken ──────────────────────────────────────────────────────
     100     NA .msg-item, en dat is geen smaak: .msg-item zet display:flex, en bij
     101     gelijke specificiteit wint de laatste regel. Stond dit ervoor, dan kwam de
     102     draadkop NAAST de bubbels te staan in plaats van erboven. */
     103  .msg-thread { display: block; }
     104  .msg-thread-head { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; margin-bottom: .4rem; }
     105  /* De tegenpartij is een labeltje bij het gesprek, geen kop erboven: een
     106     kleine verzonken uitsparing, zodat de bubbels eronder de ruimte krijgen.
     107     Het aantal zit in dezelfde uitsparing in plaats van ernaast. */
     108  /* Ook de knop die het gesprek in- en uitklapt. Een button erft geen font en
     109     geen kleur, dus die staan hier expliciet; zonder dat wordt het ineens
     110     systeemblauw in 13px. */
     111  .msg-thread-who { display: inline-flex; align-items: center; gap: .3rem; min-width: 0;
     112    font: inherit; font-size: .78em; line-height: 1.5; font-weight: 500;
     113    padding: .05rem .5rem; border-radius: 999px; border: 0; cursor: pointer;
     114    color: color-mix(in srgb, var(--ink, #000) 62%, transparent);
     115    background: color-mix(in srgb, var(--ink, #000) 5%, transparent);
     116    box-shadow: inset 0 1px 2px color-mix(in srgb, var(--ink, #000) 9%, transparent);
     117    max-width: 100%; overflow: hidden; white-space: nowrap;
     118    /* Ruimer aanraakvlak dan de tekst: een chip van 18px hoog is op een telefoon
     119       niet te raken. De uitsparing blijft klein, het doel wordt groter. */
     120    min-height: 32px; }
     121  .msg-thread-who:hover { background: color-mix(in srgb, var(--ink, #000) 9%, transparent); }
     122  .msg-thread-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
     123  .msg-thread-chevron { width: 12px; height: 12px; flex: none; opacity: .55;
     124    transition: transform .18s ease; }
     125  /* Ingeklapt: de bubbels en het antwoordveld verdwijnen, de uitsparing met de
     126     naam en het AANTAL blijft staan -- dat aantal is juist ingeklapt het meest
     127     waard. */
     128  .msg-thread.is-collapsed .msg-thread-msgs,
     129  .msg-thread.is-collapsed .msg-thread-foot { display: none; }
     130  /* Tijdens het zoeken wint de treffer van de dichtgeklapte stand. */
     131  .msg-thread.is-collapsed.is-search-open .msg-thread-msgs { display: flex; }
     132  .msg-thread.is-collapsed.is-search-open .msg-thread-foot { display: flex; }
     133  .msg-thread.is-collapsed .msg-thread-chevron { transform: rotate(-90deg); }
     134  .msg-thread.is-collapsed .msg-thread-head { margin-bottom: 0; }
     135  @media (prefers-reduced-motion: reduce) { .msg-thread-chevron { transition: none; } }
     136  .msg-thread-count { font-variant-numeric: tabular-nums; opacity: .75; flex: 0 0 auto;
     137    padding-inline-start: .3rem; border-inline-start: 1px solid color-mix(in srgb, var(--ink, #000) 14%, transparent); }
     138  .msg-thread-post { display: inline-flex; align-items: center; gap: .3rem; font-size: .85em;
     139    margin-inline-start: auto; min-width: 0; max-width: 100%;
     140    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
     141  .msg-thread-post svg { width: 13px; height: 13px; flex: none; }
     142  .msg-thread-msgs { list-style: none; margin: 0; padding: 0 0 0 .7rem; display: flex; flex-direction: column; gap: .5rem;
     143    border-inline-start: 2px solid color-mix(in srgb, var(--ink, #000) 10%, transparent); }
     144  .msg-sub { display: flex; gap: .6rem; align-items: flex-start; min-width: 0; }
     145  .msg-sub > .msg-body { min-width: 0; }
     146  /* Jouw eigen bijdrage onderscheidt zich met een tint en de accentlijn die
     147     .msg-sent al had -- niet met row-reverse: dat duwde de avatar buiten de
     148     kaart zodra de regel smaller werd dan zijn inhoud. */
     149  .msg-sub.msg-sent { border-radius: 10px; padding: .3rem .45rem;
     150    background: color-mix(in srgb, var(--accent, #06c) 5%, transparent); }
     151  /* Een lange naam of tijd mag de bubbel niet uit de kaart duwen. */
     152  .msg-sub .msg-line { flex-wrap: wrap; }
     153
     154  /* De voet van een gesprek: antwoorden en zwaaien naast elkaar, ingeklapt.
     155     Een open editor onder elk gesprek maakt de lijst weer onleesbaar -- precies
     156     wat deze weergave moest oplossen. */
     157  .msg-thread-foot { display: flex; align-items: flex-start; gap: .5rem; margin-top: .5rem; flex-wrap: wrap; }
     158  .msg-reply { flex: 1 1 12rem; min-width: 0; }
     159  .msg-reply > summary { cursor: pointer; font-size: .82rem; color: var(--ink-soft, #888); }
     160  .msg-reply[open] > summary { margin-bottom: .4rem; }
     161  .msg-reply-form { min-width: 0; }
     162  .msg-wave button { line-height: 1.2; }
     163
     164  @media (max-width: 560px) {
     165    /* Op een telefoon is 40px avatar per bubbel puur verlies: de naam staat er
     166       al naast, en de inhoud heeft de breedte harder nodig. */
     167    .msg-sub > .msg-av { display: none; }
     168    .msg-thread-msgs { padding-inline-start: .55rem; }
     169    .msg-thread-post { margin-inline-start: 0; }
     170    .msg-item { padding: .7rem .6rem; gap: .6rem; }
     171  }
    150172
    151173  .msg-av { position: relative; flex: 0 0 40px; width: 40px; height: 40px; border-radius: 50%;
Note: See TracChangeset for help on using the changeset viewer.