11import { eventsByIdCache , addSeenEventId } from "@/utils/memcache.ts"
22import { useEffect , useMemo , useState , useRef , memo } from "react"
3- import { NDKEvent } from "@nostr-dev-kit/ndk"
3+ import { NDKEvent , NDKSubscription } from "@nostr-dev-kit/ndk"
44import classNames from "classnames"
55
6- import { getEventReplyingTo , fetchEvent , getEventRoot , isRepost } from "@/utils/nostr.ts"
6+ import { getEventReplyingTo , getEventRoot , isRepost } from "@/utils/nostr.ts"
77import { getEventIdHex , handleEventContent } from "@/shared/components/event/utils.ts"
88import RepostHeader from "@/shared/components/event/RepostHeader.tsx"
99import FeedItemActions from "../reactions/FeedItemActions.tsx"
@@ -18,6 +18,7 @@ import FeedItemTitle from "./FeedItemTitle.tsx"
1818import { Link , useNavigate } from "react-router"
1919import LikeHeader from "../LikeHeader"
2020import { nip19 } from "nostr-tools"
21+ import { ndk } from "@/utils/ndk"
2122
2223const replySortFn = ( a : NDKEvent , b : NDKEvent ) => {
2324 const followDistanceA = socialGraph ( ) . getFollowDistance ( a . pubkey )
@@ -64,6 +65,7 @@ function FeedItem({
6465 const [ expanded , setExpanded ] = useState ( false )
6566 const [ hasActualReplies , setHasActualReplies ] = useState ( false )
6667 const navigate = useNavigate ( )
68+ const subscriptionRef = useRef < NDKSubscription | null > ( null )
6769
6870 if ( ( ! initialEvent || ! initialEvent . id ) && ! eventId ) {
6971 throw new Error (
@@ -146,29 +148,58 @@ function FeedItem({
146148 } , [ event ] )
147149
148150 useEffect ( ( ) => {
151+ // Clean up any existing subscription first
152+ if ( subscriptionRef . current ) {
153+ subscriptionRef . current . stop ( )
154+ // Force cleanup by removing from subscription manager (NDK bug workaround)
155+ if ( subscriptionRef . current . ndk ?. subManager ) {
156+ subscriptionRef . current . ndk . subManager . subscriptions . delete ( subscriptionRef . current . internalId )
157+ }
158+ subscriptionRef . current = null
159+ }
160+
149161 if ( ! event && eventIdHex ) {
150162 const cached = eventsByIdCache . get ( eventIdHex )
151163 if ( cached ) {
152164 setEvent ( cached )
153165 } else {
154- fetchEvent ( { ids : [ eventIdHex ] , authors : authorHints } ) . then ( ( fetched ) => {
155- if ( fetched ) {
156- setEvent ( fetched )
157- eventsByIdCache . set ( eventIdHex , fetched )
166+ const sub = ndk ( ) . subscribe (
167+ { ids : [ eventIdHex ] , authors : authorHints } ,
168+ { closeOnEose : true }
169+ )
170+ subscriptionRef . current = sub
171+
172+ sub . on ( "event" , ( fetchedEvent : NDKEvent ) => {
173+ if ( fetchedEvent && fetchedEvent . id ) {
174+ setEvent ( fetchedEvent )
175+ eventsByIdCache . set ( eventIdHex , fetchedEvent )
158176 }
159177 } )
160178 }
161179 }
180+
181+ return ( ) => {
182+ if ( subscriptionRef . current ) {
183+ subscriptionRef . current . stop ( )
184+ // Force cleanup by removing from subscription manager (NDK bug workaround)
185+ if ( subscriptionRef . current . ndk ?. subManager ) {
186+ subscriptionRef . current . ndk . subManager . subscriptions . delete ( subscriptionRef . current . internalId )
187+ }
188+ subscriptionRef . current = null
189+ }
190+ }
162191 } , [ event , eventIdHex , authorHints ] )
163192
164193 useEffect ( ( ) => {
165194 if ( event ) {
166- handleEventContent ( event , ( referred ) => {
195+ const cleanup = handleEventContent ( event , ( referred ) => {
167196 setReferredEvent ( referred )
168197 eventsByIdCache . set ( eventIdHex , referred )
169198 } )
199+
200+ return cleanup
170201 }
171- } , [ event ] )
202+ } , [ event , eventIdHex ] )
172203
173204 const wrapperClasses = classNames ( "relative max-w-[100vw]" , {
174205 "h-[200px] overflow-hidden" : asEmbed && ! expanded ,
0 commit comments