Fetch geocache event from found log's a tag to display treasure name
- Parse the `a` tag (e.g. `37516:pubkey:d-tag`) into AddrCoords - Fetch the referenced geocache event via useAddrEvent - Display the geocache's `name` tag as a clickable link (with chest icon) that navigates to the geocache's naddr detail page - Fall back to showing the d-tag identifier if the event can't be fetched Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ShieldCheck } from 'lucide-react';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { ChestIcon } from '@/components/icons/ChestIcon';
|
||||
import { useAddrEvent, type AddrCoords } from '@/hooks/useEvent';
|
||||
import type { NostrEvent } from '@nostrify/nostrify';
|
||||
|
||||
function getTag(tags: string[][], name: string): string | undefined {
|
||||
@@ -11,29 +16,55 @@ function getAllTags(tags: string[][], name: string): string[] {
|
||||
return tags.filter(([n]) => n === name).map(([, v]) => v);
|
||||
}
|
||||
|
||||
/** Parse the `a` tag from a found log into addressable event coordinates. */
|
||||
function parseGeocacheAddr(tags: string[][]): AddrCoords | undefined {
|
||||
const aTag = getTag(tags, 'a');
|
||||
if (!aTag) return undefined;
|
||||
const parts = aTag.split(':');
|
||||
if (parts.length < 3) return undefined;
|
||||
const [kindStr, pubkey, ...rest] = parts;
|
||||
const kind = Number(kindStr);
|
||||
if (!kind || !pubkey) return undefined;
|
||||
return { kind, pubkey, identifier: rest.join(':') };
|
||||
}
|
||||
|
||||
/** Renders the content of a found log event (kind 7516). */
|
||||
export function FoundLogContent({ event }: { event: NostrEvent }) {
|
||||
const text = event.content;
|
||||
const images = getAllTags(event.tags, 'image');
|
||||
const hasVerification = !!getTag(event.tags, 'verification');
|
||||
|
||||
// Extract geocache name from the `a` tag if available
|
||||
const geocacheRef = useMemo(() => {
|
||||
const aTag = getTag(event.tags, 'a');
|
||||
if (!aTag) return null;
|
||||
const [, , dTag] = aTag.split(':');
|
||||
return dTag ?? null;
|
||||
}, [event.tags]);
|
||||
const geocacheAddr = useMemo(() => parseGeocacheAddr(event.tags), [event.tags]);
|
||||
const { data: geocacheEvent, isLoading: geocacheLoading } = useAddrEvent(geocacheAddr);
|
||||
|
||||
const geocacheName = geocacheEvent?.tags.find(([n]) => n === 'name')?.[1];
|
||||
|
||||
// Build naddr link for the geocache
|
||||
const geocacheLink = useMemo(() => {
|
||||
if (!geocacheAddr) return undefined;
|
||||
return `/${nip19.naddrEncode({ kind: geocacheAddr.kind, pubkey: geocacheAddr.pubkey, identifier: geocacheAddr.identifier })}`;
|
||||
}, [geocacheAddr]);
|
||||
|
||||
return (
|
||||
<div className="mt-2">
|
||||
{/* Geocache reference + verified badge */}
|
||||
{/* Geocache name link + verified badge */}
|
||||
<div className="flex flex-wrap items-center gap-1.5 mb-2">
|
||||
{geocacheRef && (
|
||||
{geocacheLoading ? (
|
||||
<Skeleton className="h-5 w-32" />
|
||||
) : geocacheName && geocacheLink ? (
|
||||
<Link
|
||||
to={geocacheLink}
|
||||
className="flex items-center gap-1.5 text-sm font-medium text-primary hover:underline"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<ChestIcon className="size-3.5" />
|
||||
{geocacheName}
|
||||
</Link>
|
||||
) : geocacheAddr ? (
|
||||
<Badge variant="secondary" className="text-[11px] gap-1 font-medium">
|
||||
{geocacheRef}
|
||||
{geocacheAddr.identifier}
|
||||
</Badge>
|
||||
)}
|
||||
) : null}
|
||||
{hasVerification && (
|
||||
<Badge variant="secondary" className="text-[11px] gap-1 font-medium text-green-600 dark:text-green-400">
|
||||
<ShieldCheck className="size-3" />
|
||||
|
||||
Reference in New Issue
Block a user