diff --git a/src/components/note/components/repost-button.tsx b/src/components/note/components/repost-button.tsx index 59e6fe367..60cf93e4e 100644 --- a/src/components/note/components/repost-button.tsx +++ b/src/components/note/components/repost-button.tsx @@ -1,23 +1,43 @@ import { Button, IconButton, useDisclosure } from "@chakra-ui/react"; +import { kinds } from "nostr-tools"; import { NostrEvent } from "../../../types/nostr-event"; import { RepostIcon } from "../../icons"; import useEventCount from "../../../hooks/use-event-count"; import RepostModal from "./repost-modal"; +import useEventExists from "../../../hooks/use-event-exists"; +import useCurrentAccount from "../../../hooks/use-current-account"; export default function RepostButton({ event }: { event: NostrEvent }) { const { isOpen, onClose, onOpen } = useDisclosure(); - const repostCount = useEventCount({ "#e": [event.id], kinds: [6] }); + const account = useCurrentAccount(); + const hasReposted = useEventExists( + account ? { "#e": [event.id], kinds: [kinds.Repost, kinds.GenericRepost], authors: [account.pubkey] } : undefined, + [], //only check the cache + false, + ); + const repostCount = useEventCount({ "#e": [event.id], kinds: [kinds.Repost, kinds.GenericRepost] }); return ( <> {repostCount !== undefined && repostCount > 0 ? ( - ) : ( - } onClick={onOpen} aria-label="Repost Note" title="Repost Note" /> + } + onClick={onOpen} + aria-label="Repost Note" + title="Repost Note" + colorScheme={hasReposted ? "primary" : undefined} + /> )} {isOpen && } diff --git a/src/hooks/use-event-exists.ts b/src/hooks/use-event-exists.ts index bee73e463..871d4a3e3 100644 --- a/src/hooks/use-event-exists.ts +++ b/src/hooks/use-event-exists.ts @@ -4,7 +4,10 @@ import eventExistsService from "../services/event-exists"; import { NostrRequestFilter } from "../types/nostr-query"; import useSubject from "./use-subject"; -export default function useEventExists(filter: NostrRequestFilter, relays: string[], fallback = true) { - const sub = useMemo(() => eventExistsService.requestExists(filter, relays), [stringify(filter), relays.join("|")]); +export default function useEventExists(filter?: NostrRequestFilter, relays: string[] = [], fallback = true) { + const sub = useMemo( + () => filter && eventExistsService.requestExists(filter, relays), + [stringify(filter), relays.join("|")], + ); return useSubject(sub) ?? fallback; } diff --git a/src/services/event-exists.ts b/src/services/event-exists.ts index 5164a4622..3d5393ff9 100644 --- a/src/services/event-exists.ts +++ b/src/services/event-exists.ts @@ -8,6 +8,8 @@ import relayScoreboardService from "./relay-scoreboard"; import { logger } from "../helpers/debug"; import { matchFilter, matchFilters } from "nostr-tools"; import { NostrEvent } from "../types/nostr-event"; +import { relayRequest } from "../helpers/relay"; +import { localRelay } from "./local-relay"; function hashFilter(filter: NostrRequestFilter) { return stringify(filter); @@ -35,11 +37,17 @@ class EventExistsService { if (!this.filters.has(key)) this.filters.set(key, filter); if (sub.value !== true) { - for (const url of relays) { - if (!asked.has(url) && !pending.has(url)) { - pending.add(url); + relayRequest(localRelay, Array.isArray(filter) ? filter : [filter]).then((cached) => { + if (cached.length > 0) { + for (const e of cached) this.handleEvent(e, false); + } else { + for (const url of relays) { + if (!asked.has(url) && !pending.has(url)) { + pending.add(url); + } + } } - } + }); } return sub; @@ -72,13 +80,15 @@ class EventExistsService { } } - handleEvent(event: NostrEvent) { + handleEvent(event: NostrEvent, cache = true) { for (const [key, filter] of this.filters) { const doseMatch = Array.isArray(filter) ? matchFilters(filter, event) : matchFilter(filter, event); if (doseMatch && this.answers.get(key).value !== true) { this.answers.get(key).next(true); } } + + if (cache) localRelay.publish(event); } }