From 6f5da76d309844fe8caf0e48920710355b702f55 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Thu, 18 Jun 2026 12:15:46 -0400 Subject: [PATCH] [comments] align count with displayed kinds + preserve multi-line content - discussionCountService now counts getAllowedCommentKinds() (NIP-22 kind 1111 + legacy kind 1) instead of 1111-only, so the discussion badge no longer undercounts threads that contain legacy comments. The count filters are derived from the same source the thread display uses, so they can't drift. - Add white-space: pre-wrap to .comment-thread__body so comments with line breaks/paragraphs preserve them instead of collapsing into one run-on line (long lines still wrap via word-break: break-word). Test: spec-corrected discussion-count-service to assert the count filters use getAllowedCommentKinds() (reverting to 1111-only fails the deepEqual). Co-Authored-By: Claude Opus 4.8 --- css/tailwind.source.css | 4 ++++ js/services/discussionCountService.js | 13 +++++++++---- tests/discussion-count-service.test.mjs | 19 ++++++++++++------- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/css/tailwind.source.css b/css/tailwind.source.css index c87b810f..f5073387 100644 --- a/css/tailwind.source.css +++ b/css/tailwind.source.css @@ -2721,6 +2721,10 @@ color: var(--text-primary); line-height: 1.6; word-break: break-word; + /* Comment content is inserted as a single text node, so preserve the + author's line breaks/paragraphs instead of collapsing them into one + run-on line. pre-wrap keeps newlines while still wrapping long lines. */ + white-space: pre-wrap; } .comment-thread__actions { diff --git a/js/services/discussionCountService.js b/js/services/discussionCountService.js index a519a7e0..bc80e74a 100644 --- a/js/services/discussionCountService.js +++ b/js/services/discussionCountService.js @@ -1,6 +1,6 @@ import { devLogger } from "../utils/logger.js"; import { buildVideoAddressPointer } from "../utils/videoPointer.js"; -import { COMMENT_EVENT_KIND } from "../nostr/commentEvents.js"; +import { getAllowedCommentKinds } from "../nostr/commentTargetNormalizer.js"; const DEFAULT_MAX_DISCUSSION_COUNT_VIDEOS = 24; const COUNT_UNSUPPORTED_TITLE = "Relay does not support NIP-45 COUNT queries."; @@ -131,17 +131,22 @@ export default class DiscussionCountService { return []; } + // Count the same kinds the thread actually displays (NIP-22 kind 1111 plus + // legacy kind 1). Counting only 1111 made the badge undercount threads that + // contain legacy comments. + const commentKinds = getAllowedCommentKinds(); + const filters = []; const eventId = typeof video.id === "string" ? video.id.trim() : ""; if (eventId) { - filters.push({ kinds: [COMMENT_EVENT_KIND], "#E": [eventId] }); + filters.push({ kinds: commentKinds, "#E": [eventId] }); } const address = buildVideoAddressPointer(video); const rootIdentifier = typeof video.videoRootId === "string" ? video.videoRootId.trim() : ""; - const uppercaseFilter = { kinds: [COMMENT_EVENT_KIND] }; + const uppercaseFilter = { kinds: commentKinds }; let hasUppercasePointer = false; if (rootIdentifier) { @@ -184,7 +189,7 @@ export default class DiscussionCountService { } if (address) { - filters.push({ kinds: [COMMENT_EVENT_KIND], "#A": [address] }); + filters.push({ kinds: commentKinds, "#A": [address] }); } return filters; diff --git a/tests/discussion-count-service.test.mjs b/tests/discussion-count-service.test.mjs index aa2fb5ec..0ccd5383 100644 --- a/tests/discussion-count-service.test.mjs +++ b/tests/discussion-count-service.test.mjs @@ -6,7 +6,12 @@ import { JSDOM } from "jsdom"; import DiscussionCountService, { COUNT_UNSUPPORTED_TITLE, } from "../js/services/discussionCountService.js"; -import { COMMENT_EVENT_KIND } from "../js/nostr/commentEvents.js"; +import { getAllowedCommentKinds } from "../js/nostr/commentTargetNormalizer.js"; + +// SPEC CHANGE: the discussion-count badge now counts the same kinds the thread +// displays (NIP-22 kind 1111 + legacy kind 1) instead of only 1111, so it no +// longer undercounts threads that contain legacy comments. +const COMMENT_KINDS = getAllowedCommentKinds(); function createDomWithCountElement(videoId) { const dom = new JSDOM(` @@ -39,17 +44,17 @@ async function testRefreshCountsCachesResults() { assert.equal(filters.length, 3, "should request id, uppercase, and address filters"); const [eventFilter, uppercaseFilter, addressFilter] = filters; assert.deepEqual(eventFilter, { - kinds: [COMMENT_EVENT_KIND], + kinds: COMMENT_KINDS, "#E": ["count-video-1"], }); assert.deepEqual(uppercaseFilter, { - kinds: [COMMENT_EVENT_KIND], + kinds: COMMENT_KINDS, "#A": ["30078:pubkey-1:identifier-1"], "#K": ["30078"], "#P": ["pubkey-1"], }); assert.deepEqual(addressFilter, { - kinds: [COMMENT_EVENT_KIND], + kinds: COMMENT_KINDS, "#A": ["30078:pubkey-1:identifier-1"], }); return { @@ -122,17 +127,17 @@ async function testUnsupportedRelaysUpdateDomState() { assert.equal(filters.length, 3, "unsupported relays should still receive all filters"); const [eventFilter, uppercaseFilter, addressFilter] = filters; assert.deepEqual(eventFilter, { - kinds: [COMMENT_EVENT_KIND], + kinds: COMMENT_KINDS, "#E": ["unsupported-video"], }); assert.deepEqual(uppercaseFilter, { - kinds: [COMMENT_EVENT_KIND], + kinds: COMMENT_KINDS, "#A": ["30078:pubkey-2:identifier-2"], "#K": ["30078"], "#P": ["pubkey-2"], }); assert.deepEqual(addressFilter, { - kinds: [COMMENT_EVENT_KIND], + kinds: COMMENT_KINDS, "#A": ["30078:pubkey-2:identifier-2"], }); return {