diff --git a/src/components/BookmarkButton/index.tsx b/src/components/BookmarkButton/index.tsx index 3991243d..cda0422c 100644 --- a/src/components/BookmarkButton/index.tsx +++ b/src/components/BookmarkButton/index.tsx @@ -1,3 +1,4 @@ +import { getReplaceableCoordinateFromEvent, isReplaceableEvent } from '@/lib/event' import { useBookmarks } from '@/providers/BookmarksProvider' import { useNostr } from '@/providers/NostrProvider' import { BookmarkIcon, Loader } from 'lucide-react' @@ -11,10 +12,14 @@ export default function BookmarkButton({ event }: { event: Event }) { const { pubkey: accountPubkey, bookmarkListEvent, checkLogin } = useNostr() const { addBookmark, removeBookmark } = useBookmarks() const [updating, setUpdating] = useState(false) - const isBookmarked = useMemo( - () => bookmarkListEvent?.tags.some((tag) => tag[0] === 'e' && tag[1] === event.id), - [bookmarkListEvent, event] - ) + const isBookmarked = useMemo(() => { + const isReplaceable = isReplaceableEvent(event.kind) + const eventKey = isReplaceable ? getReplaceableCoordinateFromEvent(event) : event.id + + return bookmarkListEvent?.tags.some((tag) => + isReplaceable ? tag[0] === 'a' && tag[1] === eventKey : tag[0] === 'e' && tag[1] === eventKey + ) + }, [bookmarkListEvent, event]) if (!accountPubkey) return null diff --git a/src/components/BookmarkList/index.tsx b/src/components/BookmarkList/index.tsx index c6b44c3e..3aa2ee74 100644 --- a/src/components/BookmarkList/index.tsx +++ b/src/components/BookmarkList/index.tsx @@ -1,5 +1,5 @@ import { useFetchEvent } from '@/hooks' -import { generateBech32IdFromETag } from '@/lib/tag' +import { generateBech32IdFromATag, generateBech32IdFromETag } from '@/lib/tag' import { useNostr } from '@/providers/NostrProvider' import { useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -15,8 +15,14 @@ export default function BookmarkList() { return ( bookmarkListEvent.tags - .map((tag) => (tag[0] === 'e' ? generateBech32IdFromETag(tag) : undefined)) - .filter(Boolean) as `nevent1${string}`[] + .map((tag) => + tag[0] === 'e' + ? generateBech32IdFromETag(tag) + : tag[0] === 'a' + ? generateBech32IdFromATag(tag) + : null + ) + .filter(Boolean) as (`nevent1${string}` | `naddr1${string}`)[] ).reverse() }, [bookmarkListEvent]) const [showCount, setShowCount] = useState(SHOW_COUNT) diff --git a/src/lib/draft-event.ts b/src/lib/draft-event.ts index 7506a633..d9fcc6c9 100644 --- a/src/lib/draft-event.ts +++ b/src/lib/draft-event.ts @@ -599,7 +599,7 @@ function buildDTag(identifier: string) { return ['d', identifier] } -function buildETag( +export function buildETag( eventHexId: string, pubkey: string = '', hint: string = '', diff --git a/src/providers/BookmarksProvider.tsx b/src/providers/BookmarksProvider.tsx index 70c03dc6..526cc4a3 100644 --- a/src/providers/BookmarksProvider.tsx +++ b/src/providers/BookmarksProvider.tsx @@ -1,8 +1,9 @@ -import { createBookmarkDraftEvent } from '@/lib/draft-event' +import { buildATag, buildETag, createBookmarkDraftEvent } from '@/lib/draft-event' +import { getReplaceableCoordinateFromEvent, isReplaceableEvent } from '@/lib/event' import client from '@/services/client.service' +import { Event } from 'nostr-tools' import { createContext, useContext } from 'react' import { useNostr } from './NostrProvider' -import { Event } from 'nostr-tools' type TBookmarksContext = { addBookmark: (event: Event) => Promise @@ -27,11 +28,21 @@ export function BookmarksProvider({ children }: { children: React.ReactNode }) { const bookmarkListEvent = await client.fetchBookmarkListEvent(accountPubkey) const currentTags = bookmarkListEvent?.tags || [] + const isReplaceable = isReplaceableEvent(event.kind) + const eventKey = isReplaceable ? getReplaceableCoordinateFromEvent(event) : event.id - if (currentTags.some((tag) => tag[0] === 'e' && tag[1] === event.id)) return + if ( + currentTags.some((tag) => + isReplaceable + ? tag[0] === 'a' && tag[1] === eventKey + : tag[0] === 'e' && tag[1] === eventKey + ) + ) { + return + } const newBookmarkDraftEvent = createBookmarkDraftEvent( - [...currentTags, ['e', event.id, client.getEventHint(event.id), '', event.pubkey]], + [...currentTags, isReplaceable ? buildATag(event) : buildETag(event.id, event.pubkey)], bookmarkListEvent?.content ) const newBookmarkEvent = await publish(newBookmarkDraftEvent) @@ -44,7 +55,12 @@ export function BookmarksProvider({ children }: { children: React.ReactNode }) { const bookmarkListEvent = await client.fetchBookmarkListEvent(accountPubkey) if (!bookmarkListEvent) return - const newTags = bookmarkListEvent.tags.filter((tag) => !(tag[0] === 'e' && tag[1] === event.id)) + const isReplaceable = isReplaceableEvent(event.kind) + const eventKey = isReplaceable ? getReplaceableCoordinateFromEvent(event) : event.id + + const newTags = bookmarkListEvent.tags.filter((tag) => + isReplaceable ? tag[0] !== 'a' || tag[1] !== eventKey : tag[0] !== 'e' || tag[1] !== eventKey + ) if (newTags.length === bookmarkListEvent.tags.length) return const newBookmarkDraftEvent = createBookmarkDraftEvent(newTags, bookmarkListEvent.content)