mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-29 11:12:12 +01:00
small changes
This commit is contained in:
parent
f6ecace372
commit
9ea4d431b9
@ -6,8 +6,7 @@ type ContextType = { expanded: boolean; onExpand: () => void; onCollapse: () =>
|
||||
const ExpandedContext = React.createContext<ContextType | undefined>(undefined);
|
||||
|
||||
export function useExpand() {
|
||||
const ctx = useContext(ExpandedContext);
|
||||
return ctx;
|
||||
return useContext(ExpandedContext);
|
||||
}
|
||||
|
||||
export function ExpandProvider({ children }: PropsWithChildren) {
|
||||
|
@ -1,53 +0,0 @@
|
||||
import { Box, Flex, Heading, SkeletonText } from "@chakra-ui/react";
|
||||
import { useAsync } from "react-use";
|
||||
import clientRelaysService from "../../services/client-relays";
|
||||
import singleEventService from "../../services/single-event";
|
||||
import { isETag, NostrEvent } from "../../types/nostr-event";
|
||||
import { ErrorFallback } from "../error-boundary";
|
||||
import { Note } from ".";
|
||||
import { NoteMenu } from "./note-menu";
|
||||
import { UserAvatar } from "../user-avatar";
|
||||
import { UserDnsIdentityIcon } from "../user-dns-identity-icon";
|
||||
import { UserLink } from "../user-link";
|
||||
import { unique } from "../../helpers/array";
|
||||
import { TrustProvider } from "./trust";
|
||||
|
||||
export default function RepostNote({ event, maxHeight }: { event: NostrEvent; maxHeight?: number }) {
|
||||
const {
|
||||
value: repostNote,
|
||||
loading,
|
||||
error,
|
||||
} = useAsync(async () => {
|
||||
const [_, eventId, relay] = event.tags.find(isETag) ?? [];
|
||||
if (eventId) {
|
||||
const readRelays = clientRelaysService.getReadUrls();
|
||||
if (relay) readRelays.push(relay);
|
||||
return singleEventService.requestEvent(eventId, unique(readRelays));
|
||||
}
|
||||
return null;
|
||||
}, [event]);
|
||||
|
||||
return (
|
||||
<TrustProvider event={event}>
|
||||
<Flex gap="2" direction="column">
|
||||
<Flex gap="2" alignItems="center" pl="1">
|
||||
<UserAvatar pubkey={event.pubkey} size="xs" />
|
||||
<Heading size="sm" display="inline">
|
||||
<UserLink pubkey={event.pubkey} />
|
||||
</Heading>
|
||||
<UserDnsIdentityIcon pubkey={event.pubkey} onlyIcon />
|
||||
<span>Shared note</span>
|
||||
<Box flex={1} />
|
||||
<NoteMenu event={event} size="sm" variant="link" aria-label="note options" />
|
||||
</Flex>
|
||||
{loading ? (
|
||||
<SkeletonText />
|
||||
) : repostNote ? (
|
||||
<Note event={repostNote} maxHeight={maxHeight} />
|
||||
) : (
|
||||
<ErrorFallback error={error} />
|
||||
)}
|
||||
</Flex>
|
||||
</TrustProvider>
|
||||
);
|
||||
}
|
65
src/components/repost-note.tsx
Normal file
65
src/components/repost-note.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
import { Box, Flex, Heading, SkeletonText, Text } from "@chakra-ui/react";
|
||||
import { useAsync } from "react-use";
|
||||
import singleEventService from "../services/single-event";
|
||||
import { isETag, NostrEvent } from "../types/nostr-event";
|
||||
import { ErrorFallback } from "./error-boundary";
|
||||
import { Note } from "./note";
|
||||
import { NoteMenu } from "./note/note-menu";
|
||||
import { UserAvatar } from "./user-avatar";
|
||||
import { UserDnsIdentityIcon } from "./user-dns-identity-icon";
|
||||
import { UserLink } from "./user-link";
|
||||
import { TrustProvider } from "./note/trust";
|
||||
import { safeJson } from "../helpers/parse";
|
||||
import { verifySignature } from "nostr-tools";
|
||||
import { useReadRelayUrls } from "../hooks/use-client-relays";
|
||||
|
||||
function parseHardcodedNoteContent(event: NostrEvent): NostrEvent | null {
|
||||
const json = safeJson(event.content, null);
|
||||
if (json) verifySignature(json);
|
||||
return null;
|
||||
}
|
||||
|
||||
export default function RepostNote({ event, maxHeight }: { event: NostrEvent; maxHeight?: number }) {
|
||||
const hardCodedNote = parseHardcodedNoteContent(event);
|
||||
|
||||
const [_, eventId, relay] = event.tags.find(isETag) ?? [];
|
||||
const readRelays = useReadRelayUrls(relay ? [relay] : []);
|
||||
|
||||
const {
|
||||
value: loadedNote,
|
||||
loading,
|
||||
error,
|
||||
} = useAsync(async () => {
|
||||
if (eventId) {
|
||||
return singleEventService.requestEvent(eventId, readRelays);
|
||||
}
|
||||
return null;
|
||||
}, [event]);
|
||||
|
||||
const note = hardCodedNote || loadedNote;
|
||||
|
||||
return (
|
||||
<TrustProvider event={event}>
|
||||
<Flex gap="2" direction="column">
|
||||
<Flex gap="2" alignItems="center" pl="1">
|
||||
<UserAvatar pubkey={event.pubkey} size="xs" />
|
||||
<Heading size="sm" display="inline" isTruncated whiteSpace="pre">
|
||||
<UserLink pubkey={event.pubkey} />
|
||||
</Heading>
|
||||
<UserDnsIdentityIcon pubkey={event.pubkey} onlyIcon />
|
||||
<Text as="span" whiteSpace="pre" mr="auto">
|
||||
Shared note
|
||||
</Text>
|
||||
<NoteMenu event={event} size="sm" variant="link" aria-label="note options" />
|
||||
</Flex>
|
||||
{loading ? (
|
||||
<SkeletonText />
|
||||
) : note ? (
|
||||
<Note event={note} maxHeight={maxHeight} />
|
||||
) : (
|
||||
<ErrorFallback error={error} />
|
||||
)}
|
||||
</Flex>
|
||||
</TrustProvider>
|
||||
);
|
||||
}
|
@ -10,7 +10,7 @@ import { useContext } from "react";
|
||||
import { PostModalContext } from "../../providers/post-modal-provider";
|
||||
import { useReadRelayUrls } from "../../hooks/use-client-relays";
|
||||
import { useCurrentAccount } from "../../hooks/use-current-account";
|
||||
import RepostNote from "../../components/note/repost-note";
|
||||
import RepostNote from "../../components/repost-note";
|
||||
import RequireCurrentAccount from "../../providers/require-current-account";
|
||||
|
||||
function FollowingTabBody() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { useNavigate, useOutletContext } from "react-router-dom";
|
||||
import { useOutletContext } from "react-router-dom";
|
||||
import moment from "moment";
|
||||
import {
|
||||
Accordion,
|
||||
@ -9,6 +9,7 @@ import {
|
||||
AccordionPanel,
|
||||
Box,
|
||||
Flex,
|
||||
Heading,
|
||||
IconButton,
|
||||
Image,
|
||||
Link,
|
||||
@ -37,6 +38,9 @@ import { useUserContacts } from "../../hooks/use-user-contacts";
|
||||
import { convertTimestampToDate } from "../../helpers/date";
|
||||
import userTrustedStatsService from "../../services/user-trusted-stats";
|
||||
import { readablizeSats } from "../../helpers/bolt11";
|
||||
import { UserAvatar } from "../../components/user-avatar";
|
||||
import { useIsMobile } from "../../hooks/use-is-mobile";
|
||||
import { getUserDisplayName } from "../../helpers/user-metadata";
|
||||
|
||||
function buildDescriptionContent(description: string) {
|
||||
let content: EmbedableContent = [description.trim()];
|
||||
@ -48,7 +52,7 @@ function buildDescriptionContent(description: string) {
|
||||
}
|
||||
|
||||
export default function UserAboutTab() {
|
||||
const navigate = useNavigate();
|
||||
const isMobile = useIsMobile();
|
||||
const expanded = useDisclosure();
|
||||
const { pubkey } = useOutletContext() as { pubkey: string };
|
||||
const contextRelays = useAdditionalRelayContext();
|
||||
@ -74,30 +78,45 @@ export default function UserAboutTab() {
|
||||
pb="8"
|
||||
h="full"
|
||||
>
|
||||
{metadata?.banner && (
|
||||
<Box
|
||||
pt={!expanded.isOpen ? "20vh" : 0}
|
||||
px={!expanded.isOpen ? "2" : 0}
|
||||
pb={!expanded.isOpen ? "4" : 0}
|
||||
w="full"
|
||||
position="relative"
|
||||
backgroundImage={!expanded.isOpen ? metadata.banner : ""}
|
||||
backgroundPosition="center"
|
||||
backgroundSize="cover"
|
||||
backgroundRepeat="no-repeat"
|
||||
<Box
|
||||
pt={!expanded.isOpen ? "20vh" : 0}
|
||||
px={!expanded.isOpen ? "2" : 0}
|
||||
pb={!expanded.isOpen ? "4" : 0}
|
||||
w="full"
|
||||
position="relative"
|
||||
backgroundImage={!expanded.isOpen ? metadata?.banner : ""}
|
||||
backgroundPosition="center"
|
||||
backgroundSize="cover"
|
||||
backgroundRepeat="no-repeat"
|
||||
>
|
||||
{expanded.isOpen && <Image src={metadata?.banner} w="full" />}
|
||||
<Flex
|
||||
bottom="0"
|
||||
right="0"
|
||||
left="0"
|
||||
p="2"
|
||||
position="absolute"
|
||||
direction={isMobile ? "column" : "row"}
|
||||
bg="linear-gradient(180deg, rgb(255 255 255 / 0%) 0%, var(--chakra-colors-chakra-body-bg) 100%)"
|
||||
gap="2"
|
||||
alignItems={isMobile ? "flex-start" : "flex-end"}
|
||||
>
|
||||
{expanded.isOpen && <Image src={metadata?.banner} w="full" />}
|
||||
<IconButton
|
||||
icon={expanded.isOpen ? <ArrowUpSIcon /> : <ArrowDownSIcon />}
|
||||
aria-label="expand"
|
||||
onClick={expanded.onToggle}
|
||||
top="2"
|
||||
right="2"
|
||||
variant="solid"
|
||||
position="absolute"
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
<UserAvatar pubkey={pubkey} size={isMobile ? "lg" : "xl"} noProxy />
|
||||
<Box>
|
||||
<Heading>{getUserDisplayName(metadata, pubkey)}</Heading>
|
||||
<UserDnsIdentityIcon pubkey={pubkey} />
|
||||
</Box>
|
||||
</Flex>
|
||||
<IconButton
|
||||
icon={expanded.isOpen ? <ArrowUpSIcon /> : <ArrowDownSIcon />}
|
||||
aria-label="expand"
|
||||
onClick={expanded.onToggle}
|
||||
top="2"
|
||||
right="2"
|
||||
variant="solid"
|
||||
position="absolute"
|
||||
/>
|
||||
</Box>
|
||||
{aboutContent && (
|
||||
<Text whiteSpace="pre-wrap" px="2">
|
||||
{aboutContent.map((part, i) =>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Box, Button, Flex, FormControl, FormLabel, Spinner, Switch, useDisclosure } from "@chakra-ui/react";
|
||||
import { useOutletContext } from "react-router-dom";
|
||||
import { Note } from "../../components/note";
|
||||
import RepostNote from "../../components/note/repost-note";
|
||||
import RepostNote from "../../components/repost-note";
|
||||
import { isReply, isRepost } from "../../helpers/nostr-event";
|
||||
import { useAdditionalRelayContext } from "../../providers/additional-relay-context";
|
||||
import userTimelineService from "../../services/user-timeline";
|
||||
|
Loading…
x
Reference in New Issue
Block a user