mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-04-05 18:38:44 +02:00
add relay icons to notes
This commit is contained in:
parent
f383903bec
commit
214487eae7
5
.changeset/loud-points-remember.md
Normal file
5
.changeset/loud-points-remember.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": minor
|
||||
---
|
||||
|
||||
Add relay icons to notes
|
@ -18,7 +18,7 @@ import { Bech32Prefix, getSharableNoteId, normalizeToBech32 } from "../../helper
|
||||
import { NostrEvent } from "../../types/nostr-event";
|
||||
import { MenuIconButton, MenuIconButtonProps } from "../menu-icon-button";
|
||||
|
||||
import { ClipboardIcon, CodeIcon, ExternalLinkIcon, LikeIcon, RepostIcon, TrashIcon } from "../icons";
|
||||
import { ClipboardIcon, CodeIcon, ExternalLinkIcon, LikeIcon, RelayIcon, RepostIcon, TrashIcon } from "../icons";
|
||||
import NoteReactionsModal from "./note-zaps-modal";
|
||||
import NoteDebugModal from "../debug-modals/note-debug-modal";
|
||||
import { useCurrentAccount } from "../../hooks/use-current-account";
|
||||
@ -28,6 +28,8 @@ import { buildDeleteEvent } from "../../helpers/nostr-event";
|
||||
import signingService from "../../services/signing";
|
||||
import { nostrPostAction } from "../../classes/nostr-post-action";
|
||||
import clientRelaysService from "../../services/client-relays";
|
||||
import { handleEventFromRelay } from "../../services/event-relays";
|
||||
import relayPoolService from "../../services/relay-pool";
|
||||
|
||||
export const NoteMenu = ({ event, ...props }: { event: NostrEvent } & Omit<MenuIconButtonProps, "children">) => {
|
||||
const account = useCurrentAccount();
|
||||
@ -62,6 +64,18 @@ export const NoteMenu = ({ event, ...props }: { event: NostrEvent } & Omit<MenuI
|
||||
}
|
||||
}, [event]);
|
||||
|
||||
const broadcast = useCallback(() => {
|
||||
const missingRelays = clientRelaysService.getWriteUrls();
|
||||
|
||||
const { results, onComplete } = nostrPostAction(missingRelays, event, 5000);
|
||||
|
||||
results.subscribe((result) => {
|
||||
if (result.status) {
|
||||
handleEventFromRelay(relayPoolService.requestRelay(result.url, false), event);
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<MenuIconButton {...props}>
|
||||
@ -87,6 +101,9 @@ export const NoteMenu = ({ event, ...props }: { event: NostrEvent } & Omit<MenuI
|
||||
Delete Note
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem onClick={broadcast} icon={<RelayIcon />}>
|
||||
Broadcast
|
||||
</MenuItem>
|
||||
<MenuItem onClick={infoModal.onOpen} icon={<CodeIcon />}>
|
||||
View Raw
|
||||
</MenuItem>
|
||||
|
@ -1,76 +1,28 @@
|
||||
import { memo, useCallback, useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
IconButtonProps,
|
||||
Popover,
|
||||
PopoverArrow,
|
||||
PopoverBody,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
Text,
|
||||
Flex,
|
||||
PopoverFooter,
|
||||
} from "@chakra-ui/react";
|
||||
import { nostrPostAction } from "../../classes/nostr-post-action";
|
||||
import { getEventRelays, handleEventFromRelay } from "../../services/event-relays";
|
||||
import { memo } from "react";
|
||||
import { IconButton, IconButtonProps, Flex, useDisclosure } from "@chakra-ui/react";
|
||||
import { getEventRelays } from "../../services/event-relays";
|
||||
import { NostrEvent } from "../../types/nostr-event";
|
||||
import { RelayIcon, SearchIcon } from "../icons";
|
||||
import { RelayIcon } from "../icons";
|
||||
import { RelayFavicon } from "../relay-favicon";
|
||||
import { useReadRelayUrls, useWriteRelayUrls } from "../../hooks/use-client-relays";
|
||||
import relayPoolService from "../../services/relay-pool";
|
||||
import useSubject from "../../hooks/use-subject";
|
||||
import { useIsMobile } from "../../hooks/use-is-mobile";
|
||||
|
||||
export type NoteRelaysProps = Omit<IconButtonProps, "icon" | "aria-label"> & {
|
||||
event: NostrEvent;
|
||||
};
|
||||
|
||||
export const NoteRelays = memo(({ event, ...props }: NoteRelaysProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
const eventRelays = useSubject(getEventRelays(event.id));
|
||||
const writeRelays = useWriteRelayUrls();
|
||||
const { isOpen, onOpen } = useDisclosure();
|
||||
|
||||
const [broadcasting, setBroadcasting] = useState(false);
|
||||
const broadcast = useCallback(() => {
|
||||
const missingRelays = writeRelays.filter((url) => !eventRelays.includes(url));
|
||||
if (missingRelays.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
setBroadcasting(true);
|
||||
const { results, onComplete } = nostrPostAction(missingRelays, event, 5000);
|
||||
|
||||
results.subscribe((result) => {
|
||||
if (result.status) {
|
||||
handleEventFromRelay(relayPoolService.requestRelay(result.url, false), event);
|
||||
}
|
||||
});
|
||||
|
||||
onComplete.then(() => setBroadcasting(false));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Popover isLazy>
|
||||
<PopoverTrigger>
|
||||
<IconButton title="Note Relays" icon={<RelayIcon />} aria-label="Note Relays" {...props} />
|
||||
</PopoverTrigger>
|
||||
<PopoverContent>
|
||||
<PopoverArrow />
|
||||
<PopoverBody>
|
||||
{eventRelays.map((url) => (
|
||||
<Flex alignItems="center" key={url}>
|
||||
<RelayFavicon relay={url} size="2xs" mr="2" />
|
||||
<Text isTruncated>{url}</Text>
|
||||
</Flex>
|
||||
))}
|
||||
</PopoverBody>
|
||||
<PopoverFooter>
|
||||
<Flex gap="2">
|
||||
<Button size="xs" onClick={broadcast} isLoading={broadcasting} leftIcon={<RelayIcon />}>
|
||||
Broadcast
|
||||
</Button>
|
||||
</Flex>
|
||||
</PopoverFooter>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
return isOpen || !isMobile ? (
|
||||
<Flex alignItems="center" gap="-4">
|
||||
{eventRelays.map((url) => (
|
||||
<RelayFavicon key={url} relay={url} size="2xs" title={url} />
|
||||
))}
|
||||
</Flex>
|
||||
) : (
|
||||
<IconButton icon={<RelayIcon />} size="xs" aria-label="Relays" onClick={onOpen} variant="link" />
|
||||
);
|
||||
});
|
||||
|
@ -1,4 +1,3 @@
|
||||
import moment from "moment";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { App } from "./app";
|
||||
import { Providers } from "./providers";
|
||||
@ -26,7 +25,3 @@ root.render(
|
||||
<App />
|
||||
</Providers>
|
||||
);
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
window.moment = moment;
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import {
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import { useParams, useSearchParams } from "react-router-dom";
|
||||
import moment from "moment";
|
||||
import { useAppTitle } from "../../hooks/use-app-title";
|
||||
import { useReadRelayUrls } from "../../hooks/use-client-relays";
|
||||
import { useTimelineLoader } from "../../hooks/use-timeline-loader";
|
||||
@ -38,7 +37,7 @@ export default function HashTagView() {
|
||||
`${hashtag}-hashtag`,
|
||||
selectedRelay ? [selectedRelay] : defaultRelays,
|
||||
{ kinds: [1], "#t": [hashtag] },
|
||||
{ pageSize: moment.duration(5, "minutes").asSeconds() }
|
||||
{ pageSize: 60*10 }
|
||||
);
|
||||
|
||||
const timeline = showReplies ? events : events.filter((e) => !isReply(e));
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Button, Flex, FormControl, FormLabel, Select, Spinner, Switch, useDisclosure } from "@chakra-ui/react";
|
||||
import moment from "moment";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { Note } from "../../components/note";
|
||||
import { unique } from "../../helpers/array";
|
||||
@ -26,7 +25,7 @@ export default function GlobalTab() {
|
||||
`global`,
|
||||
selectedRelay ? [selectedRelay] : [],
|
||||
{ kinds: [1] },
|
||||
{ pageSize: moment.duration(5, "minutes").asSeconds() }
|
||||
{ pageSize: 60*10 }
|
||||
);
|
||||
|
||||
const timeline = showReplies ? events : events.filter((e) => !isReply(e));
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Button, Flex, Spinner, Text } from "@chakra-ui/react";
|
||||
import moment from "moment";
|
||||
import { useOutletContext } from "react-router-dom";
|
||||
import { NoteLink } from "../../components/note-link";
|
||||
import { UserLink } from "../../components/user-link";
|
||||
@ -46,7 +45,7 @@ export default function UserReportsTab() {
|
||||
`${truncatedId(pubkey)}-reports`,
|
||||
contextRelays,
|
||||
{ authors: [pubkey], kinds: [1984] },
|
||||
{ pageSize: moment.duration(1, "week").asSeconds() }
|
||||
{ pageSize: 60 * 60 * 24 * 7 }
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -4934,11 +4934,6 @@ mixme@^0.5.1:
|
||||
resolved "https://registry.yarnpkg.com/mixme/-/mixme-0.5.9.tgz#a5a58e17354632179ff3ce5b0fc130899c8ba81c"
|
||||
integrity sha512-VC5fg6ySUscaWUpI4gxCBTQMH2RdUpNrk+MsbpCYtIvf9SBJdiUey4qE7BXviJsJR4nDQxCZ+3yaYNW3guz/Pw==
|
||||
|
||||
moment@^2.29.4:
|
||||
version "2.29.4"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
|
||||
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
|
||||
|
||||
ms@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
|
Loading…
x
Reference in New Issue
Block a user