mirror of
https://gitlab.com/soapbox-pub/mkstack.git
synced 2025-08-27 04:59:22 +00:00
use single zaps component
This commit is contained in:
parent
c37df875b9
commit
7fdcb658b3
@ -1,56 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { Zap } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useCurrentUser } from '@/hooks/useCurrentUser';
|
||||
import { requestProvider } from 'webln';
|
||||
import type { WebLNProvider } from 'webln';
|
||||
import { ZapModal } from './ZapModal';
|
||||
import { useAuthor } from '@/hooks/useAuthor';
|
||||
|
||||
export interface ZapTarget {
|
||||
pubkey: string;
|
||||
id: string;
|
||||
relays?: string[];
|
||||
dTag?: string;
|
||||
naddr?: string;
|
||||
}
|
||||
|
||||
interface ZapButtonProps {
|
||||
target: ZapTarget;
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function ZapButton({ target, children, className }: ZapButtonProps) {
|
||||
const [webln, setWebln] = useState<WebLNProvider | null>(null);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const { user } = useCurrentUser();
|
||||
const { data: author } = useAuthor(target.pubkey);
|
||||
|
||||
const handleOpenModal = async () => {
|
||||
if (!webln) {
|
||||
try {
|
||||
const provider = await requestProvider();
|
||||
setWebln(provider);
|
||||
} catch (err) {
|
||||
// Silently fail
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
|
||||
if (!user || user.pubkey === target.pubkey || !author?.metadata?.lud16) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button size="sm" onClick={handleOpenModal} className={className}>
|
||||
<Zap className={`h-4 w-4 ${children ? 'mr-2' : ''}`} />
|
||||
{children}
|
||||
</Button>
|
||||
{isModalOpen && <ZapModal open={isModalOpen} onOpenChange={setIsModalOpen} target={target} webln={webln} />}
|
||||
</>
|
||||
);
|
||||
}
|
@ -1,10 +1,5 @@
|
||||
import { useToast } from '@/hooks/useToast';
|
||||
import { useZaps } from '@/hooks/useZaps';
|
||||
import type { WebLNProvider } from 'webln';
|
||||
import type { ZapTarget } from '@/components/ZapButton';
|
||||
import QRCode from 'qrcode';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { Zap, Copy } from 'lucide-react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
@ -13,23 +8,42 @@ import {
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@/components/ui/dialog';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
|
||||
import { useCurrentUser } from '@/hooks/useCurrentUser';
|
||||
import { useAuthor } from '@/hooks/useAuthor';
|
||||
import { useToast } from '@/hooks/useToast';
|
||||
import { useZaps } from '@/hooks/useZaps';
|
||||
import { requestProvider } from 'webln';
|
||||
import type { WebLNProvider } from 'webln';
|
||||
import QRCode from 'qrcode';
|
||||
|
||||
interface ZapModalProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
export interface ZapTarget {
|
||||
pubkey: string;
|
||||
id: string;
|
||||
relays?: string[];
|
||||
dTag?: string;
|
||||
naddr?: string;
|
||||
}
|
||||
|
||||
interface ZapDialogProps {
|
||||
target: ZapTarget;
|
||||
webln: WebLNProvider | null;
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const presetAmounts = [1, 50, 100, 250, 1000];
|
||||
|
||||
export function ZapModal({ open, onOpenChange, target, webln }: ZapModalProps) {
|
||||
export function ZapDialog({ target, children, className }: ZapDialogProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [webln, setWebln] = useState<WebLNProvider | null>(null);
|
||||
const { user } = useCurrentUser();
|
||||
const { data: author } = useAuthor(target.pubkey);
|
||||
const { toast } = useToast();
|
||||
const { zap, isZapping, invoice, setInvoice } = useZaps(target, webln, () => onOpenChange(false));
|
||||
const { zap, isZapping, invoice, setInvoice } = useZaps(target, webln, () => setOpen(false));
|
||||
const [amount, setAmount] = useState<number | string>(100);
|
||||
const [comment, setComment] = useState<string>('');
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
@ -68,9 +82,31 @@ export function ZapModal({ open, onOpenChange, target, webln }: ZapModalProps) {
|
||||
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) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange} data-testid="zap-modal">
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button size="sm" onClick={handleTriggerClick} className={className}>
|
||||
<Zap className={`h-4 w-4 ${children ? 'mr-2' : ''}`} />
|
||||
{children}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[425px]" data-testid="zap-modal">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{invoice ? 'Manual Zap' : 'Send a Zap'}</DialogTitle>
|
||||
<DialogDescription asChild>
|
@ -6,7 +6,7 @@ import { useAppContext } from '@/hooks/useAppContext';
|
||||
import { useToast } from '@/hooks/useToast';
|
||||
import { nip57, nip19, Event } from 'nostr-tools';
|
||||
import type { WebLNProvider } from 'webln';
|
||||
import type { ZapTarget } from '@/components/ZapButton';
|
||||
import type { ZapTarget } from '@/components/ZapDialog';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useNostr } from '@nostrify/react';
|
||||
import type { NostrEvent, NostrFilter } from '@nostrify/nostrify';
|
||||
@ -28,7 +28,7 @@ export function useZaps(target: ZapTarget, webln: WebLNProvider | null, onZapSuc
|
||||
queryFn: async (c) => {
|
||||
if (!target.id && !target.naddr) return [];
|
||||
const signal = AbortSignal.any([c.signal, AbortSignal.timeout(1500)]);
|
||||
|
||||
|
||||
const filters: NostrFilter[] = [];
|
||||
|
||||
if (target.naddr) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user