mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-26 17:52:18 +01:00
Show list embeds in notes
This commit is contained in:
parent
3d5d23407d
commit
6b4fd8ab42
5
.changeset/shy-trees-boil.md
Normal file
5
.changeset/shy-trees-boil.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": minor
|
||||
---
|
||||
|
||||
Show list embeds in notes
|
51
src/components/embed-event/event-types/embedded-list.tsx
Normal file
51
src/components/embed-event/event-types/embedded-list.tsx
Normal file
@ -0,0 +1,51 @@
|
||||
import { AvatarGroup, Card, CardBody, CardHeader, CardProps, Flex, Heading, Link, Text } from "@chakra-ui/react";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
|
||||
import { NostrEvent } from "../../../types/nostr-event";
|
||||
import { getEventsFromList, getListName, getPubkeysFromList, isSpecialListKind } from "../../../helpers/nostr/lists";
|
||||
import { createCoordinate } from "../../../services/replaceable-event-requester";
|
||||
import { getSharableEventAddress } from "../../../helpers/nip19";
|
||||
import { UserAvatarLink } from "../../user-avatar-link";
|
||||
import { UserLink } from "../../user-link";
|
||||
import { NoteLink } from "../../note-link";
|
||||
import ListFeedButton from "../../../views/lists/components/list-feed-button";
|
||||
|
||||
export default function EmbeddedList({ list: list, ...props }: Omit<CardProps, "children"> & { list: NostrEvent }) {
|
||||
const people = getPubkeysFromList(list);
|
||||
const notes = getEventsFromList(list);
|
||||
const link = isSpecialListKind(list.kind) ? createCoordinate(list.kind, list.pubkey) : getSharableEventAddress(list);
|
||||
|
||||
return (
|
||||
<Card {...props}>
|
||||
<CardHeader display="flex" alignItems="center" p="2" pb="0" gap="2">
|
||||
<Heading size="md">
|
||||
<Link as={RouterLink} to={`/lists/${link}`}>
|
||||
{getListName(list)}
|
||||
</Link>
|
||||
</Heading>
|
||||
<ListFeedButton list={list} ml="auto" size="sm" />
|
||||
</CardHeader>
|
||||
<CardBody p="2">
|
||||
<Flex gap="2">
|
||||
<Text>Created by:</Text>
|
||||
<UserAvatarLink pubkey={list.pubkey} size="xs" />
|
||||
<UserLink pubkey={list.pubkey} isTruncated fontWeight="bold" fontSize="lg" />
|
||||
</Flex>
|
||||
{people.length > 0 && (
|
||||
<AvatarGroup overflow="hidden" mb="2" max={16} size="sm">
|
||||
{people.map(({ pubkey, relay }) => (
|
||||
<UserAvatarLink key={pubkey} pubkey={pubkey} relay={relay} />
|
||||
))}
|
||||
</AvatarGroup>
|
||||
)}
|
||||
{notes.length > 0 && (
|
||||
<Flex gap="2" overflow="hidden">
|
||||
{notes.map(({ id, relay }) => (
|
||||
<NoteLink key={id} noteId={id} />
|
||||
))}
|
||||
</Flex>
|
||||
)}
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
}
|
@ -15,6 +15,8 @@ import { EMOJI_PACK_KIND } from "../../helpers/nostr/emoji-packs";
|
||||
import EmbeddedEmojiPack from "./event-types/embedded-emoji-pack";
|
||||
import EmbeddedGoal, { EmbeddedGoalOptions } from "./event-types/embedded-goal";
|
||||
import EmbeddedUnknown from "./event-types/embedded-unknown";
|
||||
import { NOTE_LIST_KIND, PEOPLE_LIST_KIND } from "../../helpers/nostr/lists";
|
||||
import EmbeddedList from "./event-types/embedded-list";
|
||||
|
||||
export type EmbedProps = {
|
||||
goalProps?: EmbeddedGoalOptions;
|
||||
@ -30,6 +32,9 @@ export function EmbedEvent({ event, goalProps }: { event: NostrEvent } & EmbedPr
|
||||
return <EmbeddedGoal goal={event} {...goalProps} />;
|
||||
case EMOJI_PACK_KIND:
|
||||
return <EmbeddedEmojiPack pack={event} />;
|
||||
case PEOPLE_LIST_KIND:
|
||||
case NOTE_LIST_KIND:
|
||||
return <EmbeddedList list={event} />;
|
||||
}
|
||||
|
||||
return <EmbeddedUnknown event={event} />;
|
||||
|
@ -20,6 +20,7 @@ import clientRelaysService from "../../../services/client-relays";
|
||||
import QuoteNote from "../quote-note";
|
||||
import NostrPublishAction from "../../../classes/nostr-publish-action";
|
||||
import { useSigningContext } from "../../../providers/signing-provider";
|
||||
import { EmbedEvent } from "../../embed-event";
|
||||
|
||||
export function RepostButton({ event }: { event: NostrEvent }) {
|
||||
const { isOpen, onClose, onOpen } = useDisclosure();
|
||||
@ -51,7 +52,7 @@ export function RepostButton({ event }: { event: NostrEvent }) {
|
||||
isLoading={loading}
|
||||
/>
|
||||
{isOpen && (
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<Modal isOpen={isOpen} onClose={onClose} size="2xl">
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader px="4" py="2">
|
||||
@ -59,7 +60,7 @@ export function RepostButton({ event }: { event: NostrEvent }) {
|
||||
</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody px="4" py="0">
|
||||
<QuoteNote noteId={event.id} />
|
||||
<EmbedEvent event={event} />
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter px="4" py="4">
|
||||
|
@ -7,7 +7,6 @@ import {
|
||||
AccordionPanel,
|
||||
Box,
|
||||
Button,
|
||||
Code,
|
||||
Flex,
|
||||
Input,
|
||||
Link,
|
||||
@ -21,12 +20,11 @@ import {
|
||||
Text,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import { Event, Kind, nip19 } from "nostr-tools";
|
||||
import { Event, Kind } from "nostr-tools";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import { useCurrentAccount } from "../hooks/use-current-account";
|
||||
import signingService from "../services/signing";
|
||||
import QuoteNote from "../components/note/quote-note";
|
||||
import createDefer, { Deferred } from "../classes/deferred";
|
||||
import useEventRelays from "../hooks/use-event-relays";
|
||||
import { useWriteRelayUrls } from "../hooks/use-client-relays";
|
||||
@ -36,6 +34,7 @@ import { getEventCoordinate, getEventUID, isReplaceable } from "../helpers/nostr
|
||||
import NostrPublishAction from "../classes/nostr-publish-action";
|
||||
import { Tag } from "../types/nostr-event";
|
||||
import deleteEventService from "../services/delete-events";
|
||||
import { EmbedEvent } from "../components/embed-event";
|
||||
|
||||
type DeleteEventContextType = {
|
||||
isLoading: boolean;
|
||||
@ -51,13 +50,6 @@ export function useDeleteEventContext() {
|
||||
return useContext(DeleteEventContext);
|
||||
}
|
||||
|
||||
function EventPreview({ event }: { event: Event }) {
|
||||
if (event.kind === Kind.Text) {
|
||||
return <QuoteNote noteId={event.id} />;
|
||||
}
|
||||
return <Code>{nip19.noteEncode(event.id)}</Code>;
|
||||
}
|
||||
|
||||
export default function DeleteEventProvider({ children }: PropsWithChildren) {
|
||||
const toast = useToast();
|
||||
const account = useCurrentAccount();
|
||||
@ -124,11 +116,11 @@ export default function DeleteEventProvider({ children }: PropsWithChildren) {
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader px="4" py="2">
|
||||
Delete Note?
|
||||
Delete Event?
|
||||
</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody px="4" py="0">
|
||||
<EventPreview event={event} />
|
||||
<EmbedEvent event={event} />
|
||||
<Input
|
||||
name="reason"
|
||||
value={reason}
|
||||
|
23
src/views/lists/components/list-feed-button.tsx
Normal file
23
src/views/lists/components/list-feed-button.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import { Button, ButtonProps } from "@chakra-ui/react";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import { Kind } from "nostr-tools";
|
||||
|
||||
import { NostrEvent } from "../../../types/nostr-event";
|
||||
import { getEventCoordinate } from "../../../helpers/nostr/events";
|
||||
import { PEOPLE_LIST_KIND } from "../../../helpers/nostr/lists";
|
||||
|
||||
export default function ListFeedButton({ list, ...props }: { list: NostrEvent } & Omit<ButtonProps, "children">) {
|
||||
const shouldShowFeedButton = list.kind === PEOPLE_LIST_KIND || list.kind === Kind.Contacts;
|
||||
|
||||
if (!shouldShowFeedButton) return null;
|
||||
|
||||
return (
|
||||
<Button
|
||||
as={RouterLink}
|
||||
to={{ pathname: "/", search: new URLSearchParams({ people: getEventCoordinate(list) }).toString() }}
|
||||
{...props}
|
||||
>
|
||||
View Feed
|
||||
</Button>
|
||||
);
|
||||
}
|
@ -1,14 +1,13 @@
|
||||
import { Link as RouterList, useNavigate, useParams } from "react-router-dom";
|
||||
import { Kind, nip19 } from "nostr-tools";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { nip19 } from "nostr-tools";
|
||||
|
||||
import { UserLink } from "../../components/user-link";
|
||||
import { Button, Divider, Flex, Heading, SimpleGrid, Spacer } from "@chakra-ui/react";
|
||||
import { ArrowLeftSIcon } from "../../components/icons";
|
||||
import { useCurrentAccount } from "../../hooks/use-current-account";
|
||||
import { useDeleteEventContext } from "../../providers/delete-event-provider";
|
||||
import { getEventCoordinate, parseCoordinate } from "../../helpers/nostr/events";
|
||||
import { PEOPLE_LIST_KIND, getEventsFromList, getListName, getPubkeysFromList } from "../../helpers/nostr/lists";
|
||||
import { parseCoordinate } from "../../helpers/nostr/events";
|
||||
import { getEventsFromList, getListName, getPubkeysFromList } from "../../helpers/nostr/lists";
|
||||
import useReplaceableEvent from "../../hooks/use-replaceable-event";
|
||||
import { EventRelays } from "../../components/note/note-relays";
|
||||
import UserCard from "./components/user-card";
|
||||
@ -16,6 +15,7 @@ import NoteCard from "./components/note-card";
|
||||
import { TrustProvider } from "../../providers/trust";
|
||||
import ListMenu from "./components/list-menu";
|
||||
import ListFavoriteButton from "./components/list-favorite-button";
|
||||
import ListFeedButton from "./components/list-feed-button";
|
||||
|
||||
function useListCoordinate() {
|
||||
const { addr } = useParams() as { addr: string };
|
||||
@ -47,7 +47,6 @@ export default function ListDetailsView() {
|
||||
);
|
||||
|
||||
const isAuthor = account?.pubkey === event.pubkey;
|
||||
const shouldShowFeedButton = event.kind === PEOPLE_LIST_KIND || event.kind === Kind.Contacts;
|
||||
const people = getPubkeysFromList(event);
|
||||
const notes = getEventsFromList(event);
|
||||
|
||||
@ -67,14 +66,7 @@ export default function ListDetailsView() {
|
||||
|
||||
<EventRelays event={event} />
|
||||
|
||||
{shouldShowFeedButton && (
|
||||
<Button
|
||||
as={RouterLink}
|
||||
to={{ pathname: "/", search: new URLSearchParams({ people: getEventCoordinate(event) }).toString() }}
|
||||
>
|
||||
View Feed
|
||||
</Button>
|
||||
)}
|
||||
<ListFeedButton list={event} />
|
||||
{isAuthor && (
|
||||
<Button colorScheme="red" onClick={() => deleteEvent(event).then(() => navigate("/lists"))}>
|
||||
Delete
|
||||
|
Loading…
x
Reference in New Issue
Block a user