Show a thread reply count on its opening post

This commit is contained in:
Coracle-Bot 2026-09-22 13:53:20 +00:00
parent 3e85df5d02
commit 4e73de7592
6 changed files with 16 additions and 8 deletions

View file

@ -727,7 +727,7 @@ so that responses connect to the right thing.
Acceptance:
- "Reply to thread" opens a composer with no quoted parent, and submitting
appends a post and increments the reply count in the header.
appends a post and increments the reply count on the opening post.
- "Reply" on a single post shows "Replying to" that post, which can be cleared
before submitting.
- A reply to a thread in a room is tagged into that room, so the relay handles

View file

@ -754,8 +754,8 @@ test("US-043 reply to a thread and to a specific post", async ({seed, as}) => {
await expect(openingPost.getByText("OP", {exact: true})).toBeVisible()
await expect(bob.getByText("20 replies")).toBeVisible()
// The page bar carries the title, so the opening post does not repeat it.
await expect(bob.getByText("Bed rotation")).toHaveCount(1)
// The opening post carries the title, and the summary bar replaces it once it scrolls away.
await expect(openingPost).toContainText("Bed rotation")
await bob.getByRole("button", {name: "Reply to thread"}).click()
@ -975,6 +975,6 @@ test("US-045 turn a chat message into a thread", async ({seed, as}) => {
await row.click()
await expect(page.getByRole("heading", {name: "Deploy failures"})).toBeVisible()
await expect(page.locator("article").filter({hasText: "Deploy failures"})).toBeVisible()
await expect(page.getByText("the deploy broke again")).toBeVisible()
})

View file

@ -393,7 +393,7 @@ test("US-065 see quoted and embedded content", async ({seed, as}) => {
await page.waitForURL(next => next.pathname === `${spacePath(url)}/threads/${thread.id}`)
await expect(page.getByRole("heading", {name: "Roadmap for Q3"})).toBeVisible()
await expect(page.locator(`[data-event="${thread.id}"]`)).toContainText("Roadmap for Q3")
})
test("US-066 see distinctive inline tokens", async ({seed, as}) => {

View file

@ -791,7 +791,7 @@ test("US-112 see which threads are unread", async ({seed, as}) => {
await hers.click()
await expect(pageBar(bob)).toContainText("the server is on fire")
await expect(bob.locator("article").filter({hasText: "the server is on fire"})).toBeVisible()
// Opening a thread is what marks it read, so only the one he opened loses its dot
await bob.goBack()

View file

@ -25,9 +25,10 @@
threadPubkey: string
onReply: (event: TrustedEvent) => void
context: FeedContext
replyCount?: number
}
const {url, event, threadPubkey, onReply, context}: Props = $props()
const {url, event, threadPubkey, onReply, context, replyCount}: Props = $props()
const profileDisplay = $profiles.display(event.pubkey, [url]).$
const handle = $handles.forPubkey(event.pubkey).$
@ -69,7 +70,13 @@
<div
class="bg-surface flex flex-wrap items-center justify-between gap-2 border-b px-3 py-2 text-xs @lg:px-4 @lg:text-sm"
style="border-color: var(--line)">
<span class="opacity-75">{formatTimestamp(event.created_at)}</span>
<div class="flex items-center gap-2 opacity-75">
<span>{formatTimestamp(event.created_at)}</span>
{#if replyCount !== undefined}
<span>·</span>
<span>{replyCount} {replyCount === 1 ? "reply" : "replies"}</span>
{/if}
</div>
<Button
class="button button-ghost button-xs h-auto min-h-0 gap-1 px-1 py-0"
onclick={copyPermalink}>

View file

@ -174,6 +174,7 @@
{context}
event={$event}
threadPubkey={$event.pubkey}
replyCount={$replies.length}
onReply={openReply} />
</div>
{#if hiddenCount > 0}