show list links on musted-by view

This commit is contained in:
hzrd149 2023-11-25 09:56:24 -06:00
parent eb18421d7c
commit b69bfa3724
3 changed files with 40 additions and 16 deletions

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Show list links on muted by view

View File

@ -82,13 +82,17 @@ export function ListCardContent({ list, ...props }: Omit<CardProps, "children">
); );
} }
export function createListLink(list: NostrEvent) {
const isSpecialList = isSpecialListKind(list.kind);
return "/lists/" + (isSpecialList ? createCoordinate(list.kind, list.pubkey) : getSharableEventAddress(list));
}
function ListCardRender({ function ListCardRender({
list, list,
hideCreator = false, hideCreator = false,
...props ...props
}: Omit<CardProps, "children"> & { list: NostrEvent; hideCreator?: boolean }) { }: Omit<CardProps, "children"> & { list: NostrEvent; hideCreator?: boolean }) {
const isSpecialList = isSpecialListKind(list.kind); const isSpecialList = isSpecialListKind(list.kind);
const link = isSpecialList ? createCoordinate(list.kind, list.pubkey) : getSharableEventAddress(list);
// if there is a parent intersection observer, register this card // if there is a parent intersection observer, register this card
const ref = useRef<HTMLDivElement | null>(null); const ref = useRef<HTMLDivElement | null>(null);
@ -101,7 +105,7 @@ function ListCardRender({
<CardHeader p="4"> <CardHeader p="4">
<Flex gap="2" alignItems="center"> <Flex gap="2" alignItems="center">
<Heading size="md" isTruncated> <Heading size="md" isTruncated>
<HoverLinkOverlay as={RouterLink} to={`/lists/${link}`}> <HoverLinkOverlay as={RouterLink} to={createListLink(list)}>
{getListName(list)} {getListName(list)}
</HoverLinkOverlay> </HoverLinkOverlay>
</Heading> </Heading>

View File

@ -1,26 +1,41 @@
import { memo, useMemo, useRef } from "react"; import { memo, useMemo, useRef } from "react";
import { Flex, Heading, SimpleGrid } from "@chakra-ui/react"; import { Flex, Heading, Link, SimpleGrid } from "@chakra-ui/react";
import { useOutletContext } from "react-router-dom"; import { Link as RouterLink, useOutletContext } from "react-router-dom";
import UserAvatarLink from "../../components/user-avatar-link"; import UserAvatarLink from "../../components/user-avatar-link";
import { UserLink } from "../../components/user-link"; import { UserLink } from "../../components/user-link";
import useTimelineLoader from "../../hooks/use-timeline-loader"; import useTimelineLoader from "../../hooks/use-timeline-loader";
import { useReadRelayUrls } from "../../hooks/use-client-relays"; import { useReadRelayUrls } from "../../hooks/use-client-relays";
import { MUTE_LIST_KIND, PEOPLE_LIST_KIND } from "../../helpers/nostr/lists"; import { MUTE_LIST_KIND, PEOPLE_LIST_KIND, getListName, getPubkeysFromList } from "../../helpers/nostr/lists";
import useSubject from "../../hooks/use-subject"; import useSubject from "../../hooks/use-subject";
import IntersectionObserverProvider, { useRegisterIntersectionEntity } from "../../providers/intersection-observer"; import IntersectionObserverProvider, { useRegisterIntersectionEntity } from "../../providers/intersection-observer";
import { useTimelineCurserIntersectionCallback } from "../../hooks/use-timeline-cursor-intersection-callback"; import { useTimelineCurserIntersectionCallback } from "../../hooks/use-timeline-cursor-intersection-callback";
import { getEventUID } from "../../helpers/nostr/events"; import { getEventUID } from "../../helpers/nostr/events";
import VerticalPageLayout from "../../components/vertical-page-layout"; import VerticalPageLayout from "../../components/vertical-page-layout";
import { NostrEvent } from "../../types/nostr-event";
import SuperMap from "../../classes/super-map";
import { createListLink } from "../lists/components/list-card";
const User = memo(({ pubkey, listId }: { pubkey: string; listId: string }) => { function ListLink({ list }: { list: NostrEvent }) {
const ref = useRef<HTMLDivElement | null>(null); const ref = useRef<HTMLAnchorElement | null>(null);
useRegisterIntersectionEntity(ref, listId); useRegisterIntersectionEntity(ref, getEventUID(list));
return ( return (
<Flex gap="2" overflow="hidden" ref={ref}> <Link as={RouterLink} ref={ref} color="blue.500" to={createListLink(list)}>
{getListName(list)} ({getPubkeysFromList(list).length})
</Link>
);
}
const User = memo(({ pubkey, lists }: { pubkey: string; lists: NostrEvent[] }) => {
return (
<Flex gap="2" overflow="hidden">
<UserAvatarLink pubkey={pubkey} noProxy size="sm" /> <UserAvatarLink pubkey={pubkey} noProxy size="sm" />
<UserLink pubkey={pubkey} isTruncated /> <Flex direction="column">
<UserLink pubkey={pubkey} isTruncated fontWeight="bold" />
{lists.map((list) => (
<ListLink key={list.id} list={list} />
))}
</Flex>
</Flex> </Flex>
); );
}); });
@ -37,11 +52,11 @@ export default function UserMutedByTab() {
const lists = useSubject(timeline.timeline); const lists = useSubject(timeline.timeline);
const pubkeys = useMemo(() => { const pubkeys = useMemo(() => {
const keys = new Map<string, string>(); const dir = new SuperMap<string, NostrEvent[]>(() => []);
for (const list of lists) { for (const list of lists) {
keys.set(list.pubkey, getEventUID(list)); dir.get(list.pubkey).push(list);
} }
return Array.from(keys).map((a) => ({ pubkey: a[0], listId: a[1] })); return Array.from(dir).map((a) => ({ pubkey: a[0], lists: a[1] }));
}, [lists]); }, [lists]);
const callback = useTimelineCurserIntersectionCallback(timeline); const callback = useTimelineCurserIntersectionCallback(timeline);
@ -49,9 +64,9 @@ export default function UserMutedByTab() {
return ( return (
<IntersectionObserverProvider callback={callback}> <IntersectionObserverProvider callback={callback}>
<VerticalPageLayout> <VerticalPageLayout>
<SimpleGrid spacing="2" columns={{ base: 1, md: 2, lg: 3, xl: 4 }}> <SimpleGrid spacing="2" columns={{ base: 1, sm: 2, lg: 3, xl: 4 }}>
{pubkeys.map(({ pubkey, listId }) => ( {pubkeys.map(({ pubkey, lists }) => (
<User key={pubkey} pubkey={pubkey} listId={listId} /> <User key={pubkey} pubkey={pubkey} lists={lists} />
))} ))}
</SimpleGrid> </SimpleGrid>
{pubkeys.length === 0 && ( {pubkeys.length === 0 && (