Changeset 9d34855 in Klonkt


Ignore:
Timestamp:
06/26/2026 11:50:14 PM (2 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
0a75356
Parents:
c7ecaf9
Message:

fix(news): feed like is a toggle too (like/unlike), like boost

The feed star was fire-and-forget with no state. Now ap_timeline.liked remembers it,
the star shows an 'on' state, and a second click retracts via /news/unlike (Undo Like)
— mirroring the existing boost/unboost toggle. markLiked/unmarkLiked added.

Location:
src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/config/database.js

    rc7ecaf9 r9d34855  
    414414  // A timeline post you boosted (🔁) — also shown in the Cirkel (mixed by date).
    415415  ensureColumn('ap_timeline', 'boosted', 'INTEGER DEFAULT 0');
     416  ensureColumn('ap_timeline', 'liked', 'INTEGER DEFAULT 0'); // a feed post you liked (⭐) → toggle
    416417}
    417418
  • src/routes/posts.js

    rc7ecaf9 r9d34855  
    695695router.post('/news/like', requireSiteManager, async (req, res) => {
    696696  const site = res.locals.site;
    697   if (site) { try { await ActivityPubService.sendInteraction(site, 'like', (req.body.note || '').toString(), (req.body.author || '').toString()); } catch (e) { /* ignore */ } }
     697  const note = (req.body.note || '').toString();
     698  if (site && note) {
     699    try { await ActivityPubService.sendInteraction(site, 'like', note, (req.body.author || '').toString()); } catch (e) { /* ignore */ }
     700    ActivityPubService.markLiked(site.slug, note);
     701  }
    698702  res.redirect('/news?success=' + encodeURIComponent('Geliket ⭐'));
     703});
     704
     705router.post('/news/unlike', requireSiteManager, async (req, res) => {
     706  const site = res.locals.site;
     707  const note = (req.body.note || '').toString();
     708  if (site && note) {
     709    try { await ActivityPubService.sendInteraction(site, 'unlike', note, (req.body.author || '').toString()); } catch (e) { /* ignore */ }
     710    ActivityPubService.unmarkLiked(site.slug, note);
     711  }
     712  res.redirect('/news?success=' + encodeURIComponent('Like ingetrokken'));
    699713});
    700714
  • src/services/ActivityPubService.js

    rc7ecaf9 r9d34855  
    10991099  try { if (!_unmarkBoost) _unmarkBoost = db.prepare('UPDATE ap_timeline SET boosted = 0 WHERE slug = ? AND id = ?'); _unmarkBoost.run(slug, noteId); } catch { /* ignore */ }
    11001100}
     1101let _markLike, _unmarkLike;
     1102export function markLiked(slug, noteId) {
     1103  try { if (!_markLike) _markLike = db.prepare('UPDATE ap_timeline SET liked = 1 WHERE slug = ? AND id = ?'); _markLike.run(slug, noteId); } catch { /* ignore */ }
     1104}
     1105export function unmarkLiked(slug, noteId) {
     1106  try { if (!_unmarkLike) _unmarkLike = db.prepare('UPDATE ap_timeline SET liked = 0 WHERE slug = ? AND id = ?'); _unmarkLike.run(slug, noteId); } catch { /* ignore */ }
     1107}
    11011108export function boostedCount(slug) {
    11021109  try { if (!_boostedCount) _boostedCount = db.prepare('SELECT COUNT(*) AS n FROM ap_timeline WHERE slug = ? AND boosted = 1'); return _boostedCount.get(slug).n; } catch { return 0; }
     
    13491356  listOutbox, deliverOutboxDelete,
    13501357  webfingerResolve, followActor, resolveRemoteActor, unfollowActor, listFollowing, setAutoBoost, getTimeline, sendInteraction,
    1351   autoBoostCount, boostedCount, markBoosted, unmarkBoosted, getCirkelPosts, getCirkelMembers, selfHealTimeline,
     1358  autoBoostCount, boostedCount, markBoosted, unmarkBoosted, markLiked, unmarkLiked, getCirkelPosts, getCirkelMembers, selfHealTimeline,
    13521359  getNotifications, listBlocks, isBlockedAny, blockTarget, unblock,
    13531360  deliverWithRetry, enqueueDelivery, processDeliveryQueue, startDeliveryWorker,
  • src/views/pages/news.ejs

    rc7ecaf9 r9d34855  
    4747
    4848          <div class="tl-actions">
     49            <% if (p.liked) { %>
     50            <form method="post" action="/news/unlike" class="tl-act-form"><input type="hidden" name="note" value="<%= p.id %>"><input type="hidden" name="author" value="<%= p.author_uri %>"><button type="submit" class="tl-act tl-act-like is-on" title="<%= t('fedi.unlike_short') %>" aria-label="<%= t('fedi.unlike_short') %>"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><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></button></form>
     51            <% } else { %>
    4952            <form method="post" action="/news/like" class="tl-act-form"><input type="hidden" name="note" value="<%= p.id %>"><input type="hidden" name="author" value="<%= p.author_uri %>"><button type="submit" class="tl-act tl-act-like" title="<%= t('fedi.likes') %>" aria-label="<%= t('fedi.likes') %>"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><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></button></form>
     53            <% } %>
    5054            <% if (p.boosted) { %>
    5155            <form method="post" action="/news/unboost" class="tl-act-form"><input type="hidden" name="note" value="<%= p.id %>"><input type="hidden" name="author" value="<%= p.author_uri %>"><button type="submit" class="tl-act tl-act-boost is-on" title="<%= t('tl.unboost') %>" aria-label="<%= t('tl.unboost') %>"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><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></button></form>
     
    126130  .tl-act-like svg { color: #e8b04b; }
    127131  .tl-act-like:hover { background: color-mix(in srgb, #e8b04b 15%, transparent); border-color: color-mix(in srgb, #e8b04b 50%, transparent); }
     132  .tl-act-like.is-on { background: color-mix(in srgb, #e8b04b 18%, transparent); border-color: color-mix(in srgb, #e8b04b 60%, transparent); }
    128133  .tl-act-boost svg { color: #2fa85a; }
    129134  .tl-act-boost:hover { background: color-mix(in srgb, #2fa85a 15%, transparent); border-color: color-mix(in srgb, #2fa85a 50%, transparent); }
Note: See TracChangeset for help on using the changeset viewer.