diff --git a/src/components/icons.tsx b/src/components/icons.tsx index cc1ea77ce..da48825da 100644 --- a/src/components/icons.tsx +++ b/src/components/icons.tsx @@ -99,7 +99,13 @@ export const LinkItem = createIcon({ }); export const LightningIcon = createIcon({ - displayName: "lightning", + displayName: "lightning-icon", d: "M13 10h7l-9 13v-9H4l9-13z", defaultProps, }); + +export const RelayIcon = createIcon({ + displayName: "relay-icon", + d: "M11 14v-3h2v3h5a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h5zM2.51 8.837C3.835 4.864 7.584 2 12 2s8.166 2.864 9.49 6.837l-1.898.632a8.003 8.003 0 0 0-15.184 0l-1.897-.632zm3.796 1.265a6.003 6.003 0 0 1 11.388 0l-1.898.633a4.002 4.002 0 0 0-7.592 0l-1.898-.633z", + defaultProps, +}); diff --git a/src/components/note/index.tsx b/src/components/note/index.tsx index f3b553e84..4728db9d8 100644 --- a/src/components/note/index.tsx +++ b/src/components/note/index.tsx @@ -31,6 +31,7 @@ import identity from "../../services/identity"; import { useUserContacts } from "../../hooks/use-user-contacts"; import { ArrowDownSIcon } from "../icons"; import { UserTipButton } from "../user-tip-button"; +import { NoteRelays } from "./note-relays"; export type NoteProps = { event: NostrEvent; @@ -62,6 +63,7 @@ export const Note = React.memo(({ event }: NoteProps) => { + diff --git a/src/components/note/note-relays.tsx b/src/components/note/note-relays.tsx new file mode 100644 index 000000000..6863ffca6 --- /dev/null +++ b/src/components/note/note-relays.tsx @@ -0,0 +1,57 @@ +import { + Button, + IconButton, + IconButtonProps, + Popover, + PopoverArrow, + PopoverBody, + PopoverContent, + PopoverTrigger, + Text, +} from "@chakra-ui/react"; +import { useCallback, useState } from "react"; +import { NostrRequest } from "../../classes/nostr-request"; +import useSubject from "../../hooks/use-subject"; +import { getEventRelays } from "../../services/event-relays"; +import settings from "../../services/settings"; +import { NostrEvent } from "../../types/nostr-event"; +import { RelayIcon } from "../icons"; + +export type NoteRelaysProps = Omit & { + event: NostrEvent; +}; + +export const NoteRelays = ({ event, ...props }: NoteRelaysProps) => { + const relays = useSubject(getEventRelays(event.id)); + + const [loading, setLoading] = useState(false); + const queryRelays = useCallback(() => { + setLoading(true); + const request = new NostrRequest(settings.relays.value); + request.start({ ids: [event.id] }); + request.onEvent.subscribe({ + complete() { + setLoading(false); + }, + }); + }, []); + + return ( + + + } {...props} aria-label="Note Relays" /> + + + + + {relays.map((url) => ( + {url} + ))} + + + + + ); +}; diff --git a/src/services/event-relays.ts b/src/services/event-relays.ts new file mode 100644 index 000000000..002431714 --- /dev/null +++ b/src/services/event-relays.ts @@ -0,0 +1,23 @@ +import { BehaviorSubject } from "rxjs"; +import { relayPool } from "./relays"; + +const eventRelays = new Map>(); + +export function getEventRelays(id: string) { + let relays = eventRelays.get(id); + if (!relays) { + relays = new BehaviorSubject([]); + eventRelays.set(id, relays); + } + return relays; +} + +relayPool.onRelayCreated.subscribe((relay) => { + relay.onEvent.subscribe(({ body: event }) => { + const relays = getEventRelays(event.id); + + if (!relays.value.includes(relay.url)) { + relays.next(relays.value.concat(relay.url)); + } + }); +});