mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-04-07 03:18:02 +02:00
Use kind 10004 for communities list
This commit is contained in:
parent
c356916905
commit
90700ebbf8
5
.changeset/mean-keys-complain.md
Normal file
5
.changeset/mean-keys-complain.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": minor
|
||||
---
|
||||
|
||||
Use kind 10004 for communities list instead of kind 30001
|
@ -4,6 +4,7 @@ import { getMatchLink, getMatchNostrLink } from "../regexp";
|
||||
import { ReactionGroup } from "./reactions";
|
||||
import { parseCoordinate } from "./events";
|
||||
|
||||
/** @deprecated */
|
||||
export const SUBSCRIBED_COMMUNITIES_LIST_IDENTIFIER = "communities";
|
||||
export const COMMUNITY_DEFINITION_KIND = 34550;
|
||||
export const COMMUNITY_APPROVAL_KIND = 4550;
|
||||
@ -91,7 +92,7 @@ export function getCommunityPostVote(grouped: ReactionGroup[]) {
|
||||
return { up, down, vote };
|
||||
}
|
||||
|
||||
export function getEventCommunityPointer(event: NostrEvent){
|
||||
export function getEventCommunityPointer(event: NostrEvent) {
|
||||
const communityTag = event.tags.filter(isATag).find((t) => t[1].startsWith(COMMUNITY_DEFINITION_KIND + ":"));
|
||||
return communityTag ? parseCoordinate(communityTag[1], true) : null;
|
||||
}
|
||||
|
@ -5,15 +5,22 @@ import { AddressPointer } from "nostr-tools/lib/types/nip19";
|
||||
import { DraftNostrEvent, NostrEvent, PTag, isATag, isDTag, isETag, isPTag, isRTag } from "../../types/nostr-event";
|
||||
import { parseCoordinate } from "./events";
|
||||
|
||||
export const MUTE_LIST_KIND = 10000;
|
||||
export const PIN_LIST_KIND = 10001;
|
||||
export const BOOKMARK_LIST_KIND = 10003;
|
||||
export const COMMUNITIES_LIST_KIND = 10004;
|
||||
export const CHATS_LIST_KIND = 10005;
|
||||
|
||||
export const PEOPLE_LIST_KIND = 30000;
|
||||
export const NOTE_LIST_KIND = 30001;
|
||||
export const PIN_LIST_KIND = 10001;
|
||||
export const MUTE_LIST_KIND = 10000;
|
||||
export const BOOKMARK_LIST_SET_KIND = 30003;
|
||||
|
||||
export function getListName(event: NostrEvent) {
|
||||
if (event.kind === Kind.Contacts) return "Following";
|
||||
if (event.kind === PIN_LIST_KIND) return "Pins";
|
||||
if (event.kind === MUTE_LIST_KIND) return "Mute";
|
||||
if (event.kind === PIN_LIST_KIND) return "Pins";
|
||||
if (event.kind === BOOKMARK_LIST_KIND) return "Bookmarks";
|
||||
if (event.kind === COMMUNITIES_LIST_KIND) return "Communities";
|
||||
return (
|
||||
event.tags.find((t) => t[0] === "name")?.[1] ||
|
||||
event.tags.find((t) => t[0] === "title")?.[1] ||
|
||||
@ -31,7 +38,14 @@ export function isJunkList(event: NostrEvent) {
|
||||
return /^(chats\/([0-9a-f]{64}|null)|notifications)\/lastOpened$/.test(name);
|
||||
}
|
||||
export function isSpecialListKind(kind: number) {
|
||||
return kind === Kind.Contacts || kind === PIN_LIST_KIND || kind === MUTE_LIST_KIND;
|
||||
return (
|
||||
kind === Kind.Contacts ||
|
||||
kind === MUTE_LIST_KIND ||
|
||||
kind === PIN_LIST_KIND ||
|
||||
kind === BOOKMARK_LIST_KIND ||
|
||||
kind === COMMUNITIES_LIST_KIND ||
|
||||
kind === CHATS_LIST_KIND
|
||||
);
|
||||
}
|
||||
|
||||
export function cloneList(list: NostrEvent, keepCreatedAt = false): DraftNostrEvent {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { COMMUNITY_DEFINITION_KIND, SUBSCRIBED_COMMUNITIES_LIST_IDENTIFIER } from "../helpers/nostr/communities";
|
||||
import { NOTE_LIST_KIND, getParsedCordsFromList } from "../helpers/nostr/lists";
|
||||
import { COMMUNITIES_LIST_KIND, NOTE_LIST_KIND, getParsedCordsFromList } from "../helpers/nostr/lists";
|
||||
import { RequestOptions } from "../services/replaceable-event-requester";
|
||||
import useCurrentAccount from "./use-current-account";
|
||||
import useReplaceableEvent from "./use-replaceable-event";
|
||||
@ -8,7 +8,10 @@ export default function useJoinedCommunitiesList(pubkey?: string, opts?: Request
|
||||
const account = useCurrentAccount();
|
||||
const key = pubkey ?? account?.pubkey;
|
||||
|
||||
const list = useReplaceableEvent(
|
||||
// TODO: remove at some future date when apps have transitioned to using k:10004 for communities
|
||||
// https://github.com/nostr-protocol/nips/pull/880
|
||||
/** @deprecated */
|
||||
const oldList = useReplaceableEvent(
|
||||
key
|
||||
? {
|
||||
kind: NOTE_LIST_KIND,
|
||||
@ -19,11 +22,19 @@ export default function useJoinedCommunitiesList(pubkey?: string, opts?: Request
|
||||
[],
|
||||
opts,
|
||||
);
|
||||
const list = useReplaceableEvent(key ? { kind: COMMUNITIES_LIST_KIND, pubkey: key } : undefined, [], opts);
|
||||
|
||||
const pointers = list ? getParsedCordsFromList(list).filter((cord) => cord.kind === COMMUNITY_DEFINITION_KIND) : [];
|
||||
let useList = list || oldList;
|
||||
console.log(list, oldList);
|
||||
|
||||
return {
|
||||
list,
|
||||
pointers,
|
||||
};
|
||||
// if both exist, use the newest one
|
||||
if (list && oldList) {
|
||||
useList = list.created_at > oldList.created_at ? list : oldList;
|
||||
}
|
||||
|
||||
const pointers = useList
|
||||
? getParsedCordsFromList(useList).filter((cord) => cord.kind === COMMUNITY_DEFINITION_KIND)
|
||||
: [];
|
||||
|
||||
return { list: useList, pointers };
|
||||
}
|
||||
|
@ -1,13 +1,8 @@
|
||||
import { SUBSCRIBED_COMMUNITIES_LIST_IDENTIFIER } from "../helpers/nostr/communities";
|
||||
import { getEventCoordinate } from "../helpers/nostr/events";
|
||||
import { NOTE_LIST_KIND } from "../helpers/nostr/lists";
|
||||
import { COMMUNITIES_LIST_KIND } from "../helpers/nostr/lists";
|
||||
import { NostrEvent } from "../types/nostr-event";
|
||||
import useEventCount from "./use-event-count";
|
||||
|
||||
export default function useCountCommunityMembers(community: NostrEvent) {
|
||||
return useEventCount({
|
||||
"#a": [getEventCoordinate(community)],
|
||||
"#d": [SUBSCRIBED_COMMUNITIES_LIST_IDENTIFIER],
|
||||
kinds: [NOTE_LIST_KIND],
|
||||
});
|
||||
return useEventCount({ "#a": [getEventCoordinate(community)], kinds: [COMMUNITIES_LIST_KIND] });
|
||||
}
|
||||
|
@ -63,15 +63,9 @@ class EventExistsService {
|
||||
const request = new NostrRequest([nextRelay], 500);
|
||||
const limitFilter = Array.isArray(filter) ? filter.map((f) => ({ ...f, limit: 1 })) : { ...filter, limit: 1 };
|
||||
request.start(limitFilter);
|
||||
request.onEvent.subscribe(() => {
|
||||
sub.next(true);
|
||||
this.log(`Found event for`, filter);
|
||||
});
|
||||
request.onEvent.subscribe(() => sub.next(true));
|
||||
await request.onComplete;
|
||||
if (sub.value === undefined) {
|
||||
sub.next(false);
|
||||
this.log(`couldn't find event for`, filter);
|
||||
}
|
||||
if (sub.value === undefined) sub.next(false);
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ function CommunityCard({ community, ...props }: Omit<CardProps, "children"> & {
|
||||
<UserAvatarLink pubkey={community.pubkey} size="sm" />
|
||||
<Text>by</Text>
|
||||
<UserLink pubkey={community.pubkey} />
|
||||
{countMembers && (
|
||||
{countMembers !== undefined && countMembers > 0 && (
|
||||
<Tag variant="solid" ml="auto" alignSelf="flex-end" textShadow="none">
|
||||
<TagLeftIcon as={User01} boxSize={4} />
|
||||
<TagLabel>{readablizeSats(countMembers)}</TagLabel>
|
||||
|
@ -2,11 +2,11 @@ import { useCallback } from "react";
|
||||
import dayjs from "dayjs";
|
||||
import { Button, ButtonProps, useToast } from "@chakra-ui/react";
|
||||
|
||||
import { DraftNostrEvent, NostrEvent } from "../../../types/nostr-event";
|
||||
import { DraftNostrEvent, NostrEvent, isDTag } from "../../../types/nostr-event";
|
||||
import useJoinedCommunitiesList from "../../../hooks/use-communities-joined-list";
|
||||
import useCurrentAccount from "../../../hooks/use-current-account";
|
||||
import { SUBSCRIBED_COMMUNITIES_LIST_IDENTIFIER, getCommunityName } from "../../../helpers/nostr/communities";
|
||||
import { NOTE_LIST_KIND, listAddCoordinate, listRemoveCoordinate } from "../../../helpers/nostr/lists";
|
||||
import { getCommunityName } from "../../../helpers/nostr/communities";
|
||||
import { COMMUNITIES_LIST_KIND, listAddCoordinate, listRemoveCoordinate } from "../../../helpers/nostr/lists";
|
||||
import { getEventCoordinate } from "../../../helpers/nostr/events";
|
||||
import { useSigningContext } from "../../../providers/signing-provider";
|
||||
import NostrPublishAction from "../../../classes/nostr-publish-action";
|
||||
@ -27,11 +27,11 @@ export default function CommunityJoinButton({
|
||||
|
||||
const handleClick = useCallback(async () => {
|
||||
try {
|
||||
const favList = list || {
|
||||
kind: NOTE_LIST_KIND,
|
||||
const favList = {
|
||||
kind: COMMUNITIES_LIST_KIND,
|
||||
content: "",
|
||||
created_at: dayjs().unix(),
|
||||
tags: [["d", SUBSCRIBED_COMMUNITIES_LIST_IDENTIFIER]],
|
||||
tags: list?.tags.filter((t) => !isDTag(t)) ?? [],
|
||||
};
|
||||
|
||||
let draft: DraftNostrEvent;
|
||||
|
@ -10,7 +10,7 @@ import { ErrorBoundary } from "../../components/error-boundary";
|
||||
import { useReadRelayUrls } from "../../hooks/use-client-relays";
|
||||
import useSubjects from "../../hooks/use-subjects";
|
||||
import replaceableEventLoaderService from "../../services/replaceable-event-requester";
|
||||
import { NOTE_LIST_KIND, getCoordinatesFromList } from "../../helpers/nostr/lists";
|
||||
import { COMMUNITIES_LIST_KIND, NOTE_LIST_KIND, getCoordinatesFromList } from "../../helpers/nostr/lists";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { ChevronLeftIcon } from "../../components/icons";
|
||||
import { parseCoordinate } from "../../helpers/nostr/events";
|
||||
@ -19,17 +19,12 @@ import { AddressPointer } from "nostr-tools/lib/types/nip19";
|
||||
|
||||
export function useUsersJoinedCommunitiesLists(pubkeys: string[], additionalRelays: string[] = []) {
|
||||
const readRelays = useReadRelayUrls(additionalRelays);
|
||||
const muteListSubjects = useMemo(() => {
|
||||
const communityListsSubjects = useMemo(() => {
|
||||
return pubkeys.map((pubkey) =>
|
||||
replaceableEventLoaderService.requestEvent(
|
||||
readRelays,
|
||||
NOTE_LIST_KIND,
|
||||
pubkey,
|
||||
SUBSCRIBED_COMMUNITIES_LIST_IDENTIFIER,
|
||||
),
|
||||
replaceableEventLoaderService.requestEvent(readRelays, COMMUNITIES_LIST_KIND, pubkey),
|
||||
);
|
||||
}, [pubkeys]);
|
||||
return useSubjects(muteListSubjects);
|
||||
return useSubjects(communityListsSubjects);
|
||||
}
|
||||
|
||||
function CommunityCardWithMembers({ pointer, pubkeys }: { pointer: AddressPointer; pubkeys: string[] }) {
|
||||
|
@ -16,7 +16,7 @@ import useTimelineLoader from "../../../hooks/use-timeline-loader";
|
||||
import { useReadRelayUrls } from "../../../hooks/use-client-relays";
|
||||
import { SUBSCRIBED_COMMUNITIES_LIST_IDENTIFIER, getCommunityRelays } from "../../../helpers/nostr/communities";
|
||||
import { getEventCoordinate } from "../../../helpers/nostr/events";
|
||||
import { NOTE_LIST_KIND } from "../../../helpers/nostr/lists";
|
||||
import { COMMUNITIES_LIST_KIND, NOTE_LIST_KIND } from "../../../helpers/nostr/lists";
|
||||
import IntersectionObserverProvider from "../../../providers/intersection-observer";
|
||||
import useSubject from "../../../hooks/use-subject";
|
||||
import { useTimelineCurserIntersectionCallback } from "../../../hooks/use-timeline-cursor-intersection-callback";
|
||||
@ -40,15 +40,27 @@ function UserCard({ pubkey }: { pubkey: string }) {
|
||||
export default function ({ community, onClose, ...props }: Omit<ModalProps, "children"> & { community: NostrEvent }) {
|
||||
const communityCoordinate = getEventCoordinate(community);
|
||||
const readRelays = useReadRelayUrls(getCommunityRelays(community));
|
||||
const timeline = useTimelineLoader(`${communityCoordinate}-members`, readRelays, {
|
||||
"#a": [communityCoordinate],
|
||||
"#d": [SUBSCRIBED_COMMUNITIES_LIST_IDENTIFIER],
|
||||
kinds: [NOTE_LIST_KIND],
|
||||
});
|
||||
const timeline = useTimelineLoader(`${communityCoordinate}-members`, readRelays, [
|
||||
{
|
||||
"#a": [communityCoordinate],
|
||||
"#d": [SUBSCRIBED_COMMUNITIES_LIST_IDENTIFIER],
|
||||
kinds: [NOTE_LIST_KIND],
|
||||
},
|
||||
{ "#a": [communityCoordinate], kinds: [COMMUNITIES_LIST_KIND] },
|
||||
]);
|
||||
|
||||
const lists = useSubject(timeline.timeline);
|
||||
const callback = useTimelineCurserIntersectionCallback(timeline);
|
||||
|
||||
// TODO: remove at some future date when apps have transitioned to using k:10004 for communities
|
||||
// https://github.com/nostr-protocol/nips/pull/880
|
||||
const listsByPubkey: Record<string, NostrEvent> = {};
|
||||
for (const list of lists) {
|
||||
if (!listsByPubkey[list.pubkey] || listsByPubkey[list.pubkey].created_at < list.created_at) {
|
||||
listsByPubkey[list.pubkey] = list;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<IntersectionObserverProvider callback={callback}>
|
||||
<Modal onClose={onClose} size="4xl" {...props}>
|
||||
|
@ -87,7 +87,8 @@ function ListCardRender({
|
||||
hideCreator = false,
|
||||
...props
|
||||
}: Omit<CardProps, "children"> & { list: NostrEvent; hideCreator?: boolean }) {
|
||||
const link = isSpecialListKind(list.kind) ? createCoordinate(list.kind, list.pubkey) : getSharableEventAddress(list);
|
||||
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
|
||||
const ref = useRef<HTMLDivElement | null>(null);
|
||||
@ -118,9 +119,8 @@ function ListCardRender({
|
||||
<ListCardContent list={list} />
|
||||
</CardBody>
|
||||
<CardFooter p="2">
|
||||
<NoteZapButton event={list} size="sm" variant="ghost" />
|
||||
{/* TODO: reactions are tagging every user in list */}
|
||||
<SimpleLikeButton event={list} variant="ghost" size="sm" />
|
||||
{!isSpecialList && <NoteZapButton event={list} size="sm" variant="ghost" />}
|
||||
{!isSpecialList && <SimpleLikeButton event={list} variant="ghost" size="sm" />}
|
||||
<ButtonGroup size="sm" variant="ghost" ml="auto">
|
||||
<ListFavoriteButton list={list} />
|
||||
<ListMenu list={list} aria-label="list menu" />
|
||||
|
@ -9,7 +9,14 @@ import { getEventUID } from "../../helpers/nostr/events";
|
||||
import useUserLists from "../../hooks/use-user-lists";
|
||||
import NewListModal from "./components/new-list-modal";
|
||||
import { getSharableEventAddress } from "../../helpers/nip19";
|
||||
import { MUTE_LIST_KIND, NOTE_LIST_KIND, PEOPLE_LIST_KIND, PIN_LIST_KIND } from "../../helpers/nostr/lists";
|
||||
import {
|
||||
BOOKMARK_LIST_KIND,
|
||||
COMMUNITIES_LIST_KIND,
|
||||
MUTE_LIST_KIND,
|
||||
NOTE_LIST_KIND,
|
||||
PEOPLE_LIST_KIND,
|
||||
PIN_LIST_KIND,
|
||||
} from "../../helpers/nostr/lists";
|
||||
import useFavoriteLists from "../../hooks/use-favorite-lists";
|
||||
import VerticalPageLayout from "../../components/vertical-page-layout";
|
||||
|
||||
@ -51,6 +58,8 @@ function ListsPage() {
|
||||
<ListCard cord={`${Kind.Contacts}:${account.pubkey}`} hideCreator />
|
||||
<ListCard cord={`${MUTE_LIST_KIND}:${account.pubkey}`} hideCreator />
|
||||
<ListCard cord={`${PIN_LIST_KIND}:${account.pubkey}`} hideCreator />
|
||||
<ListCard cord={`${COMMUNITIES_LIST_KIND}:${account.pubkey}`} hideCreator />
|
||||
<ListCard cord={`${BOOKMARK_LIST_KIND}:${account.pubkey}`} hideCreator />
|
||||
</SimpleGrid>
|
||||
{peopleLists.length > 0 && (
|
||||
<>
|
||||
|
Loading…
x
Reference in New Issue
Block a user