- Timestamp:
- 08/06/2026 09:10:41 AM (5 weeks ago)
- Branches:
- main
- Children:
- 68a4d1b
- Parents:
- 0e27e54
- git-author:
- Robin <roboburr@…> (08/06/2026 09:10:40 AM)
- git-committer:
- Claude (agent) <aiclaude@…> (08/06/2026 09:10:41 AM)
- Location:
- src
- Files:
-
- 3 edited
-
routes/activitypub.js (modified) (2 diffs)
-
routes/posts.js (modified) (5 diffs)
-
services/ActivityPubService.js (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/routes/activitypub.js
r0e27e54 r14f7cb2 285 285 const playbackAllowed = embedsAllowed 286 286 && Guardianship.externalPlaybackAllowed(auth.site.external_playback, isWard); 287 const posts = AP.getTimeline(auth.site.slug, 60).map((t) => ({ 287 const rows = AP.getTimeline(auth.site.slug, 60); 288 // Eén query voor de hele pagina (shaer-9e9 fase 2): shaer:liked komt uit de 289 // tussentabel, de bron van waarheid, en niet meer uit de afgeleide kolom op 290 // ap_timeline. Per rij vragen zou hier een N+1 opleveren. 291 const reacties = AP.getReactionsFor(auth.site.slug, rows.map((t) => t.id)); 292 const posts = rows.map((t) => ({ 288 293 id: `${t.id}#create`, 289 294 type: 'Create', … … 333 338 // Whether THIS account already liked/boosted the note, so the app's 334 339 // detail-view buttons show the current state (and can toggle/undo). 335 'shaer:liked': !! t.liked,336 'shaer:boosted': !! t.boosted,340 'shaer:liked': !!(reacties.get(t.id) || {}).liked, 341 'shaer:boosted': !!(reacties.get(t.id) || {}).boosted, 337 342 // An external (non-fediverse) embed, thumbnail-only and never an iframe. 338 343 // Omitted entirely when the gate is closed (see above). -
src/routes/posts.js
r0e27e54 r14f7cb2 806 806 liked: !!req.query.liked, 807 807 boosted: !!req.query.boosted, 808 reacted: (site && uri) ? ActivityPubService.get MyReactions(site.slug, uri) : { liked: false, boosted: false },808 reacted: (site && uri) ? ActivityPubService.getReaction(site.slug, uri) : { liked: false, boosted: false }, 809 809 siteTitle: site ? site.title : '', 810 810 }); … … 839 839 let on = false; 840 840 if (site && uri) { 841 on = !ActivityPubService.get MyReactions(site.slug, uri).liked;841 on = !ActivityPubService.getReaction(site.slug, uri).liked; 842 842 ActivityPubService.resolveRemoteNote(uri) 843 843 .then((note) => note && ActivityPubService.sendInteraction(site, on ? 'like' : 'unlike', note.object_uri || uri, note.actor_uri)) … … 857 857 let on = false; 858 858 if (site && uri) { 859 on = !ActivityPubService.get MyReactions(site.slug, uri).boosted;859 on = !ActivityPubService.getReaction(site.slug, uri).boosted; 860 860 ActivityPubService.resolveRemoteNote(uri) 861 861 .then((note) => { … … 1280 1280 let on = false; 1281 1281 if (site && note) { 1282 on = !ActivityPubService.get TimelineReaction(site.slug, note).liked;1282 on = !ActivityPubService.getReaction(site.slug, note).liked; 1283 1283 try { await ActivityPubService.sendInteraction(site, on ? 'like' : 'unlike', note, (req.body.author || '').toString()); } catch (e) { /* ignore */ } 1284 1284 ActivityPubService.setReaction(site.slug, note, 'like', on); … … 1294 1294 let on = false; 1295 1295 if (site && note) { 1296 on = !ActivityPubService.get TimelineReaction(site.slug, note).boosted;1296 on = !ActivityPubService.getReaction(site.slug, note).boosted; 1297 1297 try { await ActivityPubService.sendInteraction(site, on ? 'boost' : 'unboost', note, (req.body.author || '').toString()); } catch (e) { /* ignore */ } 1298 1298 ActivityPubService.setReaction(site.slug, note, 'boost', on); // instant UI state -
src/services/ActivityPubService.js
r0e27e54 r14f7cb2 3429 3429 * werk voor fase 2, mét datamigratie. 3430 3430 */ 3431 /** 3432 * Wat heb IK met dit object gedaan? Leest de tussentabel, de bron van waarheid 3433 * sinds shaer-9e9 fase 2. Vervangt getMyReactions en getTimelineReaction, die 3434 * dezelfde vraag beantwoordden uit twee verschillende bronnen. 3435 */ 3436 export function getReaction(slug, uri) { 3437 try { 3438 const rows = (slug && uri) 3439 ? db.prepare('SELECT kind FROM ap_my_reactions WHERE site_slug = ? AND target_uri = ?').all(slug, uri) 3440 : []; 3441 return { liked: rows.some((r) => r.kind === 'like'), boosted: rows.some((r) => r.kind === 'boost') }; 3442 } catch { return { liked: false, boosted: false }; } 3443 } 3444 3445 /** 3446 * Dezelfde vraag voor een hele pagina in EEN query. De C2S-tijdlijn zet 3447 * shaer:liked op elke post; per rij vragen zou dat een N+1 maken, en dan had je 3448 * een consistentiebug geruild voor een traagheidsbug. 3449 */ 3450 export function getReactionsFor(slug, uris) { 3451 const out = new Map(); 3452 const list = [...new Set((uris || []).filter(Boolean))].slice(0, 500); 3453 if (!slug || !list.length) return out; 3454 try { 3455 const rows = db.prepare( 3456 `SELECT target_uri, kind FROM ap_my_reactions 3457 WHERE site_slug = ? AND target_uri IN (${list.map(() => '?').join(',')})`, 3458 ).all(slug, ...list); 3459 for (const r of rows) { 3460 const cur = out.get(r.target_uri) || { liked: false, boosted: false }; 3461 if (r.kind === 'like') cur.liked = true; 3462 if (r.kind === 'boost') cur.boosted = true; 3463 out.set(r.target_uri, cur); 3464 } 3465 } catch { /* leeg = niets gereageerd, en dat is een veilige uitkomst */ } 3466 return out; 3467 } 3468 3431 3469 export function setReaction(slug, uri, kind, on, opts = {}) { 3432 3470 if (!slug || !uri || (kind !== 'like' && kind !== 'boost')) return; … … 4809 4847 gateOutgoingFollow, performApprovedFollow, 4810 4848 parseOwnPoll, pollTally, ownPollView, deliverPollUpdate, maybeCrawlThread, sendReport, localMentionSlugs, 4811 autoBoostCount, boostedCount, markBoosted, unmarkBoosted, markLiked, unmarkLiked, setReaction, get TimelineReaction, upsertBoostedNote, getCirkelPosts, getCirkelMembers, selfHealTimeline,4849 autoBoostCount, boostedCount, markBoosted, unmarkBoosted, markLiked, unmarkLiked, setReaction, getReaction, getReactionsFor, getTimelineReaction, upsertBoostedNote, getCirkelPosts, getCirkelMembers, selfHealTimeline, 4812 4850 getNotifications, listBlocks, isBlockedAny, blockTarget, unblock, 4813 4851 deliverWithRetry, enqueueDelivery, processDeliveryQueue, startDeliveryWorker,
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)