From 39a66cb4dddd0c7da0ed97f96695a28fc21f8f3d Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 29 Jan 2026 16:00:33 +0000 Subject: [PATCH] refactor(wallet): use useCopy hook for clipboard operations Replace manual clipboard state management with useCopy hook: - copyInvoice/invoiceCopied for generated invoice - copyRawTx/rawTxCopied for transaction JSON - copyNwc/nwcCopied for NWC connection string Benefits: - Cleaner code (removed manual setTimeout calls) - Automatic timeout cleanup on unmount - Consistent copy behavior across all clipboard operations https://claude.ai/code/session_01CnJgjFMvZHZWs2ujAiWAiQ --- src/components/WalletViewer.tsx | 47 +++++++++++---------------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/src/components/WalletViewer.tsx b/src/components/WalletViewer.tsx index da5f1a9..024ba83 100644 --- a/src/components/WalletViewer.tsx +++ b/src/components/WalletViewer.tsx @@ -27,6 +27,7 @@ import { } from "lucide-react"; import { Virtuoso } from "react-virtuoso"; import { useWallet } from "@/hooks/useWallet"; +import { useCopy } from "@/hooks/useCopy"; import { useGrimoire } from "@/core/state"; import { decode as decodeBolt11 } from "light-bolt11-decoder"; import { Button } from "@/components/ui/button"; @@ -442,7 +443,6 @@ export default function WalletViewer() { const [generatedPaymentHash, setGeneratedPaymentHash] = useState(""); const [invoiceQR, setInvoiceQR] = useState(""); const [generating, setGenerating] = useState(false); - const [copied, setCopied] = useState(false); const [checkingPayment, setCheckingPayment] = useState(false); // Transaction detail dialog state @@ -450,10 +450,11 @@ export default function WalletViewer() { useState(null); const [detailDialogOpen, setDetailDialogOpen] = useState(false); const [showRawTransaction, setShowRawTransaction] = useState(false); - const [copiedRawTx, setCopiedRawTx] = useState(false); - // Copy NWC connection string state - const [copiedNwc, setCopiedNwc] = useState(false); + // Copy hooks for clipboard operations + const { copy: copyInvoice, copied: invoiceCopied } = useCopy(2000); + const { copy: copyRawTx, copied: rawTxCopied } = useCopy(2000); + const { copy: copyNwc, copied: nwcCopied } = useCopy(2000); // Reset transaction state when wallet disconnects useEffect(() => { @@ -611,7 +612,7 @@ export default function WalletViewer() { } } - function copyNwcString() { + function handleCopyNwcString() { if (!state.nwcConnection) return; const { service, relays, secret, lud16 } = state.nwcConnection; @@ -621,12 +622,8 @@ export default function WalletViewer() { if (lud16) params.append("lud16", lud16); const nwcString = `nostr+walletconnect://${service}?${params.toString()}`; - - navigator.clipboard.writeText(nwcString).then(() => { - setCopiedNwc(true); - toast.success("Connection string copied"); - setTimeout(() => setCopiedNwc(false), 2000); - }); + copyNwc(nwcString); + toast.success("Connection string copied"); } async function handleConfirmSend() { @@ -869,16 +866,9 @@ export default function WalletViewer() { } } - async function handleCopyInvoice() { - try { - await navigator.clipboard.writeText(generatedInvoice); - setCopied(true); - toast.success("Invoice copied to clipboard"); - setTimeout(() => setCopied(false), 2000); - } catch (error) { - console.error("Failed to copy invoice:", error); - toast.error("Failed to copy to clipboard"); - } + function handleCopyInvoice() { + copyInvoice(generatedInvoice); + toast.success("Invoice copied to clipboard"); } function resetReceiveDialog() { @@ -887,7 +877,6 @@ export default function WalletViewer() { setInvoiceQR(""); setReceiveAmount(""); setReceiveDescription(""); - setCopied(false); } function handleDisconnect() { @@ -1119,11 +1108,11 @@ export default function WalletViewer() {