cleanup embedded article card

This commit is contained in:
hzrd149
2023-10-17 13:07:49 -05:00
parent 1f73120b2e
commit 0804ee33b4
3 changed files with 73 additions and 25 deletions

View File

@@ -21,7 +21,7 @@ I would recommend you use a browser extension like [Alby](https://getalby.com/)
## Running with docker ## Running with docker
```bash ```bash
docker run --rm -p 8080:80 ghcr.io/hzrd149/nostrudel docker run --rm -p 8080:80 ghcr.io/hzrd149/nostrudel:master
``` ```
## Running locally ## Running locally

View File

@@ -1,5 +1,5 @@
import { useRef } from "react"; import { useRef } from "react";
import { Card, CardProps, Flex, Image, LinkBox, LinkOverlay, Tag, Text } from "@chakra-ui/react"; import { Box, Card, CardBody, CardProps, Flex, Image, LinkBox, LinkOverlay, Tag, Text } from "@chakra-ui/react";
import { import {
getArticleImage, getArticleImage,
@@ -28,29 +28,39 @@ export default function EmbeddedArticle({ article, ...props }: Omit<CardProps, "
useRegisterIntersectionEntity(ref, getEventUID(article)); useRegisterIntersectionEntity(ref, getEventUID(article));
return ( return (
<Card as={LinkBox} ref={ref} p="2" flexDirection="row" {...props}> <Card as={LinkBox} ref={ref} size="sm" {...props}>
<Flex gap="2" direction="column" flex={1}> {image && (
<Flex gap="2" alignItems="center"> <Box
backgroundImage={image}
w="full"
aspectRatio={3 / 1}
hideFrom="md"
backgroundRepeat="no-repeat"
backgroundPosition="center"
backgroundSize="cover"
/>
)}
<CardBody>
{image && (
<Image src={image} alt={title} maxW="3in" maxH="2in" float="right" borderRadius="md" ml="2" hideBelow="md" />
)}
<Flex gap="2" alignItems="center" mb="2">
<UserAvatarLink pubkey={article.pubkey} size="sm" /> <UserAvatarLink pubkey={article.pubkey} size="sm" />
<UserLink pubkey={article.pubkey} fontWeight="bold" isTruncated />
<Timestamp timestamp={getArticlePublishDate(article) ?? article.created_at} />
</Flex>
<LinkOverlay href={naddr ? buildAppSelectUrl(naddr, false) : undefined} isExternal fontWeight="bold"> <LinkOverlay href={naddr ? buildAppSelectUrl(naddr, false) : undefined} isExternal fontWeight="bold">
{title} {title}
</LinkOverlay> </LinkOverlay>
<Text>by:</Text> <Text mb="2">{summary}</Text>
<UserLink pubkey={article.pubkey} />
<Text>
| <Timestamp timestamp={getArticlePublishDate(article) ?? article.created_at} />
</Text>
</Flex>
<Text flex={1}>{summary}</Text>
<Flex gap="2" alignItems="center">
{article.tags {article.tags
.filter((t) => t[0] === "t") .filter((t) => t[0] === "t")
.map(([_, hashtag]) => ( .map(([_, hashtag]) => (
<Tag>{hashtag}</Tag> <Tag mr="2" mb="2">
#{hashtag}
</Tag>
))} ))}
</Flex> </CardBody>
</Flex>
{image && <Image src={image} alt={title} maxW="2in" maxH="2in" float="right" borderRadius="md" />}
</Card> </Card>
); );
} }

View File

@@ -29,6 +29,7 @@ import trustedUserStatsService, { NostrBandUserStats } from "../../services/trus
import VerticalPageLayout from "../../components/vertical-page-layout"; import VerticalPageLayout from "../../components/vertical-page-layout";
import User01 from "../../components/icons/user-01"; import User01 from "../../components/icons/user-01";
import GenericNoteTimeline from "../../components/timeline-page/generic-note-timeline"; import GenericNoteTimeline from "../../components/timeline-page/generic-note-timeline";
import Feather from "../../components/icons/feather";
function ProfileResult({ profile }: { profile: NostrEvent }) { function ProfileResult({ profile }: { profile: NostrEvent }) {
const metadata = parseKind0Event(profile); const metadata = parseKind0Event(profile);
@@ -120,6 +121,25 @@ function NoteSearchResults({ search }: { search: string }) {
); );
} }
function ArticleSearchResults({ search }: { search: string }) {
const searchRelays = useRelaySelectionRelays();
const timeline = useTimelineLoader(
`${search}-article-search`,
searchRelays,
{ search: search || "", kinds: [Kind.Article] },
{ enabled: !!search },
);
const callback = useTimelineCurserIntersectionCallback(timeline);
return (
<IntersectionObserverProvider callback={callback}>
<GenericNoteTimeline timeline={timeline} />
</IntersectionObserverProvider>
);
}
export function SearchPage() { export function SearchPage() {
const navigate = useNavigate(); const navigate = useNavigate();
const qrScannerModal = useDisclosure(); const qrScannerModal = useDisclosure();
@@ -168,7 +188,18 @@ export function SearchPage() {
handleSearchText(searchInput); handleSearchText(searchInput);
}; };
const SearchResults = type === "users" ? ProfileSearchResults : NoteSearchResults; let SearchResults = ProfileSearchResults;
switch (type) {
case "users":
SearchResults = ProfileSearchResults;
break;
case "notes":
SearchResults = NoteSearchResults;
break;
case "articles":
SearchResults = ArticleSearchResults;
break;
}
return ( return (
<VerticalPageLayout> <VerticalPageLayout>
@@ -203,11 +234,18 @@ export function SearchPage() {
> >
Notes Notes
</Button> </Button>
<Button
leftIcon={<Feather />}
colorScheme={type === "articles" ? "primary" : undefined}
onClick={() => mergeSearchParams({ type: "articles" })}
>
Articles
</Button>
</ButtonGroup> </ButtonGroup>
<RelaySelectionButton ml="auto" size="sm" /> <RelaySelectionButton ml="auto" size="sm" />
</Flex> </Flex>
<Flex direction="column" gap="8"> <Flex direction="column" gap="4">
{search ? ( {search ? (
<SearchResults search={search} /> <SearchResults search={search} />
) : ( ) : (