import { NDKEvent, NDKFilter, NDKKind, NDKSubscriptionCacheUsage } from '@nostr-dev-kit/ndk' import { CommentContent } from 'components/comment/CommentContent' import { Reactions } from 'components/comment/Reactions' import { Zap } from 'components/comment/Zap' import { Dots } from 'components/Spinner' import { formatDate } from 'date-fns' import { useAppSelector, useDidMount, useLocalStorage, useNDKContext } from 'hooks' import { useComments } from 'hooks/useComments' import { nip19 } from 'nostr-tools' import { useState } from 'react' import { Link } from 'react-router-dom' import { appRoutes, getProfilePageRoute } from 'routes' import { FeedPostsFilter, NSFWFilter, UserProfile } from 'types' import { DEFAULT_FILTER_OPTIONS, hexToNpub } from 'utils' import { NoteRepostPopup } from './NoteRepostPopup' import { NoteQuoteRepostPopup } from './NoteQuoteRepostPopup' import { NsfwCommentWrapper } from 'components/NsfwCommentWrapper' interface NoteProps { ndkEvent: NDKEvent } export const Note = ({ ndkEvent }: NoteProps) => { const { ndk } = useNDKContext() const userState = useAppSelector((state) => state.user) const userPubkey = userState.user?.pubkey as string | undefined const [eventProfile, setEventProfile] = useState() const isRepost = ndkEvent.kind === NDKKind.Repost const filterKey = 'filter-feed-2' const [filterOptions] = useLocalStorage( filterKey, DEFAULT_FILTER_OPTIONS ) const isNsfw = ndkEvent .getMatchingTags('L') .some((t) => t[1] === 'content-warning') const [repostEvent, setRepostEvent] = useState() const [repostProfile, setRepostProfile] = useState() const noteEvent = repostEvent ?? ndkEvent const noteProfile = repostProfile ?? eventProfile const { commentEvents } = useComments(ndkEvent.pubkey, undefined, ndkEvent.id) const [quoteRepostEvents, setQuoteRepostEvents] = useState([]) const [hasQuoted, setHasQuoted] = useState(false) const [repostEvents, setRepostEvents] = useState([]) const [hasReposted, setHasReposted] = useState(false) const [isLoading, setIsLoading] = useState(false) const [showRepostPopup, setShowRepostPopup] = useState(false) const [showQuoteRepostPopup, setShowQuoteRepostPopup] = useState(false) useDidMount(() => { setIsLoading(true) ndkEvent.author.fetchProfile().then((res) => setEventProfile(res)) if (isRepost) { const parsedEvent = JSON.parse(ndkEvent.content) const ndkRepostEvent = new NDKEvent(ndk, parsedEvent) setRepostEvent(ndkRepostEvent) ndkRepostEvent.author.fetchProfile().then((res) => setRepostProfile(res)) } const repostFilter: NDKFilter = { kinds: [NDKKind.Repost], '#e': [ndkEvent.id] } const quoteFilter: NDKFilter = { kinds: [NDKKind.Text], '#q': [ndkEvent.id] } ndk .fetchEvents([repostFilter, quoteFilter], { closeOnEose: true, cacheUsage: NDKSubscriptionCacheUsage.PARALLEL }) .then((ndkEventSet) => { const ndkEvents = Array.from(ndkEventSet) if (ndkEventSet.size) { const quoteRepostEvents = ndkEvents.filter( (n) => n.kind === NDKKind.Text ) userPubkey && setHasQuoted( quoteRepostEvents.some((qr) => qr.pubkey === userPubkey) ) setQuoteRepostEvents(quoteRepostEvents) const repostEvents = ndkEvents.filter( (n) => n.kind === NDKKind.Repost ) userPubkey && setHasReposted(repostEvents.some((qr) => qr.pubkey === userPubkey)) setRepostEvents(repostEvents) } }) .finally(() => { setIsLoading(false) }) }) const profileRoute = getProfilePageRoute( nip19.nprofileEncode({ pubkey: noteEvent.pubkey }) ) const reposterRoute = repostEvent ? getProfilePageRoute( nip19.nprofileEncode({ pubkey: ndkEvent.pubkey }) ) : undefined const baseUrl = appRoutes.feed + '/' // Show who reposted the note const reposterVisual = repostEvent && reposterRoute ? ( <>

{eventProfile?.displayName || eventProfile?.name || ''}{' '} Reposted...

) : null const handleRepost = async (confirm: boolean) => { setShowRepostPopup(false) // Cancel if not confirmed if (!confirm) return const repostNdkEvent = await ndkEvent.repost(false) await repostNdkEvent.sign() } // Is this user's repost? const isUsersRepost = isRepost && ndkEvent.author.pubkey === userState.user?.pubkey return (
{reposterVisual}
{noteProfile?.displayName || noteProfile?.name || ''}{' '} {hexToNpub(noteEvent.pubkey)}
{noteEvent.created_at && (
{formatDate(noteEvent.created_at * 1000, 'hh:mm aa')}{' '} {formatDate(noteEvent.created_at * 1000, 'dd/MM/yyyy')}
)}
{/* Quote Repost, Kind 1 */}
setShowQuoteRepostPopup(true) } >

{isLoading ? : quoteRepostEvents.length}

{showQuoteRepostPopup && ( setShowQuoteRepostPopup(false)} /> )} {/* Repost, Kind 6 */} {!isUsersRepost && (
setShowRepostPopup(true) } >

{isLoading ? : repostEvents.length}

)} {showRepostPopup && ( setShowRepostPopup(false)} /> )} {typeof noteProfile?.lud16 !== 'undefined' && noteProfile.lud16 !== '' && }

{commentEvents.length}

Replies

Reply

) }