Changeset c745659 in Klonkt
- Timestamp:
- 06/26/2026 11:25:14 PM (2 months ago)
- Branches:
- main
- Children:
- 3289a64
- Parents:
- eacd3d6
- Location:
- src
- Files:
-
- 5 edited
-
config/database.js (modified) (1 diff)
-
routes/posts.js (modified) (1 diff)
-
services/ActivityPubService.js (modified) (4 diffs)
-
views/pages/post.ejs (modified) (1 diff)
-
views/partials/fedi-node.ejs (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/config/database.js
reacd3d6 rc745659 356 356 `); 357 357 ensureColumn('ap_interactions', 'parent_uri', 'TEXT'); // nesting (existing DBs) 358 ensureColumn('ap_interactions', 'acted_boost', 'INTEGER DEFAULT 0'); // owner boosted this comment (🔁) → can undo 358 359 359 360 // Fediverse CLIENT: accounts WE follow (outbound) + the home timeline of their posts. -
src/routes/posts.js
reacd3d6 rc745659 1015 1015 const kind = req.body.kind === 'boost' ? 'boost' : 'like'; 1016 1016 if (parent && parent.post_id === post.id && parent.object_uri) { 1017 ActivityPubService.sendInteraction(site, kind, parent.object_uri, parent.actor_uri) 1018 .catch((e) => console.warn('[AP] reaction failed:', e.message)); 1017 if (kind === 'boost') { 1018 // Toggle: boost an unboosted comment, or retract it (Undo Announce) if already boosted. 1019 const on = !parent.acted_boost; 1020 ActivityPubService.sendInteraction(site, on ? 'boost' : 'unboost', parent.object_uri, parent.actor_uri) 1021 .catch((e) => console.warn('[AP] reaction failed:', e.message)); 1022 ActivityPubService.setInteractionBoosted(parent.id, on); 1023 } else { 1024 ActivityPubService.sendInteraction(site, 'like', parent.object_uri, parent.actor_uri) 1025 .catch((e) => console.warn('[AP] reaction failed:', e.message)); 1026 } 1019 1027 } 1020 1028 res.redirect(`${res.locals.siteUrlBase || ''}/${post.slug}#fediverse`); -
src/services/ActivityPubService.js
reacd3d6 rc745659 352 352 _delLA = db.prepare('DELETE FROM ap_interactions WHERE kind = ? AND post_id = ? AND actor_uri = ?'); 353 353 _delReply = db.prepare("DELETE FROM ap_interactions WHERE kind = 'reply' AND object_uri = ?"); 354 _listI = db.prepare('SELECT id, kind, object_uri, parent_uri, actor_uri, actor_name, actor_handle, actor_url, actor_icon, content, published, created_at FROM ap_interactions WHERE post_id = ? ORDER BY created_at ASC');354 _listI = db.prepare('SELECT id, kind, object_uri, parent_uri, actor_uri, actor_name, actor_handle, actor_url, actor_icon, content, published, created_at, acted_boost FROM ap_interactions WHERE post_id = ? ORDER BY created_at ASC'); 355 355 _getI = db.prepare('SELECT * FROM ap_interactions WHERE id = ?'); 356 356 _insO = db.prepare('INSERT INTO ap_outbox (id, site_slug, post_id, post_slug, in_reply_to, to_actor, to_handle, content, created_at) VALUES (?,?,?,?,?,?,?,?,CURRENT_TIMESTAMP)'); … … 362 362 363 363 export function getInteractionById(id) { return iStmts().getI.get(id); } 364 export function setInteractionBoosted(id, on) { 365 db.prepare('UPDATE ap_interactions SET acted_boost = ? WHERE id = ?').run(on ? 1 : 0, id); 366 } 364 367 365 368 const localPostExists = (id) => { try { return !!db.prepare('SELECT 1 FROM posts WHERE id = ?').get(id); } catch { return false; } }; … … 420 423 actor_name: r.actor_name, actor_handle: r.actor_handle, actor_url: r.actor_url, 421 424 actor_icon: r.actor_icon, content: r.content, created_at: r.published || r.created_at, 425 acted_boost: !!r.acted_boost, 422 426 children: [], 423 427 }); … … 1327 1331 buildActor, buildNote, buildCreate, buildOutbox, buildFollowers, buildFeatured, 1328 1332 followerCount, deliver, fetchActor, verifyRequest, handleInbox, deliverCreate, deliverDelete, deliverUpdate, deliverActorUpdate, resyncFeaturedPins, 1329 getInteractions, getInteractionById, buildReplyNote, getOutboxNote, deliverReply, resolveRemoteNote,1333 getInteractions, getInteractionById, setInteractionBoosted, buildReplyNote, getOutboxNote, deliverReply, resolveRemoteNote, 1330 1334 listOutbox, deliverOutboxDelete, 1331 1335 webfingerResolve, followActor, resolveRemoteActor, unfollowActor, listFollowing, setAutoBoost, getTimeline, sendInteraction, -
src/views/pages/post.ejs
reacd3d6 rc745659 325 325 .comment-delete-btn:hover { color: #c33; } 326 326 327 /* Owner comment-action icons — same visual language as the News feed, compact (30px). */ 328 .fedi-cact { width: 30px; height: 30px; flex: 0 0 30px; border-radius: 50%; padding: 0; box-sizing: border-box; 329 display: inline-flex; align-items: center; justify-content: center; list-style: none; 330 border: 1px solid color-mix(in srgb, var(--ink, #000) 14%, transparent); 331 background: color-mix(in srgb, var(--ink, #000) 3%, transparent); 332 color: var(--ink-soft, #888); cursor: pointer; -webkit-tap-highlight-color: transparent; 333 transition: background .12s, border-color .12s, transform .1s; } 334 .fedi-cact::-webkit-details-marker { display: none; } 335 .fedi-cact svg { width: 15px; height: 15px; display: block; } 336 .fedi-cact:active { transform: scale(.9); } 337 .fedi-cact-like svg { color: #e8b04b; } 338 .fedi-cact-like:hover { background: color-mix(in srgb, #e8b04b 15%, transparent); border-color: color-mix(in srgb, #e8b04b 50%, transparent); } 339 .fedi-cact-boost svg { color: #2fa85a; } 340 .fedi-cact-boost:hover { background: color-mix(in srgb, #2fa85a 15%, transparent); border-color: color-mix(in srgb, #2fa85a 50%, transparent); } 341 .fedi-cact-boost.is-on { background: color-mix(in srgb, #2fa85a 18%, transparent); border-color: color-mix(in srgb, #2fa85a 60%, transparent); } 342 .fedi-cact-reply svg { color: var(--accent, #06c); } 343 .fedi-cact-reply:hover { background: color-mix(in srgb, var(--accent, #888) 14%, transparent); border-color: color-mix(in srgb, var(--accent, #888) 50%, transparent); } 344 327 345 .comment-replies { 328 346 margin-top: 1rem; -
src/views/partials/fedi-node.ejs
reacd3d6 rc745659 22 22 <input type="hidden" name="interaction_id" value="<%= n.id %>"> 23 23 <input type="hidden" name="kind" value="like"> 24 <button type="submit" class=" comment-reply-btn">⭐ <%= t('fedi.like_short') %></button>24 <button type="submit" class="fedi-cact fedi-cact-like" title="<%= t('fedi.like_short') %>" aria-label="<%= t('fedi.like_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> 25 25 </form> 26 26 <form method="post" action="<%= _base %>/posts/<%= postSlug %>/fedi-react" class="fedi-owner-react"> 27 27 <input type="hidden" name="interaction_id" value="<%= n.id %>"> 28 28 <input type="hidden" name="kind" value="boost"> 29 <button type="submit" class=" comment-reply-btn">🔁 <%= t('fedi.boost_short') %></button>29 <button type="submit" class="fedi-cact fedi-cact-boost<%= n.acted_boost ? ' is-on' : '' %>" title="<%= n.acted_boost ? t('tl.unboost') : t('fedi.boost_short') %>" aria-label="<%= n.acted_boost ? t('tl.unboost') : t('fedi.boost_short') %>"><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> 30 30 </form> 31 31 <details class="fedi-owner-reply"> 32 <summary class="comment-reply-btn"> 33 <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 0 0-4-4H4"/></svg> 34 <%= t('fedi.remote_reply_short') %> 35 </summary> 32 <summary class="fedi-cact fedi-cact-reply" title="<%= t('fedi.remote_reply_short') %>" aria-label="<%= t('fedi.remote_reply_short') %>"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 0 0-4-4H4"/></svg></summary> 36 33 <form method="post" action="<%= _base %>/posts/<%= postSlug %>/fedi-reply" class="comment-reply-form"> 37 34 <input type="hidden" name="interaction_id" value="<%= n.id %>">
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)