diff --git a/lua/fude/ui/format.lua b/lua/fude/ui/format.lua index b9c9211..a59427a 100644 --- a/lua/fude/ui/format.lua +++ b/lua/fude/ui/format.lua @@ -1,4 +1,5 @@ local M = {} +local util = require("fude.util") --- Normalize newlines by converting CRLF and CR to LF. --- @param s string|nil input string @@ -10,6 +11,10 @@ end --- Build status badges for a comment header (" [agent]", " [resolved]"). --- Local review comments carry author_type ("human"|"agent") and a --- thread-level resolved flag; GitHub comments have neither and get "". +--- `resolved` is a thread-level state that materialize() propagates to every +--- comment in the thread, so the `[resolved]` badge is shown only on the +--- thread's head comment (the root, which has no `in_reply_to_id`) to mark a +--- resolved thread once instead of repeating it on every reply. --- @param comment table comment object --- @return string badge suffix ("" when none apply) function M.comment_badges(comment) @@ -17,7 +22,7 @@ function M.comment_badges(comment) if comment.author_type == "agent" then badges = badges .. " [agent]" end - if comment.resolved then + if comment.resolved and util.is_null(comment.in_reply_to_id) then badges = badges .. " [resolved]" end return badges diff --git a/tests/fude/ui_spec.lua b/tests/fude/ui_spec.lua index ef7effb..049f217 100644 --- a/tests/fude/ui_spec.lua +++ b/tests/fude/ui_spec.lua @@ -61,6 +61,30 @@ describe("calculate_float_dimensions", function() end) end) +describe("comment_badges", function() + it("returns empty string for a plain GitHub comment", function() + assert.are.equal("", format.comment_badges({ user = { login = "a" } })) + end) + + it("adds [agent] for agent-authored comments regardless of reply depth", function() + assert.are.equal(" [agent]", format.comment_badges({ author_type = "agent" })) + assert.are.equal(" [agent]", format.comment_badges({ author_type = "agent", in_reply_to_id = 1 })) + end) + + it("adds [resolved] on a resolved thread root (no in_reply_to_id)", function() + assert.are.equal(" [resolved]", format.comment_badges({ resolved = true })) + assert.are.equal(" [resolved]", format.comment_badges({ resolved = true, in_reply_to_id = vim.NIL })) + end) + + it("omits [resolved] on a resolved reply (has in_reply_to_id)", function() + assert.are.equal("", format.comment_badges({ resolved = true, in_reply_to_id = 42 })) + end) + + it("combines [agent] and [resolved] on a resolved agent root", function() + assert.are.equal(" [agent] [resolved]", format.comment_badges({ author_type = "agent", resolved = true })) + end) +end) + describe("format_comments_for_display", function() local identity = function(s) return s or ""