mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-09-22 15:19:47 +02:00
cleanup embedded article card
This commit is contained in:
@@ -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
|
||||||
|
@@ -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" />
|
||||||
<LinkOverlay href={naddr ? buildAppSelectUrl(naddr, false) : undefined} isExternal fontWeight="bold">
|
<UserLink pubkey={article.pubkey} fontWeight="bold" isTruncated />
|
||||||
{title}
|
<Timestamp timestamp={getArticlePublishDate(article) ?? article.created_at} />
|
||||||
</LinkOverlay>
|
|
||||||
<Text>by:</Text>
|
|
||||||
<UserLink pubkey={article.pubkey} />
|
|
||||||
<Text>
|
|
||||||
| <Timestamp timestamp={getArticlePublishDate(article) ?? article.created_at} />
|
|
||||||
</Text>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
<Text flex={1}>{summary}</Text>
|
<LinkOverlay href={naddr ? buildAppSelectUrl(naddr, false) : undefined} isExternal fontWeight="bold">
|
||||||
<Flex gap="2" alignItems="center">
|
{title}
|
||||||
{article.tags
|
</LinkOverlay>
|
||||||
.filter((t) => t[0] === "t")
|
<Text mb="2">{summary}</Text>
|
||||||
.map(([_, hashtag]) => (
|
{article.tags
|
||||||
<Tag>{hashtag}</Tag>
|
.filter((t) => t[0] === "t")
|
||||||
))}
|
.map(([_, hashtag]) => (
|
||||||
</Flex>
|
<Tag mr="2" mb="2">
|
||||||
</Flex>
|
#{hashtag}
|
||||||
{image && <Image src={image} alt={title} maxW="2in" maxH="2in" float="right" borderRadius="md" />}
|
</Tag>
|
||||||
|
))}
|
||||||
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -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} />
|
||||||
) : (
|
) : (
|
||||||
|
Reference in New Issue
Block a user