mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-09 15:07:10 +02:00
feat: KINDS command
This commit is contained in:
3
TODO.md
3
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
|
||||
|
||||
97
src/components/KindsViewer.tsx
Normal file
97
src/components/KindsViewer.tsx
Normal file
@@ -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 (
|
||||
<div className="h-full w-full overflow-y-auto p-6">
|
||||
<div className="max-w-3xl mx-auto space-y-6">
|
||||
{/* Header */}
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold mb-2">
|
||||
Supported Event Kinds ({sortedKinds.length})
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Event kinds with rich rendering support in Grimoire. Default kinds
|
||||
display raw content only.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Kind List */}
|
||||
<div className="border border-border divide-y divide-border">
|
||||
{sortedKinds.map((kind) => {
|
||||
const kindInfo = getKindInfo(kind);
|
||||
const Icon = kindInfo?.icon;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={kind}
|
||||
className="p-4 hover:bg-muted/30 transition-colors"
|
||||
>
|
||||
<div className="flex items-start gap-4">
|
||||
{/* Icon */}
|
||||
<div className="w-10 h-10 bg-accent/20 rounded flex items-center justify-center flex-shrink-0">
|
||||
{Icon ? (
|
||||
<Icon className="w-5 h-5 text-accent" />
|
||||
) : (
|
||||
<span className="text-xs font-mono text-muted-foreground">
|
||||
{kind}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-baseline gap-2 mb-1">
|
||||
<code className="text-sm font-mono font-semibold">
|
||||
{kind}
|
||||
</code>
|
||||
<span className="text-sm font-semibold">
|
||||
{kindInfo?.name || `Kind ${kind}`}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground mb-2">
|
||||
{kindInfo?.description || "No description available"}
|
||||
</p>
|
||||
{kindInfo?.nip && (
|
||||
<Command
|
||||
name={`NIP-${kindInfo.nip}`}
|
||||
description={`View specification`}
|
||||
appId="nip"
|
||||
props={{ number: kindInfo.nip }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -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 = <KindRenderer kind={parseInt(window.props.number)} />;
|
||||
break;
|
||||
case "kinds":
|
||||
content = <KindsViewer />;
|
||||
break;
|
||||
case "man":
|
||||
content = <ManPage cmd={window.props.cmd} />;
|
||||
break;
|
||||
|
||||
@@ -3,6 +3,7 @@ import { MosaicNode } from "react-mosaic-component";
|
||||
export type AppId =
|
||||
| "nip"
|
||||
| "kind"
|
||||
| "kinds"
|
||||
| "man"
|
||||
| "feed"
|
||||
| "win"
|
||||
|
||||
@@ -87,6 +87,18 @@ export const manPages: Record<string, ManPageEntry> = {
|
||||
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",
|
||||
|
||||
Reference in New Issue
Block a user