mirror of
https://gitlab.com/soapbox-pub/mkstack.git
synced 2025-08-27 21:19:23 +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 { useState, useEffect, useRef } from 'react';
|
||||||
import { useZaps } from '@/hooks/useZaps';
|
|
||||||
import type { WebLNProvider } from 'webln';
|
|
||||||
import type { ZapTarget } from '@/components/ZapButton';
|
|
||||||
import QRCode from 'qrcode';
|
|
||||||
import { Zap, Copy } from 'lucide-react';
|
import { Zap, Copy } from 'lucide-react';
|
||||||
import React, { useState, useEffect, useRef } from 'react';
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
@ -13,23 +8,42 @@ import {
|
|||||||
DialogFooter,
|
DialogFooter,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
} from '@/components/ui/dialog';
|
} from '@/components/ui/dialog';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
|
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 {
|
export interface ZapTarget {
|
||||||
open: boolean;
|
pubkey: string;
|
||||||
onOpenChange: (open: boolean) => void;
|
id: string;
|
||||||
|
relays?: string[];
|
||||||
|
dTag?: string;
|
||||||
|
naddr?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ZapDialogProps {
|
||||||
target: ZapTarget;
|
target: ZapTarget;
|
||||||
webln: WebLNProvider | null;
|
children?: React.ReactNode;
|
||||||
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const presetAmounts = [1, 50, 100, 250, 1000];
|
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 { 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 [amount, setAmount] = useState<number | string>(100);
|
||||||
const [comment, setComment] = useState<string>('');
|
const [comment, setComment] = useState<string>('');
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
@ -68,9 +82,31 @@ export function ZapModal({ open, onOpenChange, target, webln }: ZapModalProps) {
|
|||||||
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) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={onOpenChange} data-testid="zap-modal">
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
<DialogContent className="sm:max-w-[425px]">
|
<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>
|
<DialogHeader>
|
||||||
<DialogTitle>{invoice ? 'Manual Zap' : 'Send a Zap'}</DialogTitle>
|
<DialogTitle>{invoice ? 'Manual Zap' : 'Send a Zap'}</DialogTitle>
|
||||||
<DialogDescription asChild>
|
<DialogDescription asChild>
|
@ -6,7 +6,7 @@ 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/ZapButton';
|
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';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user