mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-09-19 03:51:34 +02:00
cleanup list view
This commit is contained in:
@@ -21,14 +21,14 @@ export default function EmbeddedList({ list: list, ...props }: Omit<CardProps, "
|
||||
{getListName(list)}
|
||||
</Link>
|
||||
</Heading>
|
||||
<ListFeedButton list={list} ml="auto" size="sm" />
|
||||
</CardHeader>
|
||||
<CardBody p="2">
|
||||
<Flex gap="2">
|
||||
<Text>Created by:</Text>
|
||||
<Text>by</Text>
|
||||
<UserAvatarLink pubkey={list.pubkey} size="xs" />
|
||||
<UserLink pubkey={list.pubkey} isTruncated fontWeight="bold" fontSize="lg" />
|
||||
</Flex>
|
||||
<ListFeedButton list={list} ml="auto" size="sm" />
|
||||
</CardHeader>
|
||||
<CardBody p="2">
|
||||
<ListCardContent list={list} />
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
@@ -177,7 +177,13 @@ export const StarHalfIcon = createIcon({
|
||||
export const ErrorIcon = AlertTriangle;
|
||||
|
||||
export const BookmarkIcon = Bookmark;
|
||||
export const BookmarkedIcon = BookmarkCheck;
|
||||
|
||||
// TODO: switch to untitled UI solid icon
|
||||
export const BookmarkedIcon = createIcon({
|
||||
displayName: "BookmarkedIcon",
|
||||
d: "M4 2H20C20.5523 2 21 2.44772 21 3V22.2763C21 22.5525 20.7761 22.7764 20.5 22.7764C20.4298 22.7764 20.3604 22.7615 20.2963 22.7329L12 19.0313L3.70373 22.7329C3.45155 22.8455 3.15591 22.7322 3.04339 22.4801C3.01478 22.4159 3 22.3465 3 22.2763V3C3 2.44772 3.44772 2 4 2ZM12 13.5L14.9389 15.0451L14.3776 11.7725L16.7553 9.45492L13.4695 8.97746L12 6L10.5305 8.97746L7.24472 9.45492L9.62236 11.7725L9.06107 15.0451L12 13.5Z",
|
||||
defaultProps,
|
||||
});
|
||||
|
||||
export const V4VStreamIcon = PlayCircle;
|
||||
export const V4VStopIcon = StopCircle;
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import { Box, Button, ButtonProps, Text } from "@chakra-ui/react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { nip19 } from "nostr-tools";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
|
||||
import {
|
||||
BadgeIcon,
|
||||
DirectMessagesIcon,
|
||||
CommunityIcon,
|
||||
EmojiPacksIcon,
|
||||
NoteFeedIcon,
|
||||
GoalIcon,
|
||||
ListsIcon,
|
||||
LiveStreamIcon,
|
||||
@@ -24,7 +24,6 @@ import { useCurrentAccount } from "../../hooks/use-current-account";
|
||||
import accountService from "../../services/account";
|
||||
|
||||
export default function NavItems() {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const account = useCurrentAccount();
|
||||
|
||||
@@ -59,7 +58,8 @@ export default function NavItems() {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
onClick={() => navigate("/")}
|
||||
as={RouterLink}
|
||||
to="/"
|
||||
leftIcon={<NotesIcon boxSize={6} />}
|
||||
colorScheme={active === "notes" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -69,7 +69,8 @@ export default function NavItems() {
|
||||
{account && (
|
||||
<>
|
||||
<Button
|
||||
onClick={() => navigate("/notifications")}
|
||||
as={RouterLink}
|
||||
to="/notifications"
|
||||
leftIcon={<NotificationsIcon boxSize={6} />}
|
||||
colorScheme={active === "notifications" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -77,7 +78,8 @@ export default function NavItems() {
|
||||
Notifications
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => navigate("/dm")}
|
||||
as={RouterLink}
|
||||
to={"/dm"}
|
||||
leftIcon={<DirectMessagesIcon boxSize={6} />}
|
||||
colorScheme={active === "dm" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -87,7 +89,8 @@ export default function NavItems() {
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => navigate("/search")}
|
||||
as={RouterLink}
|
||||
to="/search"
|
||||
leftIcon={<SearchIcon boxSize={6} />}
|
||||
colorScheme={active === "search" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -96,7 +99,8 @@ export default function NavItems() {
|
||||
</Button>
|
||||
{account?.pubkey && (
|
||||
<Button
|
||||
onClick={() => navigate("/u/" + nip19.npubEncode(account.pubkey))}
|
||||
as={RouterLink}
|
||||
to={"/u/" + nip19.npubEncode(account.pubkey)}
|
||||
leftIcon={<ProfileIcon boxSize={6} />}
|
||||
colorScheme={active === "profile" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -105,7 +109,8 @@ export default function NavItems() {
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => navigate("/relays")}
|
||||
as={RouterLink}
|
||||
to="/relays"
|
||||
leftIcon={<RelayIcon boxSize={6} />}
|
||||
colorScheme={active === "relays" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -116,7 +121,8 @@ export default function NavItems() {
|
||||
Other Stuff
|
||||
</Text>
|
||||
<Button
|
||||
onClick={() => navigate("/streams")}
|
||||
as={RouterLink}
|
||||
to="/streams"
|
||||
leftIcon={<LiveStreamIcon boxSize={6} />}
|
||||
colorScheme={active === "streams" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -124,7 +130,8 @@ export default function NavItems() {
|
||||
Streams
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => navigate("/communities")}
|
||||
as={RouterLink}
|
||||
to="/communities"
|
||||
leftIcon={<CommunityIcon boxSize={6} />}
|
||||
colorScheme={active === "communities" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -132,7 +139,8 @@ export default function NavItems() {
|
||||
Communities
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => navigate("/lists")}
|
||||
as={RouterLink}
|
||||
to="/lists"
|
||||
leftIcon={<ListsIcon boxSize={6} />}
|
||||
colorScheme={active === "lists" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -140,7 +148,8 @@ export default function NavItems() {
|
||||
Lists
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => navigate("/goals")}
|
||||
as={RouterLink}
|
||||
to="/goals"
|
||||
leftIcon={<GoalIcon boxSize={6} />}
|
||||
colorScheme={active === "goals" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -148,7 +157,8 @@ export default function NavItems() {
|
||||
Goals
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => navigate("/badges")}
|
||||
as={RouterLink}
|
||||
to="/badges"
|
||||
leftIcon={<BadgeIcon boxSize={6} />}
|
||||
colorScheme={active === "badges" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -156,7 +166,8 @@ export default function NavItems() {
|
||||
Badges
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => navigate("/emojis")}
|
||||
as={RouterLink}
|
||||
to="/emojis"
|
||||
leftIcon={<EmojiPacksIcon boxSize={6} />}
|
||||
colorScheme={active === "emojis" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -164,7 +175,8 @@ export default function NavItems() {
|
||||
Emojis
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => navigate("/tools")}
|
||||
as={RouterLink}
|
||||
to="/tools"
|
||||
leftIcon={<ToolsIcon boxSize={6} />}
|
||||
colorScheme={active === "tools" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
@@ -173,7 +185,8 @@ export default function NavItems() {
|
||||
</Button>
|
||||
<Box h="4" />
|
||||
<Button
|
||||
onClick={() => navigate("/settings")}
|
||||
as={RouterLink}
|
||||
to="/settings"
|
||||
leftIcon={<SettingsIcon boxSize={6} />}
|
||||
colorScheme={active === "settings" ? "primary" : undefined}
|
||||
{...buttonProps}
|
||||
|
@@ -69,7 +69,7 @@ function BrowseListPage() {
|
||||
</Switch>
|
||||
</Flex>
|
||||
|
||||
<SimpleGrid columns={{ base: 1, lg: 2, xl: 3 }} spacing="2">
|
||||
<SimpleGrid columns={{ base: 1, lg: 2 }} spacing="2">
|
||||
{lists.map((event) => (
|
||||
<ListCard key={getEventUID(event)} list={event} />
|
||||
))}
|
||||
|
@@ -5,7 +5,6 @@ import {
|
||||
ButtonGroup,
|
||||
Card,
|
||||
CardBody,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardProps,
|
||||
Flex,
|
||||
@@ -66,6 +65,9 @@ export function ListCardContent({ list, ...props }: Omit<CardProps, "children">
|
||||
|
||||
return (
|
||||
<>
|
||||
<Text>
|
||||
Updated: <Timestamp timestamp={list.created_at} />
|
||||
</Text>
|
||||
{people.length > 0 && (
|
||||
<>
|
||||
<Text>People ({people.length}):</Text>
|
||||
@@ -77,59 +79,55 @@ export function ListCardContent({ list, ...props }: Omit<CardProps, "children">
|
||||
</>
|
||||
)}
|
||||
{notes.length > 0 && (
|
||||
<>
|
||||
<Flex gap="2" overflow="hidden" wrap="wrap">
|
||||
<Text>Notes ({notes.length}):</Text>
|
||||
<Flex gap="2" overflow="hidden">
|
||||
{notes.slice(0, 4).map(({ id, relay }) => (
|
||||
<NoteLink key={id} noteId={id} />
|
||||
))}
|
||||
</Flex>
|
||||
</>
|
||||
{notes.slice(0, 4).map(({ id, relay }) => (
|
||||
<NoteLink key={id} noteId={id} />
|
||||
))}
|
||||
</Flex>
|
||||
)}
|
||||
{references.length > 0 && (
|
||||
<>
|
||||
<Flex gap="2" overflow="hidden" wrap="wrap">
|
||||
<Text>References ({references.length})</Text>
|
||||
<Flex gap="2" overflow="hidden">
|
||||
{references.slice(0, 3).map(({ url, petname }) => (
|
||||
<Link maxW="200" href={url} isExternal whiteSpace="pre" color="blue.500" isTruncated>
|
||||
{petname || url}
|
||||
</Link>
|
||||
))}
|
||||
</Flex>
|
||||
</>
|
||||
{references.slice(0, 3).map(({ url, petname }) => (
|
||||
<Link maxW="200" href={url} isExternal whiteSpace="pre" color="blue.500" isTruncated>
|
||||
{petname || url}
|
||||
</Link>
|
||||
))}
|
||||
</Flex>
|
||||
)}
|
||||
{communities.length > 0 && (
|
||||
<>
|
||||
<Flex gap="2" overflow="hidden" wrap="wrap">
|
||||
<Text>Communities ({communities.length}):</Text>
|
||||
<Flex gap="2" overflow="hidden">
|
||||
{communities.map((pointer) => (
|
||||
<Link
|
||||
key={JSON.stringify(pointer)}
|
||||
as={RouterLink}
|
||||
to={`/c/${pointer.identifier}/${nip19.npubEncode(pointer.pubkey)}`}
|
||||
color="blue.500"
|
||||
>
|
||||
{pointer.identifier}
|
||||
</Link>
|
||||
))}
|
||||
</Flex>
|
||||
</>
|
||||
{communities.map((pointer) => (
|
||||
<Link
|
||||
key={JSON.stringify(pointer)}
|
||||
as={RouterLink}
|
||||
to={`/c/${pointer.identifier}/${nip19.npubEncode(pointer.pubkey)}`}
|
||||
color="blue.500"
|
||||
>
|
||||
{pointer.identifier}
|
||||
</Link>
|
||||
))}
|
||||
</Flex>
|
||||
)}
|
||||
{articles.length > 0 && (
|
||||
<>
|
||||
<Flex overflow="hidden" direction="column" wrap="wrap">
|
||||
<Text>Articles ({articles.length}):</Text>
|
||||
<Flex overflow="hidden" direction="column">
|
||||
{articles.slice(0, 4).map((pointer) => (
|
||||
<ArticleLinkLoader key={JSON.stringify(pointer)} pointer={pointer} isTruncated />
|
||||
))}
|
||||
</Flex>
|
||||
</>
|
||||
{articles.slice(0, 4).map((pointer) => (
|
||||
<ArticleLinkLoader key={JSON.stringify(pointer)} pointer={pointer} isTruncated />
|
||||
))}
|
||||
</Flex>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ListCardRender({ list, ...props }: Omit<CardProps, "children"> & { list: NostrEvent }) {
|
||||
function ListCardRender({
|
||||
list,
|
||||
hideCreator = false,
|
||||
...props
|
||||
}: Omit<CardProps, "children"> & { list: NostrEvent; hideCreator?: boolean }) {
|
||||
const link = isSpecialListKind(list.kind) ? createCoordinate(list.kind, list.pubkey) : getSharableEventAddress(list);
|
||||
|
||||
// if there is a parent intersection observer, register this card
|
||||
@@ -138,36 +136,43 @@ function ListCardRender({ list, ...props }: Omit<CardProps, "children"> & { list
|
||||
|
||||
return (
|
||||
<Card ref={ref} variant="outline" {...props}>
|
||||
<CardHeader display="flex" alignItems="center" p="2" pb="0">
|
||||
<CardHeader display="flex" gap="2" alignItems="center" p="2" pb="0">
|
||||
<Heading size="md" isTruncated>
|
||||
<Link as={RouterLink} to={`/lists/${link}`}>
|
||||
{getListName(list)}
|
||||
</Link>
|
||||
</Heading>
|
||||
<Link as={RouterLink} to={`/lists/${link}`} ml="auto">
|
||||
<Timestamp timestamp={list.created_at} />
|
||||
</Link>
|
||||
</CardHeader>
|
||||
<CardBody py="0" px="2">
|
||||
<ListCardContent list={list} />
|
||||
</CardBody>
|
||||
<CardFooter p="2" display="flex" alignItems="center" whiteSpace="pre" gap="2">
|
||||
<Text>Created by:</Text>
|
||||
<UserAvatarLink pubkey={list.pubkey} size="xs" />
|
||||
<UserLink pubkey={list.pubkey} isTruncated fontWeight="bold" fontSize="lg" />
|
||||
{!hideCreator && (
|
||||
<>
|
||||
<Text>by</Text>
|
||||
<UserAvatarLink pubkey={list.pubkey} size="xs" />
|
||||
<UserLink pubkey={list.pubkey} isTruncated fontWeight="bold" fontSize="lg" />
|
||||
</>
|
||||
)}
|
||||
<ButtonGroup size="xs" variant="ghost" ml="auto">
|
||||
<ListFavoriteButton list={list} />
|
||||
<ListMenu list={list} aria-label="list menu" />
|
||||
</ButtonGroup>
|
||||
</CardFooter>
|
||||
</CardHeader>
|
||||
<CardBody p="2">
|
||||
<ListCardContent list={list} />
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
function ListCard({ cord, list: maybeEvent }: { cord?: string; list?: NostrEvent }) {
|
||||
function ListCard({
|
||||
cord,
|
||||
list: maybeEvent,
|
||||
hideCreator,
|
||||
}: {
|
||||
cord?: string;
|
||||
list?: NostrEvent;
|
||||
hideCreator?: boolean;
|
||||
}) {
|
||||
const event = maybeEvent ?? (cord ? useReplaceableEvent(cord as string) : undefined);
|
||||
if (!event) return null;
|
||||
else return <ListCardRender list={event} />;
|
||||
else return <ListCardRender list={event} hideCreator={hideCreator} />;
|
||||
}
|
||||
|
||||
export default memo(ListCard);
|
||||
|
@@ -44,40 +44,44 @@ function ListsPage() {
|
||||
</Button>
|
||||
</Flex>
|
||||
|
||||
<Heading size="md">Special lists</Heading>
|
||||
<Divider />
|
||||
<SimpleGrid columns={{ base: 1, lg: 2, xl: 3 }} spacing="2">
|
||||
<ListCard cord={`${Kind.Contacts}:${account.pubkey}`} />
|
||||
<ListCard cord={`${MUTE_LIST_KIND}:${account.pubkey}`} />
|
||||
<ListCard cord={`${PIN_LIST_KIND}:${account.pubkey}`} />
|
||||
<Heading size="lg" mt="2">
|
||||
Special lists
|
||||
</Heading>
|
||||
<SimpleGrid columns={{ base: 1, lg: 2 }} spacing="2">
|
||||
<ListCard cord={`${Kind.Contacts}:${account.pubkey}`} hideCreator />
|
||||
<ListCard cord={`${MUTE_LIST_KIND}:${account.pubkey}`} hideCreator />
|
||||
<ListCard cord={`${PIN_LIST_KIND}:${account.pubkey}`} hideCreator />
|
||||
</SimpleGrid>
|
||||
{peopleLists.length > 0 && (
|
||||
<>
|
||||
<Heading size="md">People lists</Heading>
|
||||
<Divider />
|
||||
<SimpleGrid columns={{ base: 1, lg: 2, xl: 3 }} spacing="2">
|
||||
<Heading size="lg" mt="2">
|
||||
People lists
|
||||
</Heading>
|
||||
<SimpleGrid columns={{ base: 1, lg: 2 }} spacing="2">
|
||||
{peopleLists.map((event) => (
|
||||
<ListCard key={getEventUID(event)} list={event} />
|
||||
<ListCard key={getEventUID(event)} list={event} hideCreator />
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</>
|
||||
)}
|
||||
{noteLists.length > 0 && (
|
||||
<>
|
||||
<Heading size="md">Bookmark lists</Heading>
|
||||
<Divider />
|
||||
<SimpleGrid columns={{ base: 1, lg: 2, xl: 3 }} spacing="2">
|
||||
<Heading size="lg" mt="2">
|
||||
Bookmark lists
|
||||
</Heading>
|
||||
<SimpleGrid columns={{ base: 1, lg: 2 }} spacing="2">
|
||||
{noteLists.map((event) => (
|
||||
<ListCard key={getEventUID(event)} list={event} />
|
||||
<ListCard key={getEventUID(event)} list={event} hideCreator />
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</>
|
||||
)}
|
||||
{favoriteLists.length > 0 && (
|
||||
<>
|
||||
<Heading size="md">Favorite lists</Heading>
|
||||
<Divider />
|
||||
<SimpleGrid columns={{ base: 1, lg: 2, xl: 3 }} spacing="2">
|
||||
<Heading size="lg" mt="2">
|
||||
Favorite lists
|
||||
</Heading>
|
||||
<SimpleGrid columns={{ base: 1, lg: 2 }} spacing="2">
|
||||
{favoriteLists.map((event) => (
|
||||
<ListCard key={getEventUID(event)} list={event} />
|
||||
))}
|
||||
|
Reference in New Issue
Block a user