Batch kinds 0, 3, 10000 into single REQ in useFollowList
This commit is contained in:
@@ -3,6 +3,8 @@ import { useNostr } from '@nostrify/react';
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { useCurrentUser } from './useCurrentUser';
|
||||
import { useNostrPublish } from './useNostrPublish';
|
||||
import { parseAuthorEvent } from './useAuthor';
|
||||
import { parseMuteTags, setCachedMuteItems } from './useMuteList';
|
||||
import type { NostrEvent } from '@nostrify/nostrify';
|
||||
|
||||
/**
|
||||
@@ -57,7 +59,7 @@ function getCachedFollowList(pubkey: string): FollowListData | undefined {
|
||||
}
|
||||
|
||||
/** Persist follow pubkeys to localStorage. */
|
||||
function setCachedFollowList(pubkey: string, pubkeys: string[]): void {
|
||||
export function setCachedFollowList(pubkey: string, pubkeys: string[]): void {
|
||||
try {
|
||||
localStorage.setItem(FOLLOW_CACHE_KEY, JSON.stringify({ pubkey, pubkeys }));
|
||||
} catch {
|
||||
@@ -76,22 +78,54 @@ function setCachedFollowList(pubkey: string, pubkeys: string[]): void {
|
||||
export function useFollowList() {
|
||||
const { nostr } = useNostr();
|
||||
const { user } = useCurrentUser();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useQuery<FollowListData>({
|
||||
queryKey: ['follow-list', user?.pubkey ?? ''],
|
||||
queryFn: async ({ signal }) => {
|
||||
if (!user) return { event: null, pubkeys: [] };
|
||||
const [event] = await nostr.query(
|
||||
[{ kinds: [3], authors: [user.pubkey], limit: 1 }],
|
||||
{ signal: AbortSignal.any([signal, AbortSignal.timeout(3000)]) },
|
||||
|
||||
// Fetch profile, follow list, and mute list in one REQ so layout
|
||||
// components (useCurrentUser, useMuteList) resolve from cache
|
||||
// instead of each firing their own query.
|
||||
const events = await nostr.query(
|
||||
[{ kinds: [0, 3, 10000], authors: [user.pubkey], limit: 3 }],
|
||||
{ signal: AbortSignal.any([signal, AbortSignal.timeout(5000)]) },
|
||||
);
|
||||
if (!event) return { event: null, pubkeys: [] };
|
||||
const pubkeys = event.tags
|
||||
|
||||
const profile = events.find((e) => e.kind === 0);
|
||||
const followList = events.find((e) => e.kind === 3);
|
||||
const muteList = events.find((e) => e.kind === 10000);
|
||||
|
||||
// Seed author cache so useCurrentUser resolves instantly
|
||||
if (profile) {
|
||||
queryClient.setQueryData(['author', user.pubkey], parseAuthorEvent(profile));
|
||||
}
|
||||
|
||||
// Seed mute list cache so useMuteList resolves instantly
|
||||
if (muteList) {
|
||||
queryClient.setQueryData(['muteList', user.pubkey], muteList);
|
||||
if (muteList.content && user.signer.nip44) {
|
||||
try {
|
||||
const decrypted = await user.signer.nip44.decrypt(user.pubkey, muteList.content);
|
||||
const tags = JSON.parse(decrypted) as string[][];
|
||||
const items = parseMuteTags(tags);
|
||||
queryClient.setQueryData(['muteItems', muteList.id], items);
|
||||
setCachedMuteItems(user.pubkey, items);
|
||||
} catch {
|
||||
// Decryption failure is non-critical — useMuteList will retry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!followList) return { event: null, pubkeys: [] };
|
||||
|
||||
const pubkeys = followList.tags
|
||||
.filter(([name]) => name === 'p')
|
||||
.map(([, pk]) => pk);
|
||||
// Persist to localStorage for next visit
|
||||
setCachedFollowList(user.pubkey, pubkeys);
|
||||
return { event, pubkeys };
|
||||
return { event: followList, pubkeys };
|
||||
},
|
||||
enabled: !!user,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
|
||||
Reference in New Issue
Block a user