@@ -1036,35 +1024,47 @@ function StreamContent({ event }: { event: NostrEvent }) {
);
}
-function RepostHeader({ pubkey }: { pubkey: string }) {
- const author = useAuthor(pubkey);
- const name = author.data?.metadata?.name || genUserName(pubkey);
- const url = useProfileUrl(pubkey, author.data?.metadata);
-
- return (
-
-
-
-
-
- {author.isLoading ? (
-
- ) : (
- e.stopPropagation()}
- >
- {author.data?.event ? {name} : name}
-
- )}
- reposted
-
-
- );
+interface EventActionHeaderProps {
+ /** Pubkey of the person performing the action. */
+ pubkey: string;
+ /** Lucide icon component shown to the left of the author name. */
+ icon: React.ComponentType<{ className?: string }>;
+ /** Optional className for the icon (defaults to text-primary). */
+ iconClassName?: string;
+ /** Verb phrase shown after the author name, e.g. "hid a" or "is streaming". */
+ action: string;
+ /** Optional noun shown after the verb, linked to a page route, e.g. "treasure" → /treasures. */
+ noun?: string;
+ /** Route to link the noun to, e.g. "/treasures". */
+ nounRoute?: string;
}
-function StreamHeader({ pubkey, isLive }: { pubkey: string; isLive: boolean }) {
+/** Static config for deriving the action header from an event's kind and tags. */
+interface KindHeaderConfig {
+ icon: React.ComponentType<{ className?: string }>;
+ iconClassName?: string;
+ /** Static action string, or a function that computes it from the event's tags. */
+ action: string | ((tags: string[][]) => string);
+ noun?: string;
+ nounRoute?: string;
+}
+
+const KIND_HEADER_MAP: Record
= {
+ 37516: { icon: ChestIcon, action: 'hid a', noun: 'treasure', nounRoute: '/treasures' },
+ 7516: { icon: ChestIcon, action: 'found a', noun: 'treasure', nounRoute: '/treasures' },
+ 37381: { icon: CardsIcon, action: 'shared a', noun: 'deck', nounRoute: '/decks' },
+ 36767: { icon: Palette, action: 'shared a', noun: 'theme', nounRoute: '/themes' },
+ 16767: { icon: Palette, action: 'updated their', noun: 'theme', nounRoute: '/themes' },
+ 30030: { icon: SmilePlus, action: 'shared an', noun: 'emoji pack', nounRoute: '/emoji-packs' },
+ 30311: {
+ icon: Radio,
+ iconClassName: undefined, // computed dynamically below
+ action: (tags) => tags.find(([n]) => n === 'status')?.[1] === 'live' ? 'is streaming' : 'streamed',
+ },
+};
+
+/** Generic action header: icon · [author name] [action] [linked noun] */
+function EventActionHeader({ pubkey, icon: Icon, iconClassName, action, noun, nounRoute }: EventActionHeaderProps) {
const author = useAuthor(pubkey);
const name = author.data?.metadata?.name || genUserName(pubkey);
const url = useProfileUrl(pubkey, author.data?.metadata);
@@ -1072,7 +1072,7 @@ function StreamHeader({ pubkey, isLive }: { pubkey: string; isLive: boolean }) {
return (
-
+
{author.isLoading ? (
@@ -1086,128 +1086,25 @@ function StreamHeader({ pubkey, isLive }: { pubkey: string; isLive: boolean }) {
{author.data?.event ? {name} : name}
)}
-
- {isLive ? 'is streaming' : 'streamed'}
+
+ {action}
+ {noun && nounRoute && (
+ <>
+ {' '}
+ e.stopPropagation()}
+ >
+ {noun}
+
+ >
+ )}
+ {noun && !nounRoute && <>{' '}{noun}>}
);
}
-function DeckHeader({ pubkey }: { pubkey: string }) {
- const author = useAuthor(pubkey);
- const name = author.data?.metadata?.name || genUserName(pubkey);
- const url = useProfileUrl(pubkey, author.data?.metadata);
-
- return (
-
-
-
-
-
- {author.isLoading ? (
-
- ) : (
- e.stopPropagation()}
- >
- {author.data?.event ? {name} : name}
-
- )}
- shared a deck
-
-
- );
-}
-
-function TreasureHeader({ pubkey, variant }: { pubkey: string; variant: 'hid' | 'found' }) {
- const author = useAuthor(pubkey);
- const name = author.data?.metadata?.name || genUserName(pubkey);
- const url = useProfileUrl(pubkey, author.data?.metadata);
-
- return (
-
-
-
-
-
- {author.isLoading ? (
-
- ) : (
- e.stopPropagation()}
- >
- {author.data?.event ? {name} : name}
-
- )}
-
- {variant === 'hid' ? 'hid a treasure' : 'found a treasure'}
-
-
-
- );
-}
-
-function ThemeHeader({ pubkey, variant }: { pubkey: string; variant: 'shared' | 'updated' }) {
- const author = useAuthor(pubkey);
- const name = author.data?.metadata?.name || genUserName(pubkey);
- const url = useProfileUrl(pubkey, author.data?.metadata);
-
- return (
-
-
-
- {author.isLoading ? (
-
- ) : (
- e.stopPropagation()}
- >
- {author.data?.event ? {name} : name}
-
- )}
-
- {variant === 'shared' ? 'shared a theme' : 'updated their theme'}
-
-
-
- );
-}
-
-function EmojiPackHeader({ pubkey }: { pubkey: string }) {
- const author = useAuthor(pubkey);
- const name = author.data?.metadata?.name || genUserName(pubkey);
- const url = useProfileUrl(pubkey, author.data?.metadata);
-
- return (
-
-
-
-
-
- {author.isLoading ? (
-
- ) : (
- e.stopPropagation()}
- >
- {author.data?.event ? {name} : name}
-
- )}
- shared an emoji pack
-
-
- );
-}
-