import { useState } from 'react'; import { QrCode, Camera, Copy, Check, AlertCircle, Download, Upload, RefreshCw, } from 'lucide-react'; import { invoke } from '@tauri-apps/api/core'; interface PaymentRequest { address: string; amount?: number; label?: string; message?: string; } export default function QRScannerPage() { const [activeTab, setActiveTab] = useState<'generate' | 'scan'>('generate'); const [address, setAddress] = useState(''); const [amount, setAmount] = useState(''); const [label, setLabel] = useState(''); const [message, setMessage] = useState(''); const [qrCodeData, setQrCodeData] = useState(null); const [isGenerating, setIsGenerating] = useState(false); const [copiedUri, setCopiedUri] = useState(false); const [scannedData, setScannedData] = useState(null); const [error, setError] = useState(null); const generatePaymentUri = () => { let uri = `synor:${address}`; const params: string[] = []; if (amount) params.push(`amount=${amount}`); if (label) params.push(`label=${encodeURIComponent(label)}`); if (message) params.push(`message=${encodeURIComponent(message)}`); if (params.length > 0) { uri += '?' + params.join('&'); } return uri; }; const handleGenerateQR = async () => { if (!address) return; setIsGenerating(true); setError(null); try { const uri = generatePaymentUri(); const qrData = await invoke('qr_generate', { data: uri, size: 256, }); setQrCodeData(qrData); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to generate QR code'); } finally { setIsGenerating(false); } }; const handlePasteUri = async () => { try { const text = await navigator.clipboard.readText(); parsePaymentUri(text); } catch { setError('Failed to read clipboard'); } }; const parsePaymentUri = async (uri: string) => { setError(null); try { const parsed = await invoke('qr_parse_payment', { uri }); setScannedData(parsed); } catch (err) { setError(err instanceof Error ? err.message : 'Invalid payment URI'); } }; const copyUri = () => { const uri = generatePaymentUri(); navigator.clipboard.writeText(uri); setCopiedUri(true); setTimeout(() => setCopiedUri(false), 2000); }; const downloadQR = () => { if (!qrCodeData) return; const link = document.createElement('a'); link.download = `synor-payment-${Date.now()}.png`; link.href = qrCodeData; link.click(); }; return (
{/* Header */}

QR Code

Generate and scan payment QR codes

{/* Error Alert */} {error && (

{error}

)} {/* Tabs */}
{/* Generate Tab */} {activeTab === 'generate' && (
{/* Form */}

Payment Details

setAddress(e.target.value)} placeholder="synor1..." className="w-full px-4 py-2 bg-gray-800 border border-gray-700 rounded-lg text-white font-mono text-sm placeholder-gray-500 focus:outline-none focus:border-synor-500" />
setAmount(e.target.value)} placeholder="0.0" className="w-full px-4 py-2 bg-gray-800 border border-gray-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:border-synor-500" />
setLabel(e.target.value)} placeholder="e.g., Coffee Shop" className="w-full px-4 py-2 bg-gray-800 border border-gray-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:border-synor-500" />
setMessage(e.target.value)} placeholder="e.g., Payment for order #123" className="w-full px-4 py-2 bg-gray-800 border border-gray-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:border-synor-500" />
{/* QR Display */}

QR Code

{qrCodeData ? ( <>
Payment QR Code
) : (

Enter details to generate

)}
)} {/* Scan Tab */} {activeTab === 'scan' && (
{/* Input */}

Parse Payment URI

Paste a Synor payment URI to decode its contents. The URI format is:

synor:{'
'}?amount={''}&label={'