mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-26 17:52:18 +01:00
add option to repost note to community
This commit is contained in:
parent
1c8f005251
commit
99d1115304
5
.changeset/many-parents-try.md
Normal file
5
.changeset/many-parents-try.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": minor
|
||||
---
|
||||
|
||||
Add option to repost note to community
|
@ -1,105 +1,25 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import { Kind } from "nostr-tools";
|
||||
import dayjs from "dayjs";
|
||||
import { Button, IconButton, useDisclosure } from "@chakra-ui/react";
|
||||
|
||||
import { DraftNostrEvent, NostrEvent } from "../../../types/nostr-event";
|
||||
import { NostrEvent } from "../../../types/nostr-event";
|
||||
import { RepostIcon } from "../../icons";
|
||||
import clientRelaysService from "../../../services/client-relays";
|
||||
import NostrPublishAction from "../../../classes/nostr-publish-action";
|
||||
import { useSigningContext } from "../../../providers/signing-provider";
|
||||
import { EmbedEvent } from "../../embed-event";
|
||||
import relayScoreboardService from "../../../services/relay-scoreboard";
|
||||
import { getEventRelays } from "../../../services/event-relays";
|
||||
import useEventCount from "../../../hooks/use-event-count";
|
||||
|
||||
function buildRepost(event: NostrEvent): DraftNostrEvent {
|
||||
const relays = getEventRelays(event.id).value;
|
||||
const topRelay = relayScoreboardService.getRankedRelays(relays)[0] ?? "";
|
||||
|
||||
const tags: NostrEvent["tags"] = [];
|
||||
tags.push(["e", event.id, topRelay]);
|
||||
|
||||
return {
|
||||
kind: Kind.Repost,
|
||||
tags,
|
||||
content: JSON.stringify(event),
|
||||
created_at: dayjs().unix(),
|
||||
};
|
||||
}
|
||||
import RepostModal from "./repost-modal";
|
||||
|
||||
export function RepostButton({ event }: { event: NostrEvent }) {
|
||||
const { isOpen, onClose, onOpen } = useDisclosure();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const toast = useToast();
|
||||
const { requestSignature } = useSigningContext();
|
||||
|
||||
const repostCount = useEventCount({ "#e": [event.id], kinds: [6] });
|
||||
|
||||
const handleClick = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const draftRepost = buildRepost(event);
|
||||
const signed = await requestSignature(draftRepost);
|
||||
const pub = new NostrPublishAction("Repost", clientRelaysService.getWriteUrls(), signed);
|
||||
await pub.onComplete;
|
||||
onClose();
|
||||
} catch (e) {
|
||||
if (e instanceof Error) toast({ description: e.message, status: "error" });
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{repostCount !== undefined && repostCount > 0 ? (
|
||||
<Button leftIcon={<RepostIcon />} onClick={onOpen} title="Repost Note" isLoading={loading}>
|
||||
<Button leftIcon={<RepostIcon />} onClick={onOpen} title="Repost Note">
|
||||
{repostCount}
|
||||
</Button>
|
||||
) : (
|
||||
<IconButton
|
||||
icon={<RepostIcon />}
|
||||
onClick={onOpen}
|
||||
aria-label="Repost Note"
|
||||
title="Repost Note"
|
||||
isLoading={loading}
|
||||
/>
|
||||
)}
|
||||
{isOpen && (
|
||||
<Modal isOpen={isOpen} onClose={onClose} size="2xl">
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader px="4" py="2">
|
||||
Repost Note?
|
||||
</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody px="4" py="0">
|
||||
<EmbedEvent event={event} />
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter px="4" py="4">
|
||||
<Button variant="ghost" size="sm" mr={2} onClick={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button colorScheme="primary" variant="solid" onClick={handleClick} size="sm" isLoading={loading}>
|
||||
Repost
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
<IconButton icon={<RepostIcon />} onClick={onOpen} aria-label="Repost Note" title="Repost Note" />
|
||||
)}
|
||||
{isOpen && <RepostModal isOpen={isOpen} onClose={onClose} event={event} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
138
src/components/note/components/repost-modal.tsx
Normal file
138
src/components/note/components/repost-modal.tsx
Normal file
@ -0,0 +1,138 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
ModalProps,
|
||||
SimpleGrid,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
|
||||
import { DraftNostrEvent, NostrEvent } from "../../../types/nostr-event";
|
||||
import { EmbedEvent } from "../../embed-event";
|
||||
import { getEventRelays } from "../../../services/event-relays";
|
||||
import relayScoreboardService from "../../../services/relay-scoreboard";
|
||||
import { Kind } from "nostr-tools";
|
||||
import dayjs from "dayjs";
|
||||
import NostrPublishAction from "../../../classes/nostr-publish-action";
|
||||
import clientRelaysService from "../../../services/client-relays";
|
||||
import { useSigningContext } from "../../../providers/signing-provider";
|
||||
import { ChevronDownIcon, ChevronUpIcon, ExternalLinkIcon } from "../../icons";
|
||||
import useSubscribedCommunitiesList from "../../../hooks/use-subscribed-communities-list";
|
||||
import { useCurrentAccount } from "../../../hooks/use-current-account";
|
||||
import { AddressPointer } from "nostr-tools/lib/types/nip19";
|
||||
import { createCoordinate } from "../../../services/replaceable-event-requester";
|
||||
|
||||
function buildRepost(event: NostrEvent): DraftNostrEvent {
|
||||
const relays = getEventRelays(event.id).value;
|
||||
const topRelay = relayScoreboardService.getRankedRelays(relays)[0] ?? "";
|
||||
|
||||
const tags: NostrEvent["tags"] = [];
|
||||
tags.push(["e", event.id, topRelay]);
|
||||
|
||||
return {
|
||||
kind: Kind.Repost,
|
||||
tags,
|
||||
content: JSON.stringify(event),
|
||||
created_at: dayjs().unix(),
|
||||
};
|
||||
}
|
||||
|
||||
export default function RepostModal({
|
||||
event,
|
||||
isOpen,
|
||||
onClose,
|
||||
...props
|
||||
}: Omit<ModalProps, "children"> & { event: NostrEvent }) {
|
||||
const account = useCurrentAccount();
|
||||
const toast = useToast();
|
||||
const { requestSignature } = useSigningContext();
|
||||
const showCommunities = useDisclosure();
|
||||
const { pointers } = useSubscribedCommunitiesList(account?.pubkey);
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const repost = async (communityPointer?: AddressPointer) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const draftRepost = buildRepost(event);
|
||||
if (communityPointer) {
|
||||
draftRepost.tags.push([
|
||||
"a",
|
||||
createCoordinate(communityPointer.kind, communityPointer.pubkey, communityPointer.identifier),
|
||||
]);
|
||||
}
|
||||
const signed = await requestSignature(draftRepost);
|
||||
const pub = new NostrPublishAction("Repost", clientRelaysService.getWriteUrls(), signed);
|
||||
await pub.onComplete;
|
||||
onClose();
|
||||
} catch (e) {
|
||||
if (e instanceof Error) toast({ description: e.message, status: "error" });
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose} size="2xl" {...props}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader px="4" py="2">
|
||||
Repost Note
|
||||
</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody px="4" py="0">
|
||||
<EmbedEvent event={event} />
|
||||
{showCommunities.isOpen && (
|
||||
<SimpleGrid spacing="2" columns={{ base: 1, sm: 2 }} mt="2">
|
||||
{pointers.map((pointer) => (
|
||||
<Button
|
||||
key={pointer.identifier + pointer.pubkey}
|
||||
size="md"
|
||||
variant="outline"
|
||||
rightIcon={<ExternalLinkIcon />}
|
||||
isLoading={loading}
|
||||
onClick={() => repost(pointer)}
|
||||
>
|
||||
{pointer.identifier}
|
||||
</Button>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
)}
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter px="4" py="4">
|
||||
<Button
|
||||
variant="link"
|
||||
flex={1}
|
||||
size="md"
|
||||
rightIcon={showCommunities.isOpen ? <ChevronUpIcon /> : <ChevronDownIcon />}
|
||||
py="2"
|
||||
onClick={showCommunities.onToggle}
|
||||
>
|
||||
Repost to community
|
||||
</Button>
|
||||
<Button variant="ghost" size="md" mr={2} onClick={onClose} flexShrink={0}>
|
||||
Cancel
|
||||
</Button>
|
||||
{!showCommunities.isOpen && (
|
||||
<Button
|
||||
colorScheme="primary"
|
||||
variant="solid"
|
||||
onClick={() => repost()}
|
||||
size="md"
|
||||
isLoading={loading}
|
||||
flexShrink={0}
|
||||
>
|
||||
Repost
|
||||
</Button>
|
||||
)}
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
}
|
@ -42,7 +42,7 @@ export default function CommunityHomePage({ community }: { community: NostrEvent
|
||||
const communityRelays = getCommunityRelays(community);
|
||||
const readRelays = useReadRelayUrls(communityRelays);
|
||||
const timeline = useTimelineLoader(`${getEventUID(community)}-timeline`, readRelays, {
|
||||
kinds: [Kind.Text, COMMUNITY_APPROVAL_KIND],
|
||||
kinds: [Kind.Text, Kind.Repost, COMMUNITY_APPROVAL_KIND],
|
||||
"#a": [communityCoordinate],
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user