| 1 | <% if (n.type === 'thread') { %>
|
|---|
| 2 | <%
|
|---|
| 3 | var _tseen = (typeof seen !== 'undefined' && seen) ? seen : 0;
|
|---|
| 4 | // Een draad is nieuw zodra EEN bericht erin nieuw is.
|
|---|
| 5 | var _tnew = !!_tseen && (n.messages || []).some(function (m) {
|
|---|
| 6 | return m.created_at && Date.parse(m.created_at) > _tseen;
|
|---|
| 7 | });
|
|---|
| 8 | var _tpeople = (n.people || []).map(function (p) { return p.name || p.handle || '?'; });
|
|---|
| 9 | // Alleen jij aan het woord: dan is de tegenpartij het adres waaraan
|
|---|
| 10 | // je schreef, niet een lege naam.
|
|---|
| 11 | var _tto = ((n.messages || []).find(function (m) { return m.to_handle; }) || {}).to_handle;
|
|---|
| 12 | var _tlabel = _tpeople.length ? _tpeople.join(', ') : (_tto || t('msg.you'));
|
|---|
| 13 | %>
|
|---|
| 14 | <li class="msg-item msg-thread<%= _tnew ? ' is-new' : '' %>" data-kind="conv" data-who="<%= (_tpeople.join(' ') + ' ' + (_tto || '')).toLowerCase() %>">
|
|---|
| 15 | <div class="msg-thread-head">
|
|---|
| 16 | <%# Tegenpartij en aantal in EEN uitsparing: het is een label bij het
|
|---|
| 17 | gesprek, geen kop erboven. Zo houdt de inhoud de ruimte.
|
|---|
| 18 |
|
|---|
| 19 | Deze uitsparing is ook de knop die het gesprek in- en uitklapt
|
|---|
| 20 | (Barts aanwijzing): tikken op de tegenpartij is waar je van
|
|---|
| 21 | nature naar wijst als je "dit gesprek" bedoelt. Een BUTTON en
|
|---|
| 22 | geen span met een klikhandler, want dan werkt hij ook met het
|
|---|
| 23 | toetsenbord en leest een schermlezer de stand voor.
|
|---|
| 24 |
|
|---|
| 25 | Zonder JavaScript doet hij niets, en dan staat het gesprek
|
|---|
| 26 | gewoon open -- dat is ook de stand waar we mee beginnen. %>
|
|---|
| 27 | <button type="button" class="msg-thread-who" aria-expanded="true">
|
|---|
| 28 | <span class="msg-thread-name"><%= _tlabel %></span>
|
|---|
| 29 | <% if (n.count > 1) { %><span class="msg-thread-count"><%= n.count %></span><% } %>
|
|---|
| 30 | <svg class="msg-thread-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>
|
|---|
| 31 | </button>
|
|---|
| 32 | <% if (_tnew) { %><span class="msg-new" title="<%= t('msg.new') %>"></span><% } %>
|
|---|
| 33 | <%# De context bij de draad: waar gaat dit gesprek over? Zonder deze
|
|---|
| 34 | link is een antwoord in een lijst niet te plaatsen. %>
|
|---|
| 35 | <% if (n.post) { %>
|
|---|
| 36 | <a class="msg-thread-post" href="/<%= n.post.slug %>">
|
|---|
| 37 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
|
|---|
| 38 | <%= n.post.title || n.post.slug %>
|
|---|
| 39 | </a>
|
|---|
| 40 | <% } %>
|
|---|
| 41 | </div>
|
|---|
| 42 | <ul class="msg-thread-msgs">
|
|---|
| 43 | <% (n.messages || []).forEach(function (m) { %><%- include('msg-item', { n: m, seen: _tseen, inThread: true }) %><% }); %>
|
|---|
| 44 | </ul>
|
|---|
| 45 | <%# Antwoorden vanuit de draad zelf. Ingeklapt, want een open editor
|
|---|
| 46 | onder elk gesprek maakt de lijst onleesbaar -- juist het probleem
|
|---|
| 47 | dat deze weergave moest oplossen. De route kiest het pad: een
|
|---|
| 48 | draad aan een post krijgt een reply, een draad aan een persoon een
|
|---|
| 49 | direct bericht. %>
|
|---|
| 50 | <% var _rt = n.replyTo || {}; var _kan = canMutate && ((_rt.interactionId && _rt.postSlug) || _rt.actorUri); %>
|
|---|
| 51 | <% if (_kan) { %>
|
|---|
| 52 | <div class="msg-thread-foot">
|
|---|
| 53 | <details class="msg-reply">
|
|---|
| 54 | <summary><%= t('fedi.reply') %></summary>
|
|---|
| 55 | <div class="msg-reply-form">
|
|---|
| 56 | <%- include('../partials/reply-editor', {
|
|---|
| 57 | action: (typeof siteUrlBase !== 'undefined' ? siteUrlBase : '') + '/messages/reply',
|
|---|
| 58 | hiddenFields: [
|
|---|
| 59 | { name: 'interaction_id', value: _rt.interactionId || '' },
|
|---|
| 60 | { name: 'post_slug', value: _rt.postSlug || '' },
|
|---|
| 61 | { name: 'to', value: _rt.actorUri || '' },
|
|---|
| 62 | ],
|
|---|
| 63 | placeholder: t('fedi.reply_ph'),
|
|---|
| 64 | submitLabel: t('fedi.reply'),
|
|---|
| 65 | rows: 2,
|
|---|
| 66 | }) %>
|
|---|
| 67 | </div>
|
|---|
| 68 | </details>
|
|---|
| 69 | <%# De zwaai blijft een eigen knop: het is geen antwoord maar een
|
|---|
| 70 | seintje (FEP-633c), en die twee horen niet op een hoop. %>
|
|---|
| 71 | <% if (_rt.actorUri) { %>
|
|---|
| 72 | <form method="post" action="<%= (typeof siteUrlBase !== 'undefined' ? siteUrlBase : '') %>/messages/quick-reply" class="msg-wave">
|
|---|
| 73 | <input type="hidden" name="to" value="<%= _rt.actorUri %>">
|
|---|
| 74 | <button class="btn small" name="text" value="👋" title="<%= t('msg.wave_back') %>">👋</button>
|
|---|
| 75 | </form>
|
|---|
| 76 | <% } %>
|
|---|
| 77 | </div>
|
|---|
| 78 | <% } %>
|
|---|
| 79 | </li>
|
|---|
| 80 | <% } else { %>
|
|---|
| 81 | <%
|
|---|
| 82 | var _seen = (typeof seen !== 'undefined' && seen) ? seen : 0;
|
|---|
| 83 | var _t = n.type === 'announce' ? 'boost' : n.type; // reply|mention|report|like|boost|follow|sent
|
|---|
| 84 | var _new = _seen && n.created_at ? (Date.parse(n.created_at) > _seen) : false;
|
|---|
| 85 | var _who = n.name || n.handle || '';
|
|---|
| 86 | var _priv0 = (n.visibility === 'followers' || n.visibility === 'direct');
|
|---|
| 87 | // Emmers: Activiteit = likes/boosts/follows/polls, Moderatie =
|
|---|
| 88 | // reports, en al het overige is gesprek. De oude emmers 'msgs' en
|
|---|
| 89 | // 'sent' bestaan niet meer sinds Berichten, Gesprekken en Verzonden
|
|---|
| 90 | // samenvielen -- en dat is geen cosmetische hernoeming: een
|
|---|
| 91 | // gespreksregel die om wat voor reden dan ook geen draad werd (geen
|
|---|
| 92 | // post, geen herkenbare tegenpartij) hield anders een data-kind
|
|---|
| 93 | // waarvoor geen chip meer bestond, en was daarmee onder ELKE chip
|
|---|
| 94 | // behalve Alles onzichtbaar.
|
|---|
| 95 | var _kind = (_t === 'like' || _t === 'boost' || _t === 'follow' || _t === 'poll_done') ? 'act'
|
|---|
| 96 | : _t === 'report' ? 'mod'
|
|---|
| 97 | : 'conv';
|
|---|
| 98 | // Binnen een draad is dit geen zelfstandige regel: de chip filtert op
|
|---|
| 99 | // de draad, niet op de losse zinnen erin.
|
|---|
| 100 | var _sub = (typeof inThread !== 'undefined' && inThread);
|
|---|
| 101 | var _init = String(_who || '?').replace(/^@/, '').charAt(0).toUpperCase();
|
|---|
| 102 | var _priv = (n.visibility === 'followers' || n.visibility === 'direct');
|
|---|
| 103 | %>
|
|---|
| 104 | <li class="<%= _sub ? 'msg-sub' : 'msg-item' %> msg-<%= _t %><%= _new ? ' is-new' : '' %>"<% if (!_sub) { %> data-kind="<%= _kind %>"<% } %> data-who="<%= String(_who).toLowerCase() %>">
|
|---|
| 105 | <span class="msg-av<%= _t === 'sent' ? ' msg-av-sent' : '' %>" aria-hidden="true">
|
|---|
| 106 | <% if (_t === 'sent') { %><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
|
|---|
| 107 | <% } else if (_t === 'poll_done') { %><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>
|
|---|
| 108 | <% } else if (n.icon) { %><img src="<%= avatar(n.icon, 96) %>" alt="" loading="lazy">
|
|---|
| 109 | <% } else { %><%= _init %><% } %>
|
|---|
| 110 | <span class="msg-dot msg-dot-<%= _t %>">
|
|---|
| 111 | <% if (_t === 'like') { %><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.6l2.9 5.88 6.49.95-4.7 4.58 1.11 6.46L12 17.96l-5.8 3.06 1.1-6.46-4.69-4.58 6.49-.95z"/></svg>
|
|---|
| 112 | <% } else if (_t === 'boost') { %><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg>
|
|---|
| 113 | <% } else if (_t === 'follow') { %><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><line x1="19" y1="8" x2="19" y2="14"/><line x1="22" y1="11" x2="16" y2="11"/></svg>
|
|---|
| 114 | <% } else if (_t === 'report') { %><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/></svg>
|
|---|
| 115 | <% } else if (_t === 'mention') { %><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.92 7.94"/></svg>
|
|---|
| 116 | <% } else if (_t === 'sent') { %><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 0 0-4-4H4"/></svg>
|
|---|
| 117 | <% } else if (_t === 'poll_done') { %><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>
|
|---|
| 118 | <% } else { %><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg><% } %>
|
|---|
| 119 | </span>
|
|---|
| 120 | </span>
|
|---|
| 121 |
|
|---|
| 122 | <div class="msg-body">
|
|---|
| 123 | <div class="msg-line">
|
|---|
| 124 | <% if (_t === 'sent') { %>
|
|---|
| 125 | <span class="msg-who"><%= t('msg.you') %></span>
|
|---|
| 126 | <% if (n.to_handle && !_sub) { %><span class="msg-handle">→ <%= n.to_handle %></span><% } %>
|
|---|
| 127 | <% } else { %>
|
|---|
| 128 | <a class="msg-who" href="<%= n.url %>" target="_blank" rel="nofollow noopener"><%- emojiName(_who, n.actor_emoji_json) %></a>
|
|---|
| 129 | <% /* De naam blijft: binnen een draad moet je zien WIE wat zei.
|
|---|
| 130 | De handle erachter niet -- die staat in de kop. */ %>
|
|---|
| 131 | <% if (n.handle && n.name && !_sub) { %><span class="msg-handle"><%= n.handle %></span><% } %>
|
|---|
| 132 | <% } %>
|
|---|
| 133 | <% if (_new) { %><span class="msg-new" title="<%= t('msg.new') %>"></span><% } %>
|
|---|
| 134 | <% /* When the post was written, like de Krant and de Guardian PWA
|
|---|
| 135 | show it. created_at (when it reached us) stays the sort key
|
|---|
| 136 | and drives the "new since your last visit" dot above. */ %>
|
|---|
| 137 | <% if (n.published || n.created_at) { %><span class="msg-time"><%= formatDateTime(n.published || n.created_at) %></span><% } %>
|
|---|
| 138 | </div>
|
|---|
| 139 |
|
|---|
| 140 | <% var _hasWhat = !_sub || _priv
|
|---|
| 141 | || (_t === 'mention' && (n.help_request || n.wave || n.note_url))
|
|---|
| 142 | || (_t === 'sent' && n.in_reply_to); %>
|
|---|
| 143 | <% if (_hasWhat) { %>
|
|---|
| 144 | <div class="msg-what">
|
|---|
| 145 | <% if (n.count && n.count > 1) { %>
|
|---|
| 146 | <strong><%= t('msg.and_more', { n: n.count - 1 }) %></strong>
|
|---|
| 147 | <%= _t === 'like' ? t('msg.liked_many') : t('msg.boosted_many') %>
|
|---|
| 148 | <% } else if (_t === 'follow') { %><%= t('notif.followed') %>
|
|---|
| 149 | <% } else if (_t === 'like') { %><%= t('notif.liked') %>
|
|---|
| 150 | <% } else if (_t === 'boost') { %><%= t('notif.boosted') %>
|
|---|
| 151 | <% } else if (_t === 'report') { %><%= t('notif.reported') %>
|
|---|
| 152 | <% } else if (_t === 'mention' && n.help_request) { %>🛟 <%= t('msg.help_request') %>
|
|---|
| 153 | <% } else if (_t === 'mention' && n.wave) { %>👋 <%= t('msg.waved_at_you') %>
|
|---|
| 154 | <% } else if (_sub) { %><%# binnen een draad zegt de kop al dat dit een gesprek is %>
|
|---|
| 155 | <% } else if (_t === 'mention') { %><%= t('notif.mentioned') %>
|
|---|
| 156 | <% } else if (_t === 'sent') { %><%= t('msg.sent_reply') %>
|
|---|
| 157 | <% } else if (_t === 'poll_done') { %><strong><%= t('msg.poll_done') %></strong>
|
|---|
| 158 | <% } else { %><%= t('notif.replied') %><% } %>
|
|---|
| 159 | <% if (_priv) { %><span class="msg-priv" title="<%= t('msg.private_hint') %>">🔒 <%= t('msg.private') %></span><% } %>
|
|---|
| 160 | <% if (n.post_slug && !_sub) { %><a class="msg-post" href="/<%= n.post_slug %>"><%= n.post_title || n.post_slug %></a><% } %>
|
|---|
| 161 | <% if (_t === 'mention' && n.note_url) { %><a class="msg-post" href="<%= n.note_url %>" target="_blank" rel="nofollow noopener"><%= t('tl.view_original') %></a><% } %>
|
|---|
| 162 | <% if (_t === 'sent' && n.in_reply_to) { %><a class="msg-post" href="<%= n.in_reply_to %>" target="_blank" rel="nofollow noopener"><%= t('tl.view_original') %></a><% } %>
|
|---|
| 163 | </div>
|
|---|
| 164 | <% } %>
|
|---|
| 165 |
|
|---|
| 166 | <% if (_t === 'report' && n.content) { %><div class="msg-content"><%= n.content %></div>
|
|---|
| 167 | <% } else if ((_t === 'reply' || _t === 'mention' || _t === 'sent') && n.content) { %><div class="msg-content msg-note"><%- include('../partials/note-body', { nb: n }) %></div>
|
|---|
| 168 | <% if (_t === 'mention' && n.wave && n.actorUri && canMutate) { %>
|
|---|
| 169 | <form class="msg-quickreply" method="post" action="<%= (typeof siteUrlBase !== 'undefined' ? siteUrlBase : '') %>/messages/quick-reply" style="display:flex;gap:6px;flex-wrap:wrap;margin-top:6px">
|
|---|
| 170 | <input type="hidden" name="to" value="<%= n.actorUri %>">
|
|---|
| 171 | <button class="btn small" name="text" value="<%= t('msg.wave_r1') %>"><%= t('msg.wave_r1') %></button>
|
|---|
| 172 | <button class="btn small" name="text" value="<%= t('msg.wave_r2') %>"><%= t('msg.wave_r2') %></button>
|
|---|
| 173 | <button class="btn small" name="text" value="👋"><%= t('msg.wave_back') %></button>
|
|---|
| 174 | </form>
|
|---|
| 175 | <% } %>
|
|---|
| 176 | <% } else if (_t === 'poll_done' && n.poll) { %>
|
|---|
| 177 | <div class="msg-poll" role="group">
|
|---|
| 178 | <% n.poll.options.forEach(function (o) { %>
|
|---|
| 179 | <div class="msg-poll-opt">
|
|---|
| 180 | <div class="msg-poll-top"><span class="msg-poll-name"><%= o.name %></span><span class="msg-poll-pct"><%= o.pct %>%</span></div>
|
|---|
| 181 | <div class="msg-poll-bar"><span style="width:<%= o.pct %>%"></span></div>
|
|---|
| 182 | </div>
|
|---|
| 183 | <% }); %>
|
|---|
| 184 | <div class="msg-poll-total"><%= t('msg.poll_total', { n: n.poll.voters }) %></div>
|
|---|
| 185 | </div>
|
|---|
| 186 | <% } %>
|
|---|
| 187 |
|
|---|
| 188 | <% if (_t === 'sent' && n.outboxId) { %>
|
|---|
| 189 | <div class="msg-actions">
|
|---|
| 190 | <details class="msg-edit">
|
|---|
| 191 | <summary><%= t('fedi.edit') %></summary>
|
|---|
| 192 | <div class="msg-edit-form">
|
|---|
| 193 | <%- include('../partials/reply-editor', {
|
|---|
| 194 | action: '/fediverse/' + n.outboxId + '/edit',
|
|---|
| 195 | placeholder: t('fedi.reply_ph'),
|
|---|
| 196 | submitLabel: t('fedi.save_edit'),
|
|---|
| 197 | rows: 2,
|
|---|
| 198 | initialHtml: n.content,
|
|---|
| 199 | initialText: n.editable,
|
|---|
| 200 | defaultLang: n.language,
|
|---|
| 201 | noAttach: true,
|
|---|
| 202 | }) %>
|
|---|
| 203 | </div>
|
|---|
| 204 | </details>
|
|---|
| 205 | <form method="post" action="/fediverse/<%= n.outboxId %>/delete" data-confirm="<%= t('fedi.delete_confirm') %>">
|
|---|
| 206 | <button type="submit" class="msg-del"><%= t('comments.delete') %></button>
|
|---|
| 207 | </form>
|
|---|
| 208 | </div>
|
|---|
| 209 | <% } %>
|
|---|
| 210 | </div>
|
|---|
| 211 | </li>
|
|---|
| 212 | <% } %>
|
|---|