Skip to content

Commit d3cb4d8

Browse files
sideshowbarkerchmouel
authored andcommitted
feat: show reply count for each comment in List view
Comments with replies now display a count like "[3 replies]" between the line number and the resolved status. Uses singular "reply" for one reply and plural "replies" for multiple.
1 parent b599d44 commit d3cb4d8

3 files changed

Lines changed: 81 additions & 4 deletions

File tree

DESIGN.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,11 @@ The browse command provides two interactive views:
147147
├───────────────────────────────────────────────────────────────────────┤
148148
│ │
149149
│ > src/components/Button.tsx │
150-
│ @reviewer: Consider using memo here... (unresolved) │
151-
│ @author: Good point, I'll update... (resolved) │
150+
│ @reviewer Line 42 [2 replies] (unresolved) │
151+
│ @author Line 15 (resolved) │
152152
│ │
153153
│ > src/utils/format.ts │
154-
│ @reviewer: This could be simplified... (unresolved) │
154+
│ @reviewer Line 8 [1 reply] (unresolved) │
155155
│ │
156156
├───────────────────────────────────────────────────────────────────────┤
157157
│ arrows:navigate enter:view o:open r:resolve Q:quote a:agent │

cmd/browse.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,18 @@ func (r *browseItemRenderer) Title(item BrowseItem) string {
592592
// Comment Metadata
593593
style := ui.NewReviewListStyle(item.Comment.Author, item.Comment.IsResolved())
594594
// Indent with tree structure
595-
return fmt.Sprintf(" └── %s Line %d %s", style.FormatCommentTitle(item.Comment.ID), item.Comment.Line, style.Status.Format(true))
595+
title := fmt.Sprintf(" └── %s Line %d", style.FormatCommentTitle(item.Comment.ID), item.Comment.Line)
596+
// Add reply count if there are replies
597+
if len(item.Comment.ThreadComments) > 0 {
598+
replyCount := len(item.Comment.ThreadComments)
599+
replyText := "reply"
600+
if replyCount > 1 {
601+
replyText = "replies"
602+
}
603+
title += fmt.Sprintf(" [%d %s]", replyCount, replyText)
604+
}
605+
title += " " + style.Status.Format(true)
606+
return title
596607
}
597608

598609
func (r *browseItemRenderer) Description(item BrowseItem) string {

cmd/browse_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,72 @@ func TestBuildCommentTree(t *testing.T) {
252252
}
253253
}
254254

255+
func TestBrowseItemRenderer_Title_ReplyCount(t *testing.T) {
256+
renderer := &browseItemRenderer{
257+
repo: "owner/repo",
258+
prNumber: 123,
259+
collapsedFiles: make(map[string]bool),
260+
}
261+
262+
tests := []struct {
263+
name string
264+
replyCount int
265+
wantContains string
266+
wantNotContain string
267+
}{
268+
{
269+
name: "no replies shows no count",
270+
replyCount: 0,
271+
wantContains: "",
272+
wantNotContain: "repl",
273+
},
274+
{
275+
name: "one reply shows singular",
276+
replyCount: 1,
277+
wantContains: "[1 reply]",
278+
},
279+
{
280+
name: "multiple replies shows plural",
281+
replyCount: 3,
282+
wantContains: "[3 replies]",
283+
},
284+
}
285+
286+
for _, tt := range tests {
287+
t.Run(tt.name, func(t *testing.T) {
288+
var threadComments []github.ThreadComment
289+
for i := 0; i < tt.replyCount; i++ {
290+
threadComments = append(threadComments, github.ThreadComment{
291+
ID: int64(100 + i),
292+
Author: "replier",
293+
Body: "Reply body",
294+
})
295+
}
296+
297+
item := BrowseItem{
298+
Type: "comment",
299+
Path: "src/main.go",
300+
Comment: &github.ReviewComment{
301+
ID: 123,
302+
Author: "reviewer",
303+
Body: "Original comment",
304+
Line: 42,
305+
ThreadComments: threadComments,
306+
},
307+
}
308+
309+
title := renderer.Title(item)
310+
311+
if tt.wantContains != "" && !strings.Contains(title, tt.wantContains) {
312+
t.Errorf("Title should contain %q, got: %q", tt.wantContains, title)
313+
}
314+
if tt.wantNotContain != "" && strings.Contains(title, tt.wantNotContain) {
315+
t.Errorf("Title should not contain %q, got: %q", tt.wantNotContain, title)
316+
}
317+
})
318+
}
319+
}
320+
255321
func TestStripMarkdownForPreview(t *testing.T) {
256322
tests := []struct {
257323
name string

0 commit comments

Comments
 (0)