Skip to content

Commit 9553e2e

Browse files
fix: skip hidden resolved comments during navigation (#322)
1 parent 4c87eaf commit 9553e2e

2 files changed

Lines changed: 88 additions & 17 deletions

File tree

assets/js/document-renderer.js

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4382,35 +4382,37 @@ function getInlineCommentCards(ctx) {
43824382
}
43834383

43844384
function navigateToComment(ctx, direction) {
4385-
const cards = getInlineCommentCards(ctx)
4385+
const allCards = getInlineCommentCards(ctx)
4386+
const isEligible = card => !isHideResolved(ctx) || !card.classList.contains('resolved-card')
4387+
const cards = allCards.filter(isEligible)
43864388
if (cards.length === 0) return
43874389

43884390
const header = document.querySelector('.crit-header')
43894391
const headerHeight = header ? header.offsetHeight : 52
43904392

4391-
// Find current position by stored comment ID (immune to smooth-scroll race conditions)
4393+
// Keep the current position in the full order even when that card becomes
4394+
// hidden, then scan in the requested direction for the next eligible card.
43924395
let idx = ctx._navCommentId
4393-
? cards.findIndex(c => c.dataset.commentId === ctx._navCommentId)
4396+
? allCards.findIndex(c => c.dataset.commentId === ctx._navCommentId)
43944397
: -1
43954398

4396-
let targetIdx
4397-
if (direction === 1) {
4398-
if (idx < 0) {
4399-
// First use: pick first card below the header area by viewport position
4400-
const firstBelow = cards.findIndex(c => c.getBoundingClientRect().top > headerHeight + 8)
4401-
targetIdx = firstBelow >= 0 ? firstBelow : 0
4402-
} else {
4403-
targetIdx = idx >= cards.length - 1 ? 0 : idx + 1
4399+
let target
4400+
if (idx >= 0) {
4401+
for (let step = 1; step <= allCards.length; step++) {
4402+
const candidateIdx = (idx + direction * step + allCards.length) % allCards.length
4403+
if (isEligible(allCards[candidateIdx])) {
4404+
target = allCards[candidateIdx]
4405+
break
4406+
}
44044407
}
4408+
} else if (direction === 1) {
4409+
// First use: pick first card below the header area by viewport position
4410+
const firstBelow = cards.findIndex(c => c.getBoundingClientRect().top > headerHeight + 8)
4411+
target = cards[firstBelow >= 0 ? firstBelow : 0]
44054412
} else {
4406-
if (idx < 0) {
4407-
targetIdx = cards.length - 1
4408-
} else {
4409-
targetIdx = idx <= 0 ? cards.length - 1 : idx - 1
4410-
}
4413+
target = cards[cards.length - 1]
44114414
}
44124415

4413-
const target = cards[targetIdx]
44144416
ctx._navCommentId = target.dataset.commentId
44154417

44164418
const rect = target.getBoundingClientRect()
@@ -4894,6 +4896,7 @@ export const DocumentRenderer = {
48944896
const newEl = createCommentElement(comment, ctx)
48954897
block.replaceWith(newEl)
48964898
}
4899+
applyHideResolved(ctx)
48974900
updateCommentCount(ctx)
48984901
updateTreeBadge(ctx, comment.file_path)
48994902
rerenderPanel(ctx)

e2e/hide-resolved.spec.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
deleteReview,
55
loadReview,
66
addCommentViaUI,
7+
seedComment,
78
} from "./helpers";
89

910
/**
@@ -129,6 +130,73 @@ test.describe("Hide Resolved", () => {
129130
await expect(resolvedBlock).toBeVisible();
130131
});
131132

133+
test("comment arrows skip hidden resolved comments in both directions", async ({
134+
page,
135+
request,
136+
}) => {
137+
await seedComment(request, token, {
138+
body: "Open A",
139+
startLine: 1,
140+
});
141+
await seedComment(request, token, {
142+
body: "Open C",
143+
startLine: 6,
144+
});
145+
await loadReview(page, token);
146+
await addAndResolveComment(page, "Resolved B", {
147+
lineIndex: 1,
148+
});
149+
150+
const openA = page
151+
.locator(".comment-card:not(.resolved-card)")
152+
.filter({ hasText: "Open A" });
153+
const resolvedCard = page
154+
.locator(".comment-card.resolved-card")
155+
.filter({ hasText: "Resolved B" });
156+
const openC = page
157+
.locator(".comment-card:not(.resolved-card)")
158+
.filter({ hasText: "Open C" });
159+
160+
await page.locator("#comment-nav-next").click();
161+
await expect(openA).toHaveClass(/comment-nav-highlight/);
162+
await page.locator("#comment-nav-next").click();
163+
await expect(resolvedCard).toHaveClass(/comment-nav-highlight/);
164+
165+
await page.keyboard.press("h");
166+
await expect(resolvedCard).not.toBeVisible();
167+
await page.locator("#comment-nav-prev").click();
168+
await expect(openA).toHaveClass(/comment-nav-highlight/);
169+
await expect(openC).not.toHaveClass(/comment-nav-highlight/);
170+
await expect(resolvedCard).not.toHaveClass(/comment-nav-highlight/);
171+
172+
await page.keyboard.press("h");
173+
await page.locator("#comment-nav-next").click();
174+
await expect(resolvedCard).toHaveClass(/comment-nav-highlight/);
175+
176+
await page.keyboard.press("h");
177+
await page.locator("#comment-nav-next").click();
178+
await expect(openC).toHaveClass(/comment-nav-highlight/);
179+
await expect(resolvedCard).not.toHaveClass(/comment-nav-highlight/);
180+
});
181+
182+
test("resolving a comment while hide resolved is enabled hides it", async ({
183+
page,
184+
}) => {
185+
await loadReview(page, token);
186+
await addCommentViaUI(page, "Resolve while hidden");
187+
await page.keyboard.press("h");
188+
189+
const card = page
190+
.locator(".comment-card")
191+
.filter({ hasText: "Resolve while hidden" });
192+
await card.locator(".resolve-btn").click();
193+
194+
const resolvedBlock = page
195+
.locator(".comment-block:not(.panel-comment-block)")
196+
.filter({ has: page.locator(".resolved-card") });
197+
await expect(resolvedBlock).not.toBeVisible();
198+
});
199+
132200
test("persists via localStorage across reload", async ({ page }) => {
133201
await loadReview(page, token);
134202

0 commit comments

Comments
 (0)