From bdfb41c68fa19c6fd76c74cb7841cdb0f6a8cc29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20G=C3=B3mez?= Date: Thu, 11 Dec 2025 11:21:33 +0100 Subject: [PATCH] feat: KINDS command --- TODO.md | 3 + src/components/KindsViewer.tsx | 97 +++++++++++++++++++++++++++++++ src/components/WindowRenderer.tsx | 4 ++ src/types/app.ts | 1 + src/types/man.ts | 12 ++++ 5 files changed, 117 insertions(+) create mode 100644 src/components/KindsViewer.tsx diff --git a/TODO.md b/TODO.md index cb2744f..080c1d9 100644 --- a/TODO.md +++ b/TODO.md @@ -34,3 +34,6 @@ avoid inserting `br`, look into noStrudel's eol metadata ## TODO: window crashes on unsupported kind event ## TODO: app-wide error boundary. splash crash screen. +## TODO: collapsible relay list -> user relaylink without inbox/outbox icon + +## TODO: use NIP badges everywhere for linking NIPs diff --git a/src/components/KindsViewer.tsx b/src/components/KindsViewer.tsx new file mode 100644 index 0000000..4d24dc6 --- /dev/null +++ b/src/components/KindsViewer.tsx @@ -0,0 +1,97 @@ +import { getKindInfo } from "@/constants/kinds"; +import Command from "./Command"; + +// Supported kinds with rich renderers +const SUPPORTED_KINDS = [ + 0, // Profile Metadata + 1, // Short Text Note + 3, // Contact List + 6, // Repost + 7, // Reaction + 20, // Picture (NIP-68) + 21, // Video Event (NIP-71) + 22, // Short Video (NIP-71) + 1063, // File Metadata (NIP-94) + 1111, // Post + 9735, // Zap Receipt + 9802, // Highlight + 10002, // Relay List Metadata (NIP-65) + 30023, // Long-form Article +]; + +/** + * KindsViewer - System introspection command + * Shows all event kinds with rich rendering support + */ +export default function KindsViewer() { + // Sort kinds in ascending order + const sortedKinds = [...SUPPORTED_KINDS].sort((a, b) => a - b); + + return ( +
+
+ {/* Header */} +
+

+ Supported Event Kinds ({sortedKinds.length}) +

+

+ Event kinds with rich rendering support in Grimoire. Default kinds + display raw content only. +

+
+ + {/* Kind List */} +
+ {sortedKinds.map((kind) => { + const kindInfo = getKindInfo(kind); + const Icon = kindInfo?.icon; + + return ( +
+
+ {/* Icon */} +
+ {Icon ? ( + + ) : ( + + {kind} + + )} +
+ + {/* Content */} +
+
+ + {kind} + + + {kindInfo?.name || `Kind ${kind}`} + +
+

+ {kindInfo?.description || "No description available"} +

+ {kindInfo?.nip && ( + + )} +
+
+
+ ); + })} +
+
+
+ ); +} diff --git a/src/components/WindowRenderer.tsx b/src/components/WindowRenderer.tsx index d1494c4..28ccccb 100644 --- a/src/components/WindowRenderer.tsx +++ b/src/components/WindowRenderer.tsx @@ -11,6 +11,7 @@ import EncodeViewer from "./EncodeViewer"; import DecodeViewer from "./DecodeViewer"; import { RelayViewer } from "./RelayViewer"; import KindRenderer from "./KindRenderer"; +import KindsViewer from "./KindsViewer"; import Feed from "./nostr/Feed"; import { WinViewer } from "./WinViewer"; import { DebugViewer } from "./DebugViewer"; @@ -101,6 +102,9 @@ export function WindowRenderer({ window, onClose }: WindowRendererProps) { case "kind": content = ; break; + case "kinds": + content = ; + break; case "man": content = ; break; diff --git a/src/types/app.ts b/src/types/app.ts index 69ad082..f19e803 100644 --- a/src/types/app.ts +++ b/src/types/app.ts @@ -3,6 +3,7 @@ import { MosaicNode } from "react-mosaic-component"; export type AppId = | "nip" | "kind" + | "kinds" | "man" | "feed" | "win" diff --git a/src/types/man.ts b/src/types/man.ts index eae477f..904c92a 100644 --- a/src/types/man.ts +++ b/src/types/man.ts @@ -87,6 +87,18 @@ export const manPages: Record = { category: "System", defaultProps: { cmd: "help" }, }, + kinds: { + name: "kinds", + section: "1", + synopsis: "kinds", + description: + "Display all Nostr event kinds with rich rendering support in Grimoire. Shows kind numbers, names, descriptions, and links to their defining NIPs.", + examples: ["kinds View all supported event kinds"], + seeAlso: ["kind", "nip", "man"], + appId: "kinds", + category: "System", + defaultProps: {}, + }, // debug: { // name: "debug", // section: "1",