import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useNostr } from '@nostrify/react'; import { useNostrPublish } from '@/hooks/useNostrPublish'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useToast } from '@/hooks/useToast'; import { useTranslation } from '@/contexts/language'; import { onlyVerified } from '@/lib/verifyEvents'; import { addLocalMute, getLocalMutes } from '@/lib/localMutes'; import { MUTE_LIST_KIND } from '@/hooks/useMuteList'; /** * Mute a pubkey by republishing the viewer's NIP-51 kind-10000 mute list with * the target added, preserving any entries already there. Optimistically records * it locally and invalidates the content queries so the muted account drops out * of the lists immediately. */ export function useMuteUser() { const { nostr } = useNostr(); const { mutateAsync: publish } = useNostrPublish(); const { user } = useCurrentUser(); const { toast } = useToast(); const { t } = useTranslation(); const queryClient = useQueryClient(); return useMutation({ mutationFn: async (target: string) => { if (!user) throw new Error(t('walletUi.trust.loginToMute')); let existing: string[] = []; try { const signal = AbortSignal.any([AbortSignal.timeout(8000)]); const events = onlyVerified(await nostr.query( [{ kinds: [MUTE_LIST_KIND], authors: [user.pubkey], limit: 1 }], { signal }, )); existing = (events[0]?.tags ?? []) .filter(([name]) => name === 'p') .map(([, value]) => value) .filter(Boolean); } catch { // Relay unreachable — publish with what we know locally rather than fail. } const merged = new Set([...existing, ...getLocalMutes(), target]); await publish({ kind: MUTE_LIST_KIND, content: '', tags: [...merged].map((pk) => ['p', pk]), }); }, onSuccess: (_data, target) => { addLocalMute(target); queryClient.invalidateQueries({ queryKey: ['mute-list', user?.pubkey] }); // Refresh content so the muted account's items drop out of the lists. queryClient.invalidateQueries(); toast({ title: t('walletUi.trust.muted'), description: t('walletUi.trust.mutedDesc') }); }, onError: (error) => { toast({ title: t('walletUi.trust.muteFailed'), description: error instanceof Error ? error.message : undefined, variant: 'destructive', }); }, }); }