From 26c978740e868cdcceb7e35c67803b8544a82753 Mon Sep 17 00:00:00 2001 From: oppiliappan Date: Thu, 30 Jul 2026 00:12:53 +0100 Subject: [PATCH] web/routes: load reactions on visiting issues page Signed-off-by: oppiliappan --- .../[repo]/issues/[aturi]/+page.svelte | 7 +++ .../[handle]/[repo]/issues/[aturi]/+page.ts | 51 +++++++++++++++++-- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/web/src/routes/[handle]/[repo]/issues/[aturi]/+page.svelte b/web/src/routes/[handle]/[repo]/issues/[aturi]/+page.svelte index 521e7bac..03fa33c6 100644 --- a/web/src/routes/[handle]/[repo]/issues/[aturi]/+page.svelte +++ b/web/src/routes/[handle]/[repo]/issues/[aturi]/+page.svelte @@ -5,6 +5,7 @@ import IssueLabelPanel from "$lib/components/repo/issues/IssueLabelPanel.svelte"; import CommentList from "$lib/components/comment/CommentList.svelte"; import CommentBox from "$lib/components/comment/CommentBox.svelte"; + import Reactions from "$lib/components/reaction/Reactions.svelte"; import SignupPrompt from "$lib/components/ui/SignupPrompt.svelte"; import TabPanel from "$lib/components/ui/TabPanel.svelte"; import IssueForm from "$lib/components/repo/issues/IssueForm.svelte"; @@ -143,6 +144,12 @@ actions={isAuthor ? issueActions : undefined} /> + {#if deleteError}
diff --git a/web/src/routes/[handle]/[repo]/issues/[aturi]/+page.ts b/web/src/routes/[handle]/[repo]/issues/[aturi]/+page.ts index e7fea91b..dcf87dff 100644 --- a/web/src/routes/[handle]/[repo]/issues/[aturi]/+page.ts +++ b/web/src/routes/[handle]/[repo]/issues/[aturi]/+page.ts @@ -1,10 +1,18 @@ import { error } from "@sveltejs/kit"; import { createBobbinClient } from "$lib/api/client"; import { IdentityCache } from "$lib/api/identity"; -import { getIssue, listComments, listIssueStates } from "$lib/api/records"; +import { + getIssue, + listComments, + listIssueStates, + listReactions, + type RecordView, + type ReactionRecord +} from "$lib/api/records"; import { didFromUri, rkeyFromUri } from "$lib/api/uri"; import { renderMarkup } from "$lib/markup"; import { buildCommentThreads, type ThreadInput } from "$lib/components/comment/comments"; +import { buildReactions, type ReactionGroup } from "$lib/components/reaction/reactions"; import type { PageLoad } from "./$types"; export const load: PageLoad = async (event) => { @@ -34,11 +42,42 @@ export const load: PageLoad = async (event) => { const latest = states?.items[0]?.value.state; const state = latest?.endsWith(".closed") ? ("closed" as const) : ("open" as const); - const body = record.value.body ?? ""; const bodyHtml = body ? await renderMarkup(body, markupOpts) : null; - + const viewerDid = parent.auth?.did; const commentItems = comments?.items ?? []; + + // reactions: one listReactions per subject (the issue itself + each comment). + // bobbin has no batch-by-subject query and enrich can't break counts down by + // emoji, so we fan out and group client-side. empty subjects come back empty. + const subjects = [record.uri, ...commentItems.map((item) => item.uri)]; + const reactionPages = await Promise.all( + subjects.map((subject) => + listReactions(ctx, subject, { order: "asc", limit: 100 }).catch(() => null) + ) + ); + const reactionsBySubject = new Map[]>(); + subjects.forEach((subject, i) => reactionsBySubject.set(subject, reactionPages[i]?.items ?? [])); + + // resolve every reactor's handle once for the whole page (IdentityCache dedups) + const reactorDids = new Set(); + for (const items of reactionsBySubject.values()) { + for (const item of items) reactorDids.add(didFromUri(item.uri)); + } + const reactorHandles = new Map(); + await Promise.all( + [...reactorDids].map(async (did) => { + const doc = await identities.resolve(did).catch(() => null); + reactorHandles.set(did, doc?.handle ?? did); + }) + ); + const reactionsFor = (subject: string): ReactionGroup[] => + buildReactions( + reactionsBySubject.get(subject) ?? [], + viewerDid, + (did) => reactorHandles.get(did) ?? did + ); + const threadInputs: ThreadInput[] = await Promise.all( commentItems.map(async (item): Promise => { const commentDid = didFromUri(item.uri); @@ -56,7 +95,8 @@ export const load: PageLoad = async (event) => { authorHandle: doc?.handle ?? commentDid, createdAt: item.value.createdAt, body: commentBody, - bodyHtml: commentBodyHtml + bodyHtml: commentBodyHtml, + reactions: reactionsFor(item.uri) }, replyTo: item.value.replyTo?.uri ?? null, replyToCid: item.value.replyTo?.cid @@ -75,7 +115,8 @@ export const load: PageLoad = async (event) => { state, authorDid, authorHandle: author?.handle ?? authorDid, - createdAt: record.value.createdAt + createdAt: record.value.createdAt, + reactions: reactionsFor(record.uri) }, comments: buildCommentThreads(threadInputs), markup: markupOpts -- 2.51.2