use event directly

This commit is contained in:
Chad Curtis 2025-07-13 04:09:32 +00:00
parent 7fdcb658b3
commit ec1a9777de
2 changed files with 24 additions and 35 deletions

View File

@ -17,20 +17,12 @@ import { useCurrentUser } from '@/hooks/useCurrentUser';
import { useAuthor } from '@/hooks/useAuthor'; import { useAuthor } from '@/hooks/useAuthor';
import { useToast } from '@/hooks/useToast'; import { useToast } from '@/hooks/useToast';
import { useZaps } from '@/hooks/useZaps'; import { useZaps } from '@/hooks/useZaps';
import { requestProvider } from 'webln';
import type { WebLNProvider } from 'webln'; import type { WebLNProvider } from 'webln';
import QRCode from 'qrcode'; import QRCode from 'qrcode';
import type { Event } from 'nostr-tools';
export interface ZapTarget {
pubkey: string;
id: string;
relays?: string[];
dTag?: string;
naddr?: string;
}
interface ZapDialogProps { interface ZapDialogProps {
target: ZapTarget; target: Event;
children?: React.ReactNode; children?: React.ReactNode;
className?: string; className?: string;
} }
@ -39,7 +31,7 @@ const presetAmounts = [1, 50, 100, 250, 1000];
export function ZapDialog({ target, children, className }: ZapDialogProps) { export function ZapDialog({ target, children, className }: ZapDialogProps) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [webln, setWebln] = useState<WebLNProvider | null>(null); const [webln, _setWebln] = useState<WebLNProvider | null>(null);
const { user } = useCurrentUser(); const { user } = useCurrentUser();
const { data: author } = useAuthor(target.pubkey); const { data: author } = useAuthor(target.pubkey);
const { toast } = useToast(); const { toast } = useToast();
@ -82,18 +74,6 @@ export function ZapDialog({ target, children, className }: ZapDialogProps) {
zap(finalAmount, comment); zap(finalAmount, comment);
}; };
const handleTriggerClick = async () => {
if (!webln) {
try {
const provider = await requestProvider();
setWebln(provider);
} catch (err) {
// Silently fail
console.error(err);
}
}
};
if (!user || user.pubkey === target.pubkey || !author?.metadata?.lud16) { if (!user || user.pubkey === target.pubkey || !author?.metadata?.lud16) {
return null; return null;
} }
@ -101,7 +81,7 @@ export function ZapDialog({ target, children, className }: ZapDialogProps) {
return ( return (
<Dialog open={open} onOpenChange={setOpen}> <Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild> <DialogTrigger asChild>
<Button size="sm" onClick={handleTriggerClick} className={className}> <Button size="sm" className={className}>
<Zap className={`h-4 w-4 ${children ? 'mr-2' : ''}`} /> <Zap className={`h-4 w-4 ${children ? 'mr-2' : ''}`} />
{children} {children}
</Button> </Button>

View File

@ -6,12 +6,12 @@ import { useAppContext } from '@/hooks/useAppContext';
import { useToast } from '@/hooks/useToast'; import { useToast } from '@/hooks/useToast';
import { nip57, nip19, Event } from 'nostr-tools'; import { nip57, nip19, Event } from 'nostr-tools';
import type { WebLNProvider } from 'webln'; import type { WebLNProvider } from 'webln';
import type { ZapTarget } from '@/components/ZapDialog';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { useNostr } from '@nostrify/react'; import { useNostr } from '@nostrify/react';
import type { NostrEvent, NostrFilter } from '@nostrify/nostrify'; import type { NostrEvent, NostrFilter } from '@nostrify/nostrify';
export function useZaps(target: ZapTarget, webln: WebLNProvider | null, onZapSuccess?: () => void) { export function useZaps(target: Event, webln: WebLNProvider | null, onZapSuccess?: () => void) {
const { nostr } = useNostr(); const { nostr } = useNostr();
const { toast } = useToast(); const { toast } = useToast();
const { user } = useCurrentUser(); const { user } = useCurrentUser();
@ -21,19 +21,28 @@ export function useZaps(target: ZapTarget, webln: WebLNProvider | null, onZapSuc
const [isZapping, setIsZapping] = useState(false); const [isZapping, setIsZapping] = useState(false);
const [invoice, setInvoice] = useState<string | null>(null); const [invoice, setInvoice] = useState<string | null>(null);
const queryKey = target.naddr ? `naddr:${target.naddr}` : `event:${target.id}`; const naddr =
target.kind >= 30000 && target.kind < 40000
? nip19.naddrEncode({
identifier: target.tags.find((t) => t[0] === 'd')?.[1] || '',
pubkey: target.pubkey,
kind: target.kind,
})
: undefined;
const queryKey = naddr ? `naddr:${naddr}` : `event:${target.id}`;
const { data: zaps, ...query } = useQuery<NostrEvent[], Error>({ const { data: zaps, ...query } = useQuery<NostrEvent[], Error>({
queryKey: ['zaps', queryKey], queryKey: ['zaps', queryKey],
queryFn: async (c) => { queryFn: async (c) => {
if (!target.id && !target.naddr) return []; if (!target.id && !naddr) return [];
const signal = AbortSignal.any([c.signal, AbortSignal.timeout(1500)]); const signal = AbortSignal.any([c.signal, AbortSignal.timeout(1500)]);
const filters: NostrFilter[] = []; const filters: NostrFilter[] = [];
if (target.naddr) { if (naddr) {
try { try {
const decoded = nip19.decode(target.naddr); const decoded = nip19.decode(naddr);
if (decoded.type === 'naddr') { if (decoded.type === 'naddr') {
const { kind, pubkey, identifier } = decoded.data; const { kind, pubkey, identifier } = decoded.data;
filters.push({ filters.push({
@ -42,7 +51,7 @@ export function useZaps(target: ZapTarget, webln: WebLNProvider | null, onZapSuc
}); });
} }
} catch (e) { } catch (e) {
console.error("Invalid naddr", target.naddr, e); console.error("Invalid naddr", naddr, e);
} }
} else { } else {
filters.push({ filters.push({
@ -56,7 +65,7 @@ export function useZaps(target: ZapTarget, webln: WebLNProvider | null, onZapSuc
const events = await nostr.query(filters, { signal }); const events = await nostr.query(filters, { signal });
return events; return events;
}, },
enabled: !!target.id || !!target.naddr, enabled: !!target.id || !!naddr,
}); });
const zap = async (amount: number, comment: string) => { const zap = async (amount: number, comment: string) => {
@ -119,9 +128,9 @@ export function useZaps(target: ZapTarget, webln: WebLNProvider | null, onZapSuc
comment: comment, comment: comment,
}); });
if (target.naddr) { if (naddr) {
const naddr = nip19.decode(target.naddr).data as nip19.AddressPointer; const decoded = nip19.decode(naddr).data as nip19.AddressPointer;
zapRequest.tags.push(["a", `${naddr.kind}:${naddr.pubkey}:${naddr.identifier}`]); zapRequest.tags.push(["a", `${decoded.kind}:${decoded.pubkey}:${decoded.identifier}`]);
zapRequest.tags = zapRequest.tags.filter(t => t[0] !== 'e'); zapRequest.tags = zapRequest.tags.filter(t => t[0] !== 'e');
} }