import React from 'react'; import { useProfile } from "nostr-react"; import { nip19, } from "nostr-tools"; import { Card, CardContent, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip" import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel" import ReactionButton from '@/components/ReactionButton'; import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'; import ViewNoteButton from './ViewNoteButton'; import Link from 'next/link'; import { Event as NostrEvent } from "nostr-tools"; import ZapButton from './ZapButton'; import CardOptionsDropdown from './CardOptionsDropdown'; import { renderTextWithLinkedTags } from '@/utils/textUtils'; import { PinIcon } from "lucide-react"; // Function to extract video URL from imeta tags const getVideoUrl = (tags: string[][]): string | null => { for (const tag of tags) { if (tag[0] === 'imeta') { for (let i = 1; i < tag.length; i++) { if (tag[i].startsWith('url ')) { return tag[i].substring(4); } } } } return null; }; // Function to check if an event has reference tags (e, a, u) const hasReferenceTags = (tags: string[][]): boolean => { return tags.some(tag => ['e', 'a', 'u'].includes(tag[0])); }; // Function to get the first reference tag for opening source const getFirstReferenceTag = (tags: string[][]): { type: string; value: string; relays?: string[] } | null => { for (const tag of tags) { if (tag[0] === 'e') { return { type: 'e', value: tag[1], relays: tag.slice(2) }; } if (tag[0] === 'a') { return { type: 'a', value: tag[1], relays: tag.slice(2) }; } if (tag[0] === 'u') { return { type: 'u', value: tag[1] }; } } return null; }; // Component for the purple pin icon const PinButton: React.FC<{ referenceTag: { type: string; value: string; relays?: string[] }; onPinClick?: (referenceTag: { type: string; value: string; relays?: string[] }) => void; }> = ({ referenceTag, onPinClick }) => { return ( ); }; interface NoteCardProps { pubkey: string; text: string; eventId: string; tags: string[][]; event: NostrEvent; showViewNoteCardButton: boolean; onPinClick?: (referenceTag: { type: string; value: string; relays?: string[] }) => void; } const NoteCard: React.FC = ({ pubkey, text, eventId, tags, event, showViewNoteCardButton, onPinClick }) => { const { data: userData } = useProfile({ pubkey, }); const title = userData?.username || userData?.display_name || userData?.name || userData?.npub || nip19.npubEncode(pubkey); // text = text.replaceAll('\n', '
'); text = text.replaceAll('\n', ' '); // Extract video URL from imeta tags for video events (kind 21 or 22) const imetaVideoUrl = (event.kind === 21 || event.kind === 22) ? getVideoUrl(tags) : null; // Combine text-based video detection with imeta-based detection const textVideoSrc = text.match(/https?:\/\/[^ ]*\.(mp4|webm|mov)/g); const videoSrc = imetaVideoUrl ? [imetaVideoUrl] : textVideoSrc; const imageSrc = text.match(/https?:\/\/[^ ]*\.(png|jpg|gif|jpeg)/g); const textWithoutImage = text.replace(/https?:\/\/.*\.(?:png|jpg|gif|mp4|webm|mov|jpeg)/g, ''); const createdAt = new Date(event.created_at * 1000); const hrefProfile = `/profile/${nip19.npubEncode(pubkey)}`; const profileImageSrc = userData?.picture || "https://robohash.org/" + pubkey; // Check for reference tags and gallery tags const hasReferences = hasReferenceTags(tags); const referenceTag = getFirstReferenceTag(tags); const isGalleryTagged = text.includes('#gallery') || tags.some((tag: string[]) => tag[0] === 't' && tag[1] === 'gallery'); return ( <> {(hasReferences && referenceTag) || isGalleryTagged ? ( ) : null}
{title.charAt(0).toUpperCase()} {title}

{title}

{
{imageSrc && imageSrc.length > 1 ? ( {imageSrc.map((src, index) => ( {textWithoutImage ))} ) : ( imageSrc ? {textWithoutImage : "" )}
{videoSrc && videoSrc.length > 1 ? ( {videoSrc.map((src, index) => ( ))} ) : ( videoSrc ?
}
{renderTextWithLinkedTags(textWithoutImage, tags)}

{showViewNoteCardButton && }
{createdAt.toLocaleString()}
); } export default NoteCard;