Changes in src/views/pages/messages.ejs [e64a49b:439f095] in Klonkt
- File:
-
- 1 edited
-
src/views/pages/messages.ejs (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/views/pages/messages.ejs
re64a49b r439f095 2 2 <%- include('../partials/fedi-tabs', { active: 'berichten' }) %> 3 3 <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 === '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><% } %>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><% } %> 6 6 7 7 <%# FEP-633c: a pending guardianship offer is a special message: the kid … … 25 25 26 26 <div class="msg-filters" role="tablist" aria-label="<%= t('msg.title') %>"> 27 <%# Vier chips, geen zes: Berichten, Gesprekken en Verzonden gingen op in28 een enkele Gesprekken-view, waarin verzonden en ontvangen in dezelfde29 draad staan. Activiteit en Moderatie blijven wat ze waren. %>30 27 <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> 31 29 <button type="button" class="msg-chip" data-show="conv"><%= t('msg.filter_conv') %></button> 32 30 <button type="button" class="msg-chip" data-show="act"><%= t('msg.filter_act') %></button> 33 31 <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> 34 33 </div> 35 34 <div class="msg-search"> … … 60 59 </div> 61 60 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). %> 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> 66 119 67 120 <style> … … 86 139 .msg-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: .55rem; } 87 140 88 89 141 .msg-item { display: flex; gap: .8rem; padding: .85rem .95rem; border-radius: 14px; align-items: flex-start; 90 142 background: color-mix(in srgb, var(--ink, #000) 3.5%, transparent); … … 96 148 background: color-mix(in srgb, var(--accent, #06c) 4%, transparent); } 97 149 .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 bij101 gelijke specificiteit wint de laatste regel. Stond dit ervoor, dan kwam de102 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: een106 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 en109 geen kleur, dus die staan hier expliciet; zonder dat wordt het ineens110 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 telefoon119 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 de126 naam en het AANTAL blijft staan -- dat aantal is juist ingeklapt het meest127 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 die147 .msg-sent al had -- niet met row-reverse: dat duwde de avatar buiten de148 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 -- precies156 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 er166 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 }172 150 173 151 .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.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)