From ef9794ae1d02727a1cb9ec9c8572ccdc5b5de170 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Jan 2026 21:16:11 +0000 Subject: [PATCH] feat: implement NIP-22 comment thread adapter Add complete NIP-22 protocol adapter to treat kind 1111 comment threads as chat conversations. Root event is displayed with appropriate kind renderer, followed by all comments, zaps, and reactions. Key features: - Parse note/nevent/naddr identifiers for any event kind (except kind 1) - Smart relay selection using outbox relays and aggregator fallback - Full support for nested comment replies with proper NIP-22 tagging - Root message rendered with KindRenderer for proper event display - Zap and reaction support for individual comments - NIP-30 custom emoji and NIP-92 blob attachment support Files changed: - src/lib/chat/adapters/nip-22-adapter.ts: Core adapter implementation - src/lib/chat/adapters/nip-22-adapter.test.ts: Comprehensive test suite - src/types/chat.ts: Add NIP-22 protocol and CommentThreadIdentifier types - src/lib/chat-parser.ts: Register Nip22Adapter in priority order - src/components/ChatViewer.tsx: Add NIP-22 root message rendering - src/lib/nostr-utils.ts: Add getRootEventTitle() utility - src/types/man.ts: Update chat command documentation --- src/components/ChatViewer.tsx | 25 +- src/lib/chat-parser.ts | 11 +- src/lib/chat/adapters/nip-22-adapter.test.ts | 163 ++++ src/lib/chat/adapters/nip-22-adapter.ts | 790 +++++++++++++++++++ src/lib/nostr-utils.ts | 42 + src/types/chat.ts | 39 +- src/types/man.ts | 7 +- 7 files changed, 1065 insertions(+), 12 deletions(-) create mode 100644 src/lib/chat/adapters/nip-22-adapter.test.ts create mode 100644 src/lib/chat/adapters/nip-22-adapter.ts diff --git a/src/components/ChatViewer.tsx b/src/components/ChatViewer.tsx index af29920..2ed0376 100644 --- a/src/components/ChatViewer.tsx +++ b/src/components/ChatViewer.tsx @@ -26,6 +26,7 @@ import type { import { CHAT_KINDS } from "@/types/chat"; // import { NipC7Adapter } from "@/lib/chat/adapters/nip-c7-adapter"; // Coming soon import { Nip10Adapter } from "@/lib/chat/adapters/nip-10-adapter"; +import { Nip22Adapter } from "@/lib/chat/adapters/nip-22-adapter"; import { Nip29Adapter } from "@/lib/chat/adapters/nip-29-adapter"; import { Nip53Adapter } from "@/lib/chat/adapters/nip-53-adapter"; import type { ChatProtocolAdapter } from "@/lib/chat/adapters/base-adapter"; @@ -41,6 +42,7 @@ import { RelaysDropdown } from "./chat/RelaysDropdown"; import { MessageReactions } from "./chat/MessageReactions"; import { StatusBadge } from "./live/StatusBadge"; import { ChatMessageContextMenu } from "./chat/ChatMessageContextMenu"; +import { KindRenderer } from "./nostr/kinds"; import { useGrimoire } from "@/core/state"; import { Button } from "./ui/button"; import LoginDialog from "./nostr/LoginDialog"; @@ -278,6 +280,18 @@ const MessageItem = memo(function MessageItem({ [conversation], ); + // NIP-22 root messages: render with KindRenderer for proper event display + if (conversation.protocol === "nip-22" && message.metadata?.isRootMessage) { + return ( +
+
+ Commenting on: +
+ +
+ ); + } + // System messages (join/leave) have special styling if (message.type === "system") { return ( @@ -999,7 +1013,8 @@ export function ChatViewer({ Header: () => hasMore && conversationResult.status === "success" && - protocol !== "nip-10" ? ( + protocol !== "nip-10" && + protocol !== "nip-22" ? (