From b28ebbe2785ba70b67ddf9ba4e343f411a1482b1 Mon Sep 17 00:00:00 2001 From: codytseng Date: Thu, 6 Feb 2025 22:08:08 +0800 Subject: [PATCH] feat: seen on button --- src/components/NoteCard/RepostNoteCard.tsx | 7 +++ src/components/NoteStats/SeenOnButton.tsx | 51 ++++++++++++++++++++++ src/components/NoteStats/index.tsx | 6 ++- src/services/client.service.ts | 28 +++++++----- 4 files changed, 80 insertions(+), 12 deletions(-) create mode 100644 src/components/NoteStats/SeenOnButton.tsx diff --git a/src/components/NoteCard/RepostNoteCard.tsx b/src/components/NoteCard/RepostNoteCard.tsx index 68666c94..4f441236 100644 --- a/src/components/NoteCard/RepostNoteCard.tsx +++ b/src/components/NoteCard/RepostNoteCard.tsx @@ -21,6 +21,13 @@ export default function RepostNoteCard({ return null } client.addEventToCache(targetEvent) + const targetSeenOn = client.getSeenEventRelays(targetEvent.id) + if (targetSeenOn.length === 0) { + const seenOn = client.getSeenEventRelays(event.id) + seenOn.forEach((relay) => { + client.trackEventSeenOn(targetEvent.id, relay) + }) + } } catch { return null } diff --git a/src/components/NoteStats/SeenOnButton.tsx b/src/components/NoteStats/SeenOnButton.tsx new file mode 100644 index 00000000..3dd3fc14 --- /dev/null +++ b/src/components/NoteStats/SeenOnButton.tsx @@ -0,0 +1,51 @@ +import { useSecondaryPage } from '@/PageManager' +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger +} from '@/components/ui/dropdown-menu' +import { toRelay } from '@/lib/link' +import { simplifyUrl } from '@/lib/url' +import client from '@/services/client.service' +import { Server } from 'lucide-react' +import { Event } from 'nostr-tools' +import { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' + +export default function SeenOnButton({ event }: { event: Event }) { + const { t } = useTranslation() + const { push } = useSecondaryPage() + const [relays, setRelays] = useState([]) + + useEffect(() => { + const seenOn = client.getSeenEventRelayUrls(event.id) + setRelays(seenOn) + }, []) + + return ( + + + + + + Seen on + + {relays.map((relay) => ( + push(toRelay(relay))}> + {simplifyUrl(relay)} + + ))} + + + ) +} diff --git a/src/components/NoteStats/index.tsx b/src/components/NoteStats/index.tsx index 3bab1d6e..4973c8ce 100644 --- a/src/components/NoteStats/index.tsx +++ b/src/components/NoteStats/index.tsx @@ -4,6 +4,7 @@ import LikeButton from './LikeButton' import NoteOptions from './NoteOptions' import ReplyButton from './ReplyButton' import RepostButton from './RepostButton' +import SeenOnButton from './SeenOnButton' export default function NoteStats({ event, @@ -23,7 +24,10 @@ export default function NoteStats({ - +
e.stopPropagation()}> + + +
) } diff --git a/src/services/client.service.ts b/src/services/client.service.ts index f4cdf818..ac29aa11 100644 --- a/src/services/client.service.ts +++ b/src/services/client.service.ts @@ -204,6 +204,9 @@ class ClientService extends EventTarget { function startSub() { startedCount++ return relay.subscribe([since ? { ...filter, since } : filter], { + receivedEvent: (relay, id) => { + that.trackEventSeenOn(id, relay) + }, alreadyHaveEvent: (id: string) => { const have = _knownIds.has(id) if (have) { @@ -214,7 +217,6 @@ class ClientService extends EventTarget { }, onevent: (evt: NEvent) => { that.eventDataLoader.prime(evt.id, Promise.resolve(evt)) - that.trackEventSeenOn(evt.id, relay) // not eosed yet, push to events if (eosedCount < startedCount) { return events.push(evt) @@ -549,8 +551,21 @@ class ClientService extends EventTarget { } } + getSeenEventRelays(eventId: string) { + return Array.from(this.pool.seenOn.get(eventId)?.values() || []) + } + getSeenEventRelayUrls(eventId: string) { - return Array.from(this.pool.seenOn.get(eventId)?.values() || []).map((relay) => relay.url) + return this.getSeenEventRelays(eventId).map((relay) => relay.url) + } + + trackEventSeenOn(eventId: string, relay: AbstractRelay) { + let set = this.pool.seenOn.get(eventId) + if (!set) { + set = new Set() + this.pool.seenOn.set(eventId, set) + } + set.add(relay) } private async fetchEventById(relayUrls: string[], id: string): Promise { @@ -756,15 +771,6 @@ class ClientService extends EventTarget { return followListEvents.sort((a, b) => b.created_at - a.created_at)[0] } - - private trackEventSeenOn(eventId: string, relay: AbstractRelay) { - let set = this.pool.seenOn.get(eventId) - if (!set) { - set = new Set() - this.pool.seenOn.set(eventId, set) - } - set.add(relay) - } } const instance = ClientService.getInstance()